Exemple #1
0
/**
 * Normalizes a value using the given context.
 *
 * @param ctx the context.
 * @param value the value to normalize.
 * @param type the expected RDF type, use RDF_TYPE_UNKNOWN if not known.
 * @param predicate an optional predicate for the value (used to look up
 *           type coercion info).
 * @param usedCtx a context to update if a value was used from "ctx".
 *
 * @return the normalized string.
 */
static string _normalizeValue(
   DynamicObject& ctx, DynamicObject value,
   RdfType type, const char* predicate, DynamicObject* usedCtx)
{
   string rval;

   // "@" or "a"/RDF_TYPE predicates have values that are IRIs or CURIEs
   if(predicate != NULL &&
      (strcmp(predicate, "@") == 0 || strcmp(predicate, "a") == 0 ||
       strcmp(predicate, RDF_TYPE_NORM) == 0))
   {
      type = RDF_TYPE_IRI;
   }

   // IRI "@" is already normalized
   if(type == RDF_TYPE_IRI && strcmp(value, "@") == 0)
   {
      rval.assign(value);
   }
   // IRI "a" is special rdf type
   else if(type == RDF_TYPE_IRI && strcmp(value, "a") == 0)
   {
      rval.assign(RDF_TYPE_NORM);
   }
   else
   {
      string datatype;

      // look for type coercion info
      if(type == RDF_TYPE_UNKNOWN && predicate != NULL &&
         !ctx.isNull() && ctx->hasMember("#types") &&
         ctx["#types"]->hasMember(predicate))
      {
         DynamicObject& tci = ctx["#types"][predicate];
         if(usedCtx != NULL)
         {
            (*usedCtx)["#types"][predicate] = tci.clone();
         }

         // handle specific type
         if(tci->getType() == String)
         {
            rval = value->getString();
            datatype = _normalizeValue(ctx, tci, RDF_TYPE_IRI, NULL, usedCtx);
            type = (strcmp(datatype.c_str(), XSD_ANY_URI_NORM) == 0) ?
               RDF_TYPE_IRI : RDF_TYPE_TYPED_LITERAL;
         }
         // handle type preferences in order
         else
         {
            DynamicObjectIterator ti = tci.getIterator();
            while(type == RDF_TYPE_UNKNOWN && ti->hasNext())
            {
               // FIXME: if value works w/type, set value, datatype, type
               //type = RDF_TYPE_TYPED_LITERAL;
            }
         }
      }
      // determine type from DynamicObjectType
      else if(type == RDF_TYPE_UNKNOWN && value->getType() != String)
      {
         type = RDF_TYPE_TYPED_LITERAL;
         rval = value->getString();

         // handle native xsd types
         if(value->isNumber())
         {
            datatype = value->isInteger() ? XSD_INTEGER : XSD_DOUBLE;
         }
         else if(value->getType() == Boolean)
         {
            datatype = XSD_BOOLEAN;
         }
         else
         {
            // FIXME: this should never happen?
            datatype = XSD_ANY_TYPE;
         }
      }
      else
      {
         // JSON-LD decode
         RdfType t = type;
         _decode(value, type, rval, datatype);
         if(type == RDF_TYPE_TYPED_LITERAL)
         {
            _expandCurie(ctx, datatype.c_str(), datatype, usedCtx);
         }

         // preserve expected type
         if(t != RDF_TYPE_UNKNOWN)
         {
            type = t;
         }
      }

      // expand CURIE
      if(type == RDF_TYPE_IRI)
      {
         _expandCurie(ctx, rval.c_str(), rval, usedCtx);
      }

      // JSON-LD encode
      rval = _encode(type, rval.c_str(), datatype.c_str());
   }

   return rval;
}