/** * Tests the merging of two graphs */ public function testMerge() { $this->markTestSkipped("Merging graphs doesn't work yet as blank nodes are not relabeled properly"); $json = <<<JSON_LD_DOCUMENT { "@context": { "ex": "http://vocab.com/", "node": "ex:type/node" }, "@graph": [ { "@id": "1", "@type": "ex:type/node", "ex:name": "1", "ex:link": { "@id": "./2" }, "ex:contains": { "ex:nested": "1.1 (graph 2)" } }, { "@id": "/node/2", "ex:name": "and a different name in graph 2", "ex:link": { "@id": "/node/4" }, "ex:newFromGraph2": "this was added in graph 2" }, { "@id": "http://example.com/node/4", "ex:name": "node 4 from graph 2" } ] } JSON_LD_DOCUMENT; $graph2 = Document::load($json, array('base' => 'http://example.com/node/index.jsonld'))->getGraph(); // Merge graph2 into graph $this->graph->merge($graph2); $nodeIds = array('http://example.com/node/1', 'http://example.com/node/2', 'http://example.com/node/3', 'http://example.com/node/4', '_:b0', '_:b1', '_:b2', '_:b3', '_:b4', 'http://vocab.com/type/node', 'http://vocab.com/type/nodeWithAliases'); $nodes = $this->graph->getNodes(); $this->assertCount(count($nodeIds), $nodes); foreach ($nodes as $node) { // Is the node's ID valid? $this->assertContains($node->getId(), $nodeIds, 'Found unexpected node ID: ' . $node->getId()); // Is the node of the right type? $this->assertInstanceOf('ML\\JsonLD\\Node', $node); // Does the graph return the same instance? $n = $this->graph->getNode($node->getId()); $this->assertSame($node, $n, 'same instance'); $this->assertTrue($node->equals($n), 'equals'); $this->assertSame($this->graph, $n->getGraph(), 'linked to graph'); // It must not share node objects with graph 2 $this->assertNotSame($node, $graph2->getNode($node->getId()), 'shared instance between graph and graph 2'); } // Check that the properties have been updated as well $node1 = $this->graph->getNode('http://example.com/node/1'); $node2 = $this->graph->getNode('http://example.com/node/2'); $node3 = $this->graph->getNode('http://example.com/node/3'); $node4 = $this->graph->getNode('http://example.com/node/4'); $this->assertEquals(new TypedValue('1', RdfConstants::XSD_STRING), $node1->getProperty('http://vocab.com/name'), 'n1->name'); $this->assertSame($node2, $node1->getProperty('http://vocab.com/link'), 'n1 -link-> n2'); $this->assertCount(2, $node1->getProperty('http://vocab.com/contains'), 'n1 -contains-> 2 blank nodes'); $this->assertEquals(array(new TypedValue('2', RdfConstants::XSD_STRING), new TypedValue('and a different name in graph 2', RdfConstants::XSD_STRING)), $node2->getProperty('http://vocab.com/name'), 'n2->name'); $this->assertSame(array($node3, $node4), $node2->getProperty('http://vocab.com/link'), 'n2 -link-> n3 & n4'); $this->assertEquals(new TypedValue('this was added in graph 2', RdfConstants::XSD_STRING), $node2->getProperty('http://vocab.com/newFromGraph2'), 'n2->newFromGraph2'); $this->assertEquals(new TypedValue('node 4 from graph 2', RdfConstants::XSD_STRING), $node4->getProperty('http://vocab.com/name'), 'n4->name'); // Verify that graph 2 wasn't changed $nodeIds = array('http://example.com/node/1', 'http://example.com/node/2', '_:b0', 'http://example.com/node/4', 'http://vocab.com/type/node'); $nodes = $graph2->getNodes(); $this->assertCount(count($nodeIds), $nodes); foreach ($nodes as $node) { // Is the node's ID valid? $this->assertContains($node->getId(), $nodeIds, 'Found unexpected node ID in graph 2: ' . $node->getId()); // Is the node of the right type? $this->assertInstanceOf('ML\\JsonLD\\Node', $node); // Does the graph return the same instance? $n = $graph2->getNode($node->getId()); $this->assertSame($node, $n, 'same instance (graph 2)'); $this->assertTrue($node->equals($n), 'equals (graph 2)'); $this->assertSame($graph2, $n->getGraph(), 'linked to graph (graph 2)'); } }
/** * {@inheritdoc} */ public function merge(GraphInterface $graph) { $nodes = $graph->getNodes(); $bnodeMap = array(); foreach ($nodes as $node) { if ($node->isBlankNode()) { if (false === isset($bnodeMap[$node->getId()])) { $bnodeMap[$node->getId()] = $this->createNode(); } $n = $bnodeMap[$node->getId()]; } else { $n = $this->createNode($node->getId()); } foreach ($node->getProperties() as $property => $values) { if (false === is_array($values)) { $values = array($values); } foreach ($values as $val) { if ($val instanceof NodeInterface) { // If the value is another node, we just need to // create a reference to the corresponding node // in this graph. The properties will be merged // in the outer loop if ($val->isBlankNode()) { if (false === isset($bnodeMap[$val->getId()])) { $bnodeMap[$val->getId()] = $this->createNode(); } $val = $bnodeMap[$val->getId()]; } else { $val = $this->createNode($val->getId()); } } elseif (is_object($val)) { // Clone typed values and language-tagged strings $val = clone $val; } $n->addPropertyValue($property, $val); } } } return $this; }