1package gojsonld 2 3// /** 4// * Compacts the given input using the context according to the steps in the 5// * <a href="http://www.w3.org/TR/json-ld-api/#compaction-algorithm"> 6// * Compaction algorithm</a>. 7// * 8// * @param input 9// * The input JSON-LD object. 10// * @param context 11// * The context object to use for the compaction algorithm. 12// * @param opts 13// * The {@link JsonLdOptions} that are to be sent to the 14// * compaction algorithm. 15// * @return The compacted JSON-LD document 16// * @throws JsonLdError 17// * If there is an error while compacting. 18// */ 19// public static Map<String, Object> compact(Object input, Object context, JsonLdOptions opts) 20// throws JsonLdError { 21// // 1) 22// // TODO: look into java futures/promises 23 24// // 2-6) NOTE: these are all the same steps as in expand 25// final Object expanded = expand(input, opts); 26// // 7) 27// if (context instanceof Map && ((Map<String, Object>) context).containsKey("@context")) { 28// context = ((Map<String, Object>) context).get("@context"); 29// } 30// Context activeCtx = new Context(opts); 31// activeCtx = activeCtx.parse(context); 32// // 8) 33// Object compacted = new JsonLdApi(opts).compact(activeCtx, null, expanded, 34// opts.getCompactArrays()); 35 36// // final step of Compaction Algorithm 37// // TODO: SPEC: the result result is a NON EMPTY array, 38// if (compacted instanceof List) { 39// if (((List<Object>) compacted).isEmpty()) { 40// compacted = new LinkedHashMap<String, Object>(); 41// } else { 42// final Map<String, Object> tmp = new LinkedHashMap<String, Object>(); 43// // TODO: SPEC: doesn't specify to use vocab = true here 44// tmp.put(activeCtx.compactIri("@graph", true), compacted); 45// compacted = tmp; 46// } 47// } 48// if (compacted != null && context != null) { 49// // TODO: figure out if we can make "@context" appear at the start of 50// // the keySet 51// if ((context instanceof Map && !((Map<String, Object>) context).isEmpty()) 52// || (context instanceof List && !((List<Object>) context).isEmpty())) { 53// ((Map<String, Object>) compacted).put("@context", context); 54// } 55// } 56 57// // 9) 58// return (Map<String, Object>) compacted; 59// } 60 61// /** 62// * Expands the given input according to the steps in the <a 63// * href="http://www.w3.org/TR/json-ld-api/#expansion-algorithm">Expansion 64// * algorithm</a>. 65// * 66// * @param input 67// * The input JSON-LD object. 68// * @param opts 69// * The {@link JsonLdOptions} that are to be sent to the expansion 70// * algorithm. 71// * @return The expanded JSON-LD document 72// * @throws JsonLdError 73// * If there is an error while expanding. 74// */ 75// public static List<Object> expand(Object input, JsonLdOptions opts) throws JsonLdError { 76// // 1) 77// // TODO: look into java futures/promises 78 79// // 2) TODO: better verification of DOMString IRI 80// if (input instanceof String && ((String) input).contains(":")) { 81// try { 82// final RemoteDocument tmp = opts.getDocumentLoader().loadDocument((String) input); 83// input = tmp.document; 84// // TODO: figure out how to deal with remote context 85// } catch (final Exception e) { 86// throw new JsonLdError(Error.LOADING_DOCUMENT_FAILED, e.getMessage()); 87// } 88// // if set the base in options should override the base iri in the 89// // active context 90// // thus only set this as the base iri if it's not already set in 91// // options 92// if (opts.getBase() == null) { 93// opts.setBase((String) input); 94// } 95// } 96 97// // 3) 98// Context activeCtx = new Context(opts); 99// // 4) 100// if (opts.getExpandContext() != null) { 101// Object exCtx = opts.getExpandContext(); 102// if (exCtx instanceof Map && ((Map<String, Object>) exCtx).containsKey("@context")) { 103// exCtx = ((Map<String, Object>) exCtx).get("@context"); 104// } 105// activeCtx = activeCtx.parse(exCtx); 106// } 107 108// // 5) 109// // TODO: add support for getting a context from HTTP when content-type 110// // is set to a jsonld compatable format 111 112// // 6) 113// Object expanded = new JsonLdApi(opts).expand(activeCtx, input); 114 115// // final step of Expansion Algorithm 116// if (expanded instanceof Map && ((Map) expanded).containsKey("@graph") 117// && ((Map) expanded).size() == 1) { 118// expanded = ((Map<String, Object>) expanded).get("@graph"); 119// } else if (expanded == null) { 120// expanded = new ArrayList<Object>(); 121// } 122 123// // normalize to an array 124// if (!(expanded instanceof List)) { 125// final List<Object> tmp = new ArrayList<Object>(); 126// tmp.add(expanded); 127// expanded = tmp; 128// } 129// return (List<Object>) expanded; 130// } 131 132// /** 133// * Expands the given input according to the steps in the <a 134// * href="http://www.w3.org/TR/json-ld-api/#expansion-algorithm">Expansion 135// * algorithm</a>, using the default {@link JsonLdOptions}. 136// * 137// * @param input 138// * The input JSON-LD object. 139// * @return The expanded JSON-LD document 140// * @throws JsonLdError 141// * If there is an error while expanding. 142// */ 143// public static List<Object> expand(Object input) throws JsonLdError { 144// return expand(input, new JsonLdOptions("")); 145// } 146 147// public static Object flatten(Object input, Object context, JsonLdOptions opts) 148// throws JsonLdError { 149// // 2-6) NOTE: these are all the same steps as in expand 150// final Object expanded = expand(input, opts); 151// // 7) 152// if (context instanceof Map && ((Map<String, Object>) context).containsKey("@context")) { 153// context = ((Map<String, Object>) context).get("@context"); 154// } 155// // 8) NOTE: blank node generation variables are members of JsonLdApi 156// // 9) NOTE: the next block is the Flattening Algorithm described in 157// // http://json-ld.org/spec/latest/json-ld-api/#flattening-algorithm 158 159// // 1) 160// final Map<String, Object> nodeMap = new LinkedHashMap<String, Object>(); 161// nodeMap.put("@default", new LinkedHashMap<String, Object>()); 162// // 2) 163// new JsonLdApi(opts).generateNodeMap(expanded, nodeMap); 164// // 3) 165// final Map<String, Object> defaultGraph = (Map<String, Object>) nodeMap.remove("@default"); 166// // 4) 167// for (final String graphName : nodeMap.keySet()) { 168// final Map<String, Object> graph = (Map<String, Object>) nodeMap.get(graphName); 169// // 4.1+4.2) 170// Map<String, Object> entry; 171// if (!defaultGraph.containsKey(graphName)) { 172// entry = new LinkedHashMap<String, Object>(); 173// entry.put("@id", graphName); 174// defaultGraph.put(graphName, entry); 175// } else { 176// entry = (Map<String, Object>) defaultGraph.get(graphName); 177// } 178// // 4.3) 179// // TODO: SPEC doesn't specify that this should only be added if it 180// // doesn't exists 181// if (!entry.containsKey("@graph")) { 182// entry.put("@graph", new ArrayList<Object>()); 183// } 184// final List<String> keys = new ArrayList<String>(graph.keySet()); 185// Collections.sort(keys); 186// for (final String id : keys) { 187// final Map<String, Object> node = (Map<String, Object>) graph.get(id); 188// if (!(node.containsKey("@id") && node.size() == 1)) { 189// ((List<Object>) entry.get("@graph")).add(node); 190// } 191// } 192 193// } 194// // 5) 195// final List<Object> flattened = new ArrayList<Object>(); 196// // 6) 197// final List<String> keys = new ArrayList<String>(defaultGraph.keySet()); 198// Collections.sort(keys); 199// for (final String id : keys) { 200// final Map<String, Object> node = (Map<String, Object>) defaultGraph.get(id); 201// if (!(node.containsKey("@id") && node.size() == 1)) { 202// flattened.add(node); 203// } 204// } 205// // 8) 206// if (context != null && !flattened.isEmpty()) { 207// Context activeCtx = new Context(opts); 208// activeCtx = activeCtx.parse(context); 209// // TODO: only instantiate one jsonldapi 210// Object compacted = new JsonLdApi(opts).compact(activeCtx, null, flattened, 211// opts.getCompactArrays()); 212// if (!(compacted instanceof List)) { 213// final List<Object> tmp = new ArrayList<Object>(); 214// tmp.add(compacted); 215// compacted = tmp; 216// } 217// final String alias = activeCtx.compactIri("@graph"); 218// final Map<String, Object> rval = activeCtx.serialize(); 219// rval.put(alias, compacted); 220// return rval; 221// } 222// return flattened; 223// } 224 225// /** 226// * Flattens the given input and compacts it using the passed context 227// * according to the steps in the <a 228// * href="http://www.w3.org/TR/json-ld-api/#flattening-algorithm">Flattening 229// * algorithm</a>: 230// * 231// * @param input 232// * The input JSON-LD object. 233// * @param opts 234// * The {@link JsonLdOptions} that are to be sent to the 235// * flattening algorithm. 236// * @return The flattened JSON-LD document 237// * @throws JsonLdError 238// * If there is an error while flattening. 239// */ 240// public static Object flatten(Object input, JsonLdOptions opts) throws JsonLdError { 241// return flatten(input, null, opts); 242// } 243 244// /** 245// * Frames the given input using the frame according to the steps in the <a 246// * href="http://json-ld.org/spec/latest/json-ld-framing/#framing-algorithm"> 247// * Framing Algorithm</a>. 248// * 249// * @param input 250// * The input JSON-LD object. 251// * @param frame 252// * The frame to use when re-arranging the data of input; either 253// * in the form of an JSON object or as IRI. 254// * @param opts 255// * The {@link JsonLdOptions} that are to be sent to the framing 256// * algorithm. 257// * @return The framed JSON-LD document 258// * @throws JsonLdError 259// * If there is an error while framing. 260// */ 261// public static Map<String, Object> frame(Object input, Object frame, JsonLdOptions opts) 262// throws JsonLdError { 263 264// if (frame instanceof Map) { 265// frame = JsonLdUtils.clone(frame); 266// } 267// // TODO string/IO input 268 269// final Object expandedInput = expand(input, opts); 270// final List<Object> expandedFrame = expand(frame, opts); 271 272// final JsonLdApi api = new JsonLdApi(expandedInput, opts); 273// final List<Object> framed = api.frame(expandedInput, expandedFrame); 274// final Context activeCtx = api.context.parse(((Map<String, Object>) frame).get("@context")); 275 276// Object compacted = api.compact(activeCtx, null, framed); 277// if (!(compacted instanceof List)) { 278// final List<Object> tmp = new ArrayList<Object>(); 279// tmp.add(compacted); 280// compacted = tmp; 281// } 282// final String alias = activeCtx.compactIri("@graph"); 283// final Map<String, Object> rval = activeCtx.serialize(); 284// rval.put(alias, compacted); 285// JsonLdUtils.removePreserve(activeCtx, rval, opts); 286// return rval; 287// } 288 289// /** 290// * A registry for RDF Parsers (in this case, JSONLDSerializers) used by 291// * fromRDF if no specific serializer is specified and options.format is set. 292// * 293// * TODO: this would fit better in the document loader class 294// */ 295// private static Map<String, RDFParser> rdfParsers = new LinkedHashMap<String, RDFParser>() { 296// { 297// // automatically register nquad serializer 298// put("application/nquads", new NQuadRDFParser()); 299// put("text/turtle", new TurtleRDFParser()); 300// } 301// }; 302 303// public static void registerRDFParser(String format, RDFParser parser) { 304// rdfParsers.put(format, parser); 305// } 306 307// public static void removeRDFParser(String format) { 308// rdfParsers.remove(format); 309// } 310 311// /** 312// * Converts an RDF dataset to JSON-LD. 313// * 314// * @param dataset 315// * a serialized string of RDF in a format specified by the format 316// * option or an RDF dataset to convert. 317// * @param options 318// * the options to use: [format] the format if input is not an 319// * array: 'application/nquads' for N-Quads (default). 320// * [useRdfType] true to use rdf:type, false to use @type 321// * (default: false). [useNativeTypes] true to convert XSD types 322// * into native types (boolean, integer, double), false not to 323// * (default: true). 324// * @return A JSON-LD object. 325// * @throws JsonLdError 326// * If there is an error converting the dataset to JSON-LD. 327// */ 328// public static Object fromRDF(Object dataset, JsonLdOptions options) throws JsonLdError { 329// // handle non specified serializer case 330 331// RDFParser parser = null; 332 333// if (options.format == null && dataset instanceof String) { 334// // attempt to parse the input as nquads 335// options.format = "application/nquads"; 336// } 337 338// if (rdfParsers.containsKey(options.format)) { 339// parser = rdfParsers.get(options.format); 340// } else { 341// throw new JsonLdError(JsonLdError.Error.UNKNOWN_FORMAT, options.format); 342// } 343 344// // convert from RDF 345// return fromRDF(dataset, options, parser); 346// } 347 348// /** 349// * Converts an RDF dataset to JSON-LD, using the default 350// * {@link JsonLdOptions}. 351// * 352// * @param dataset 353// * a serialized string of RDF in a format specified by the format 354// * option or an RDF dataset to convert. 355// * @return The JSON-LD object represented by the given RDF dataset 356// * @throws JsonLdError 357// * If there was an error converting from RDF to JSON-LD 358// */ 359// public static Object fromRDF(Object dataset) throws JsonLdError { 360// return fromRDF(dataset, new JsonLdOptions("")); 361// } 362 363// /** 364// * Converts an RDF dataset to JSON-LD, using a specific instance of 365// * {@link RDFParser}. 366// * 367// * @param input 368// * a serialized string of RDF in a format specified by the format 369// * option or an RDF dataset to convert. 370// * @param options 371// * the options to use: [format] the format if input is not an 372// * array: 'application/nquads' for N-Quads (default). 373// * [useRdfType] true to use rdf:type, false to use @type 374// * (default: false). [useNativeTypes] true to convert XSD types 375// * into native types (boolean, integer, double), false not to 376// * (default: true). 377// * @param parser 378// * A specific instance of {@link RDFParser} to use for the 379// * conversion. 380// * @return A JSON-LD object. 381// * @throws JsonLdError 382// * If there is an error converting the dataset to JSON-LD. 383// */ 384// public static Object fromRDF(Object input, JsonLdOptions options, RDFParser parser) 385// throws JsonLdError { 386 387// final RDFDataset dataset = parser.parse(input); 388 389// // convert from RDF 390// final Object rval = new JsonLdApi(options).fromRDF(dataset); 391 392// // re-process using the generated context if outputForm is set 393// if (options.outputForm != null) { 394// if ("expanded".equals(options.outputForm)) { 395// return rval; 396// } else if ("compacted".equals(options.outputForm)) { 397// return compact(rval, dataset.getContext(), options); 398// } else if ("flattened".equals(options.outputForm)) { 399// return flatten(rval, dataset.getContext(), options); 400// } else { 401// throw new JsonLdError(JsonLdError.Error.UNKNOWN_ERROR); 402// } 403// } 404// return rval; 405// } 406 407// /** 408// * Converts an RDF dataset to JSON-LD, using a specific instance of 409// * {@link RDFParser}, and the default {@link JsonLdOptions}. 410// * 411// * @param input 412// * a serialized string of RDF in a format specified by the format 413// * option or an RDF dataset to convert. 414// * @param parser 415// * A specific instance of {@link RDFParser} to use for the 416// * conversion. 417// * @return A JSON-LD object. 418// * @throws JsonLdError 419// * If there is an error converting the dataset to JSON-LD. 420// */ 421// public static Object fromRDF(Object input, RDFParser parser) throws JsonLdError { 422// return fromRDF(input, new JsonLdOptions(""), parser); 423// } 424 425// /** 426// * Outputs the RDF dataset found in the given JSON-LD object. 427// * 428// * @param input 429// * the JSON-LD input. 430// * @param callback 431// * A callback that is called when the input has been converted to 432// * Quads (null to use options.format instead). 433// * @param options 434// * the options to use: [base] the base IRI to use. [format] the 435// * format to use to output a string: 'application/nquads' for 436// * N-Quads (default). [loadContext(url, callback(err, url, 437// * result))] the context loader. 438// * @return A JSON-LD object. 439// * @throws JsonLdError 440// * If there is an error converting the dataset to JSON-LD. 441// */ 442// public static Object toRDF(Object input, JsonLdTripleCallback callback, JsonLdOptions options) 443// throws JsonLdError { 444 445// final Object expandedInput = expand(input, options); 446 447// final JsonLdApi api = new JsonLdApi(expandedInput, options); 448// final RDFDataset dataset = api.toRDF(); 449 450// // generate namespaces from context 451// if (options.useNamespaces) { 452// List<Map<String, Object>> _input; 453// if (input instanceof List) { 454// _input = (List<Map<String, Object>>) input; 455// } else { 456// _input = new ArrayList<Map<String, Object>>(); 457// _input.add((Map<String, Object>) input); 458// } 459// for (final Map<String, Object> e : _input) { 460// if (e.containsKey("@context")) { 461// dataset.parseContext(e.get("@context")); 462// } 463// } 464// } 465 466// if (callback != null) { 467// return callback.call(dataset); 468// } 469 470// if (options.format != null) { 471// if ("application/nquads".equals(options.format)) { 472// return new NQuadTripleCallback().call(dataset); 473// } else if ("text/turtle".equals(options.format)) { 474// return new TurtleTripleCallback().call(dataset); 475// } else { 476// throw new JsonLdError(JsonLdError.Error.UNKNOWN_FORMAT, options.format); 477// } 478// } 479// return dataset; 480// } 481 482// /** 483// * Outputs the RDF dataset found in the given JSON-LD object. 484// * 485// * @param input 486// * the JSON-LD input. 487// * @param options 488// * the options to use: [base] the base IRI to use. [format] the 489// * format to use to output a string: 'application/nquads' for 490// * N-Quads (default). [loadContext(url, callback(err, url, 491// * result))] the context loader. 492// * @return A JSON-LD object. 493// * @throws JsonLdError 494// * If there is an error converting the dataset to JSON-LD. 495// */ 496// public static Object toRDF(Object input, JsonLdOptions options) throws JsonLdError { 497// return toRDF(input, null, options); 498// } 499 500// /** 501// * Outputs the RDF dataset found in the given JSON-LD object, using the 502// * default {@link JsonLdOptions}. 503// * 504// * @param input 505// * the JSON-LD input. 506// * @param callback 507// * A callback that is called when the input has been converted to 508// * Quads (null to use options.format instead). 509// * @return A JSON-LD object. 510// * @throws JsonLdError 511// * If there is an error converting the dataset to JSON-LD. 512// */ 513// public static Object toRDF(Object input, JsonLdTripleCallback callback) throws JsonLdError { 514// return toRDF(input, callback, new JsonLdOptions("")); 515// } 516 517// /** 518// * Outputs the RDF dataset found in the given JSON-LD object, using the 519// * default {@link JsonLdOptions}. 520// * 521// * @param input 522// * the JSON-LD input. 523// * @return A JSON-LD object. 524// * @throws JsonLdError 525// * If there is an error converting the dataset to JSON-LD. 526// */ 527// public static Object toRDF(Object input) throws JsonLdError { 528// return toRDF(input, new JsonLdOptions("")); 529// } 530 531// /** 532// * Performs RDF dataset normalization on the given JSON-LD input. The output 533// * is an RDF dataset unless the 'format' option is used. 534// * 535// * @param input 536// * the JSON-LD input to normalize. 537// * @param options 538// * the options to use: [base] the base IRI to use. [format] the 539// * format if output is a string: 'application/nquads' for 540// * N-Quads. [loadContext(url, callback(err, url, result))] the 541// * context loader. 542// * @return The JSON-LD object 543// * @throws JsonLdError 544// * If there is an error normalizing the dataset. 545// */ 546// public static Object normalize(Object input, JsonLdOptions options) throws JsonLdError { 547 548// final JsonLdOptions opts = new JsonLdOptions(options.getBase()); 549// opts.format = null; 550// final RDFDataset dataset = (RDFDataset) toRDF(input, opts); 551 552// return new JsonLdApi(options).normalize(dataset); 553// } 554 555// /** 556// * Performs RDF dataset normalization on the given JSON-LD input. The output 557// * is an RDF dataset unless the 'format' option is used. Uses the default 558// * {@link JsonLdOptions}. 559// * 560// * @param input 561// * the JSON-LD input to normalize. 562// * @return The JSON-LD object 563// * @throws JsonLdError 564// * If there is an error normalizing the dataset. 565// */ 566// public static Object normalize(Object input) throws JsonLdError { 567// return normalize(input, new JsonLdOptions("")); 568// } 569