tasks/rdfstore/index.js
function(parent, parentProperty, value, subjects)
{
   var flattened = null;
   
   if(value === null)
   {
      // drop null values
   }
   else if(value.constructor === Array)
   {
      // list of objects or a disjoint graph
      for(var i in value)
      {
         _flatten(parent, parentProperty, value[i], subjects);
      }
   }
   else if(value.constructor === Object)
   {
      // already-expanded value or special-case reference-only @type
      if('@literal' in value || parentProperty === '@type')
      {
         flattened = _clone(value);
      }
      // graph literal/disjoint graph
      else if(value['@id'].constructor === Array)
      {
         // cannot flatten embedded graph literals
         if(parent !== null)
         {
            throw {
               message: 'Embedded graph literals cannot be flattened.'
            };
         }
         
         // top-level graph literal
         for(var idx in value['@id'])
         {
            _flatten(parent, parentProperty, value['@id'][idx], subjects);
         }
      }
      // regular subject
      else
      {
         // create or fetch existing subject
         var subject;
         if(value['@id'] in subjects)
         {
            // FIXME: '@id' might be a graph literal (as {})
            subject = subjects[value['@id']];
         }
         else
         {
            // FIXME: '@id' might be a graph literal (as {})
            subject = {'@id': value['@id']};
            subjects[value['@id']] = subject;
         }
         flattened = {'@id': subject['@id']};

         // flatten embeds
         for(var key in value)
         {
            var v = value[key];
            
            // drop null values, skip @id (it is already set above)
            if(v !== null && key !== '@id')
            {
               if(key in subject)
               {
                  if(subject[key].constructor !== Array)
                  {
                     subject[key] = [subject[key]];
                  }
               }
               else
               {
                  subject[key] = [];
               }
               
               _flatten(subject[key], key, v, subjects);
               if(subject[key].length === 1)
               {
                  // convert subject[key] to object if it has only 1
                  subject[key] = subject[key][0];
               }
            }
         }
      }
   }
   // string value
   else
   {
      flattened = value;
   }

   // add flattened value to parent
   if(flattened !== null && parent !== null)
   {
      if(parent.constructor === Array)
      {
         // do not add duplicate IRIs for the same property
         var duplicate = false;
         if(flattened.constructor === Object && '@id' in flattened)
         {
            duplicate = (parent.filter(function(e)
            {
               return (e.constructor === Object && '@id' in e &&
                  e['@id'] === flattened['@id']);
            }).length > 0);
         }
         if(!duplicate)
         {
            parent.push(flattened);
         }
      }
      else
      {
         parent[parentProperty] = flattened;
      }
   }
}
function(parent, parentProperty, value, subjects)
{
   var flattened = null;
   
   if(value === null)
   {
      // drop null values
   }
   else if(value.constructor === Array)
   {
      // list of objects or a disjoint graph
      for(var i in value)
      {
         _flatten(parent, parentProperty, value[i], subjects);
      }
   }
   else if(value.constructor === Object)
   {
      // already-expanded value or special-case reference-only @type
      if('@literal' in value || parentProperty === '@type')
      {
         flattened = _clone(value);
      }
      // graph literal/disjoint graph
      else if(value['@id'].constructor === Array)
      {
         // cannot flatten embedded graph literals
         if(parent !== null)
         {
            throw {
               message: 'Embedded graph literals cannot be flattened.'
            };
         }
         
         // top-level graph literal
         for(var idx in value['@id'])
         {
            _flatten(parent, parentProperty, value['@id'][idx], subjects);
         }
      }
      // regular subject
      else
      {
         // create or fetch existing subject
         var subject;
         if(value['@id'] in subjects)
         {
            // FIXME: '@id' might be a graph literal (as {})
            subject = subjects[value['@id']];
         }
         else
         {
            // FIXME: '@id' might be a graph literal (as {})
            subject = {'@id': value['@id']};
            subjects[value['@id']] = subject;
         }
         flattened = {'@id': subject['@id']};

         // flatten embeds
         for(var key in value)
         {
            var v = value[key];
            
            // drop null values, skip @id (it is already set above)
            if(v !== null && key !== '@id')
            {
               if(key in subject)
               {
                  if(subject[key].constructor !== Array)
                  {
                     subject[key] = [subject[key]];
                  }
               }
               else
               {
                  subject[key] = [];
               }
               
               _flatten(subject[key], key, v, subjects);
               if(subject[key].length === 1)
               {
                  // convert subject[key] to object if it has only 1
                  subject[key] = subject[key][0];
               }
            }
         }
      }
   }
   // string value
   else
   {
      flattened = value;
   }

   // add flattened value to parent
   if(flattened !== null && parent !== null)
   {
      if(parent.constructor === Array)
      {
         // do not add duplicate IRIs for the same property
         var duplicate = false;
         if(flattened.constructor === Object && '@id' in flattened)
         {
            duplicate = (parent.filter(function(e)
            {
               return (e.constructor === Object && '@id' in e &&
                  e['@id'] === flattened['@id']);
            }).length > 0);
         }
         if(!duplicate)
         {
            parent.push(flattened);
         }
      }
      else
      {
         parent[parentProperty] = flattened;
      }
   }
}
function ( parent , parentProperty , value , subjects ) { var flattened = null ; if ( value === null ) { // drop null values } else if ( value . constructor === Array ) { // list of objects or a disjoint graph for ( var i in value ) { _flatten ( parent , parentProperty , value [ i ] , subjects ) ; } } else if ( value . constructor === Object ) { // already-expanded value or special-case reference-only @type if ( '@literal' in value || parentProperty === '@type' ) { flattened = _clone ( value ) ; } // graph literal/disjoint graph else if ( value [ '@id' ] . constructor === Array ) { // cannot flatten embedded graph literals if ( parent !== null ) { throw { message : 'Embedded graph literals cannot be flattened.' } ; } // top-level graph literal for ( var idx in value [ '@id' ] ) { _flatten ( parent , parentProperty , value [ '@id' ] [ idx ] , subjects ) ; } } // regular subject else { // create or fetch existing subject var subject ; if ( value [ '@id' ] in subjects ) { // FIXME: '@id' might be a graph literal (as {}) subject = subjects [ value [ '@id' ] ] ; } else { // FIXME: '@id' might be a graph literal (as {}) subject = { '@id' : value [ '@id' ] } ; subjects [ value [ '@id' ] ] = subject ; } flattened = { '@id' : subject [ '@id' ] } ; // flatten embeds for ( var key in value ) { var v = value [ key ] ; // drop null values, skip @id (it is already set above) if ( v !== null && key !== '@id' ) { if ( key in subject ) { if ( subject [ key ] . constructor !== Array ) { subject [ key ] = [ subject [ key ] ] ; } } else { subject [ key ] = [ ] ; } _flatten ( subject [ key ] , key , v , subjects ) ; if ( subject [ key ] . length === 1 ) { // convert subject[key] to object if it has only 1 subject [ key ] = subject [ key ] [ 0 ] ; } } } } } // string value else { flattened = value ; } // add flattened value to parent if ( flattened !== null && parent !== null ) { if ( parent . constructor === Array ) { // do not add duplicate IRIs for the same property var duplicate = false ; if ( flattened . constructor === Object && '@id' in flattened ) { duplicate = ( parent . filter ( function ( e ) { return ( e . constructor === Object && '@id' in e && e [ '@id' ] === flattened [ '@id' ] ) ; } ) . length > 0 ) ; } if ( ! duplicate ) { parent . push ( flattened ) ; } } else { parent [ parentProperty ] = flattened ; } } }
Flattens the given value into a map of unique subjects. It is assumed that
all blank nodes have been uniquely named before this call. Array values for
properties will be sorted.

@param parent the value's parent, NULL for none.
@param parentProperty the property relating the value to the parent.
@param value the value to flatten.
@param subjects the map of subjects to write to.
Flattens the given value into a map of unique subjects . It is assumed that all blank nodes have been uniquely named before this call . Array values for properties will be sorted .