lib/annotations.js
function createAnnotation(desc) {
  utils.check(['type', 'hasTarget', 'annotatedBy'], desc);

  var anno = { type: desc.type, hasTarget: desc.hasTarget, annotatedAt : desc.annotatedAt || new Date().toISOString(), annotatedBy : desc.annotatedBy, state: desc.state || utils.states.annotations.unvalidated};

 // used to create a hierarchical position
 // FIXME reconcile roots / position
  var position = desc.roots || [], flattened = desc.type + unitSep;
  anno.roots = desc.roots || [];
  if (desc.type === 'quote') {
    utils.check(['ranges', 'quote'], desc);
    if (!desc.ranges || desc.ranges.length < 1) {
      utils.checkError(desc, 'missing ranges');
    }
    anno.quote = desc.quote;
    anno.ranges = desc.ranges;
    position.push(anno.quote);
    flattened += position.join(unitSep);
  } else if (desc.type === 'category') {
    utils.check(['category'], desc);
    anno.category = Array.isArray(desc.category) ? desc.category : [desc.category];
    position = position.concat(anno.category);
    flattened += position.join(unitSep);
  } else if (desc.type === 'value' || desc.type === 'valueQuote') {
    utils.check(['key', 'value'], desc);
    if (desc.type === 'valueQuote') {
      utils.check(['ranges'], desc);
      anno.ranges = desc.ranges;
    }
    anno.key = desc.key;
    anno.value = desc.value;
    position.push(desc.key);
    flattened += position.join(unitSep) + unitSep + desc.value;

// add data types
    if (desc.isA) {
      try {
        anno.isA = desc.isA;
        anno.typed = {};
        anno.typed[desc.isA] = dataTypes[desc.isA](desc.value);
      } catch (e) {
        anno.typed.failure = e;
        GLOBAL.warn('isA failed', e, desc);
      }
    }
  } else {
    throw new Error('unknown type ' + desc.type);
  }
  anno.position = position;
  anno.flattened = flattened;
  if (anno.attributes) {
    anno.attributes = desc.attributes; // additional attributes
  }
  return anno;
}
function createAnnotation(desc) {
  utils.check(['type', 'hasTarget', 'annotatedBy'], desc);

  var anno = { type: desc.type, hasTarget: desc.hasTarget, annotatedAt : desc.annotatedAt || new Date().toISOString(), annotatedBy : desc.annotatedBy, state: desc.state || utils.states.annotations.unvalidated};

 // used to create a hierarchical position
 // FIXME reconcile roots / position
  var position = desc.roots || [], flattened = desc.type + unitSep;
  anno.roots = desc.roots || [];
  if (desc.type === 'quote') {
    utils.check(['ranges', 'quote'], desc);
    if (!desc.ranges || desc.ranges.length < 1) {
      utils.checkError(desc, 'missing ranges');
    }
    anno.quote = desc.quote;
    anno.ranges = desc.ranges;
    position.push(anno.quote);
    flattened += position.join(unitSep);
  } else if (desc.type === 'category') {
    utils.check(['category'], desc);
    anno.category = Array.isArray(desc.category) ? desc.category : [desc.category];
    position = position.concat(anno.category);
    flattened += position.join(unitSep);
  } else if (desc.type === 'value' || desc.type === 'valueQuote') {
    utils.check(['key', 'value'], desc);
    if (desc.type === 'valueQuote') {
      utils.check(['ranges'], desc);
      anno.ranges = desc.ranges;
    }
    anno.key = desc.key;
    anno.value = desc.value;
    position.push(desc.key);
    flattened += position.join(unitSep) + unitSep + desc.value;

// add data types
    if (desc.isA) {
      try {
        anno.isA = desc.isA;
        anno.typed = {};
        anno.typed[desc.isA] = dataTypes[desc.isA](desc.value);
      } catch (e) {
        anno.typed.failure = e;
        GLOBAL.warn('isA failed', e, desc);
      }
    }
  } else {
    throw new Error('unknown type ' + desc.type);
  }
  anno.position = position;
  anno.flattened = flattened;
  if (anno.attributes) {
    anno.attributes = desc.attributes; // additional attributes
  }
  return anno;
}
function createAnnotation ( desc ) { utils . check ( [ 'type' , 'hasTarget' , 'annotatedBy' ] , desc ) ; var anno = { type : desc . type , hasTarget : desc . hasTarget , annotatedAt : desc . annotatedAt || new Date ( ) . toISOString ( ) , annotatedBy : desc . annotatedBy , state : desc . state || utils . states . annotations . unvalidated } ; // used to create a hierarchical position // FIXME reconcile roots / position var position = desc . roots || [ ] , flattened = desc . type + unitSep ; anno . roots = desc . roots || [ ] ; if ( desc . type === 'quote' ) { utils . check ( [ 'ranges' , 'quote' ] , desc ) ; if ( ! desc . ranges || desc . ranges . length < 1 ) { utils . checkError ( desc , 'missing ranges' ) ; } anno . quote = desc . quote ; anno . ranges = desc . ranges ; position . push ( anno . quote ) ; flattened += position . join ( unitSep ) ; } else if ( desc . type === 'category' ) { utils . check ( [ 'category' ] , desc ) ; anno . category = Array . isArray ( desc . category ) ? desc . category : [ desc . category ] ; position = position . concat ( anno . category ) ; flattened += position . join ( unitSep ) ; } else if ( desc . type === 'value' || desc . type === 'valueQuote' ) { utils . check ( [ 'key' , 'value' ] , desc ) ; if ( desc . type === 'valueQuote' ) { utils . check ( [ 'ranges' ] , desc ) ; anno . ranges = desc . ranges ; } anno . key = desc . key ; anno . value = desc . value ; position . push ( desc . key ) ; flattened += position . join ( unitSep ) + unitSep + desc . value ; // add data types if ( desc . isA ) { try { anno . isA = desc . isA ; anno . typed = { } ; anno . typed [ desc . isA ] = dataTypes [ desc . isA ] ( desc . value ) ; } catch ( e ) { anno . typed . failure = e ; GLOBAL . warn ( 'isA failed' , e , desc ) ; } } } else { throw new Error ( 'unknown type ' + desc . type ) ; } anno . position = position ; anno . flattened = flattened ; if ( anno . attributes ) { anno . attributes = desc . attributes ; // additional attributes } return anno ; }
validates and creates an annotation. pass .roots to insert into hierarchy
validates and creates an annotation . pass . roots to insert into hierarchy