diff -r ac3dc090e987 -r f2a40bbc27f6 server/src/app/Libraries/Mergers/CocoonAbstractRdfMerger.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/app/Libraries/Mergers/CocoonAbstractRdfMerger.php Tue Nov 17 13:11:55 2015 +0100 @@ -0,0 +1,200 @@ +mergedArray = []; + $this->resGraph = new Graph($baseGraph->getUri()); + $this->bnodeMerge = []; + $this->baseGraph = $baseGraph; + $this->srcGraph = $srcGraph; + + + $typeMergeMethodMap = $this->getTypeMergeMethodMap(); + + foreach ( $typeMergeMethodMap as $nodeType => $mergeMethod) { + + foreach($baseGraph->allOfType($nodeType) as $baseResource) { + if($baseResource->isBNode()) { + continue; + } + $this->mergedArray[$baseResource->getUri()] = $baseGraph->toRdfPhp()[$baseResource->getUri()]; + } + foreach($srcGraph->allOfType($nodeType) as $srcResource) { + if($baseResource->isBNode()) { + continue; + } + if(empty($baseGraph->propertyUris($srcResource->getUri()))) { + $this->mergedArray[$srcResource->getUri()] = $srcGraph->toRdfPhp()[$srcResource->getUri()]; + } + else { + $baseResource = $baseGraph->resource($srcResource->getUri()); + $this->mergedArray[$srcResource->getUri()] = $baseGraph->toRdfPhp()[$baseResource->getUri()]; + call_user_func(array($this, $mergeMethod), $baseResource, $srcResource); + } + } + } + + // merge blank node + reset($this->bnodeMerge); + while(list($bnodeId, $bnodeDef) = each($this->bnodeMerge)) { + + $srcUrl = isset($bnodeDef['src_url'])?$bnodeDef['src_url']:null; + $baseUrl = isset($bnodeDef['base_url'])?$bnodeDef['base_url']:null; + + if(is_null($srcUrl) && !is_null($baseUrl)) { + $this->mergedArray[$bnodeId] = $this->copyResource($baseGraph->toRdfPhp()[$baseUrl],CocoonAbstractRdfMerger::ORIGIN_BASE); + } + elseif (is_null($baseUrl) && !is_null($srcUrl)) { + $this->mergedArray[$bnodeId] = $this->copyResource($srcGraph->toRdfPhp()[$srcUrl],CocoonAbstractRdfMerger::ORIGIN_SRC); + } + elseif (!is_null($baseUrl) && !is_null($srcUrl)) { + + $baseResource = $baseGraph->resource($baseUrl); + $srcResource = $srcGraph->resource($srcUrl); + + $mergeMethod = $typeMergeMethodMap[$baseResource->typeAsResource()->getUri()]; + $this->mergedArray[$bnodeId] = []; + + call_user_func(array($this, $mergeMethod), $baseResource, $srcResource, $bnodeId); + + } + + } + + //echo "MERGED ARRAY:\n"; + $this->resGraph->parse($this->mergedArray); + return $this->resGraph; + } + + /** + * Copy a full resource node + * + */ + protected function copyResource($origArray, $origin) { + $resArray = []; + foreach($origArray as $prop => $propValues) { + $resArray[$prop] = $this->buildValueList($propValues, $origin); + } + return $resArray; + } + + /** + * Build a value list. replace the blank node reference. + * @param $srcValues array The original values + * @param $origin int values are 'ORIGIN_BASE' if bnode from base graph or 'ORIGIN_SRC' from source graph + */ + protected function buildValueList($srcValues, $origin) { + $srcArrayProps = []; + foreach ($srcValues as $propValue) { + if(is_array($propValue) && array_key_exists('type', $propValue) && $propValue['type'] == 'bnode') { + $newBNodeId = $this->resGraph->newBNodeId(); + if($origin == CocoonAbstractRdfMerger::ORIGIN_SRC) { + $this->bnodeMerge[$newBNodeId] = ['src_url' => $propValue['value'], 'base_url' => null]; + } + else { + $this->bnodeMerge[$newBNodeId] = ['base_url' => $propValue['value'], 'src_url' => null]; + } + + $propValue['value'] = $newBNodeId; + } + $srcArrayProps[] = $propValue; + } + return $srcArrayProps; + } + + protected function mergePropertySingleValue($prop, &$targetArray, $baseArray, $srcArray) { + + if(isset($baseArray[$prop])) { + $targetArray[$prop] = $this->buildValueList($baseArray[$prop], CocoonAbstractRdfMerger::ORIGIN_BASE); + } + elseif(isset($srcArray[$prop])) { + $targetArray[$prop] = $this->buildValueList($srcArray[$prop], CocoonAbstractRdfMerger::ORIGIN_SRC); + } + } + + protected function mergePropertyMultiplevalue($prop, &$targetArray, $baseArray, $srcArray) { + $propArray = $this->buildValueList(isset($baseArray[$prop])?$baseArray[$prop]:[], CocoonAbstractRdfMerger::ORIGIN_BASE); + if(isset($srcArray[$prop])) { + $mergedArray = array_merge($propArray, $this->buildValueList($srcArray[$prop], CocoonAbstractRdfMerger::ORIGIN_BASE)); + //yes, this is real. Array_unique does not work on multidimentional arrays. Most work-around suggest the use of serialize to compare sub arrays... + $propArray = array_values(array_intersect_key($mergedArray, array_unique(array_map('md5',array_map('serialize', $mergedArray))))); + } + + if(!empty($propArray)) { + $targetArray[$prop] = $propArray; + } + } + + protected function mergePropertySingleBNode($prop, &$targetArray, $baseArray, $srcArray) { + + $newBNodeId = $this->resGraph->newBNodeId(); + + $srcUrl = null; + $baseUrl = null; + + // in src but not in base + if(array_key_exists($prop, $baseArray) && + !empty($baseArray[$prop]) && + array_key_exists('type',$baseArray[$prop][0]) && + array_key_exists('value',$baseArray[$prop][0]) && + $baseArray[$prop][0]['type'] === 'bnode') { + $baseUrl = $baseArray[$prop][0]['value']; + } + + if(array_key_exists($prop, $srcArray) && + !empty($srcArray[$prop]) && + array_key_exists('type',$srcArray[$prop][0]) && + array_key_exists('value',$srcArray[$prop][0]) && + $srcArray[$prop][0]['type'] === 'bnode') { + $srcUrl = $srcArray[$prop][0]['value']; + } + + $this->bnodeMerge[$newBNodeId] = ['src_url' => $srcUrl, 'base_url' => $baseUrl]; + + $targetArray[$prop] = [ [ 'type' => 'bnode', 'value' => $newBNodeId], ]; + + } + + + protected function mergeProperties($singleBNodeProperties, $singleProperties, &$targetArray, $baseRes, $srcRes) { + $srcArray = $this->srcGraph->toRdfPhp()[$srcRes->getUri()]; + $baseArray = $this->baseGraph->toRdfPhp()[$baseRes->getUri()]; + foreach($srcRes->propertyUris() as $prop) { + if(in_array($prop, $singleBNodeProperties)) { + $this->mergePropertySingleBNode($prop, $targetArray, $baseArray, $srcArray); + } + elseif(in_array($prop, $singleProperties)) { + $this->mergePropertySingleValue($prop, $targetArray, $baseArray, $srcArray); + } + else { + $this->mergePropertyMultiplevalue($prop, $targetArray, $baseArray, $srcArray); + } + } + } +}