// Currently just handles top level and @:[...] constructs. static bool _findType(DynamicObject& in, const char* type, DynamicObject& out) { out->clear(); if(in->hasMember("@")) { DynamicObject& id = in["@"]; switch(id->getType()) { // top level object case String: { if(_isType(in, type)) { out->append(in); } break; } // top level is blank node case Array: { DynamicObjectIterator i = id.getIterator(); while(i->hasNext()) { DynamicObject& next = i->next(); if(_isType(next, type)) { out->append(next); } } break; } default: break; } } return true; }
bool JsonLd::normalize(DynamicObject& in, DynamicObject& out) { bool rval = true; // initialize output out->setType(Map); out->clear(); // create map to store subjects DynamicObject subjects; subjects->setType(Map); // initialize context DynamicObject ctx(NULL); if(in->hasMember("#")) { ctx = in["#"]; } // put all subjects in an array for single code path DynamicObject input; input->setType(Array); if(in->hasMember("@") && in["@"]->getType() == Array) { input.merge(in["@"], true); } else { input->append(in); } // do normalization int bnodeId = 0; DynamicObjectIterator i = input.getIterator(); while(rval && i->hasNext()) { rval = _normalize(ctx, i->next(), &subjects, NULL, bnodeId); } // build output if(rval) { // single subject if(subjects->length() == 1) { DynamicObject subject = subjects.first(); out.merge(subject, false); // FIXME: will need to check predicates for blank nodes as well... // and fail if they aren't embeds? // strip blank node '@' if(_isBlankNode(out)) { out->removeMember("@"); } } // multiple subjects else { DynamicObject& array = out["@"]; array->setType(Array); i = subjects.getIterator(); while(i->hasNext()) { DynamicObject& next = i->next(); // FIXME: will need to check predicates for blank nodes as well... // and fail if they aren't embeds? // strip blank node '@' if(_isBlankNode(next)) { next->removeMember("@"); } array->append(next); } } } return rval; }