/** * 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; }