MetadataImpl.java

  1. /*
  2.  * Copyright (c) 2007-2017 MetaSolutions AB
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *     http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */


  16. package org.entrystore.impl;

  17. import lombok.Getter;
  18. import org.eclipse.rdf4j.common.iteration.Iterations;
  19. import org.eclipse.rdf4j.model.IRI;
  20. import org.eclipse.rdf4j.model.Model;
  21. import org.eclipse.rdf4j.model.Resource;
  22. import org.eclipse.rdf4j.model.Statement;
  23. import org.eclipse.rdf4j.model.Value;
  24. import org.eclipse.rdf4j.model.impl.LinkedHashModel;
  25. import org.eclipse.rdf4j.repository.RepositoryConnection;
  26. import org.eclipse.rdf4j.repository.RepositoryException;
  27. import org.entrystore.AuthorizationException;
  28. import org.entrystore.Metadata;
  29. import org.entrystore.PrincipalManager;
  30. import org.entrystore.PrincipalManager.AccessProperty;
  31. import org.entrystore.repository.RepositoryEvent;
  32. import org.entrystore.repository.RepositoryEventObject;
  33. import org.slf4j.Logger;
  34. import org.slf4j.LoggerFactory;

  35. import javax.xml.datatype.DatatypeConfigurationException;
  36. import java.net.URI;


  37. public class MetadataImpl implements Metadata {

  38.     private EntryImpl entry;
  39.     private IRI uri;
  40.     private IRI resourceUri;
  41.     private org.eclipse.rdf4j.model.Resource mdContext;
  42.     @Getter
  43.     private boolean cached;
  44.     private boolean localCache;
  45.     Logger log = LoggerFactory.getLogger(MetadataImpl.class);

  46.     public MetadataImpl(EntryImpl entry, IRI uri, IRI resourceUri, boolean cached) {
  47.         this.entry = entry;
  48.         this.uri = uri;
  49.         this.resourceUri = resourceUri;
  50.         this.mdContext = uri;
  51.         this.cached = cached;
  52.         this.localCache = true; //TODO fix
  53.     }

  54.     public Model getGraph() {
  55.         PrincipalManager pm = this.entry.getRepositoryManager().getPrincipalManager();
  56.         if (pm != null) {
  57.             pm.checkAuthenticatedUserAuthorized(entry, AccessProperty.ReadMetadata);
  58.         }
  59.         /*      if (cached && localCache) {
  60.             Entry cachedFrom = this.entry.getRepositoryManager().getContextManager().getEntry(getURI());
  61.             if (cachedFrom != null) {
  62.                 return cachedFrom.getMetadataGraph();
  63.             }
  64.         }*/
  65.         RepositoryConnection rc = null;
  66.         try {
  67.             rc = this.entry.repository.getConnection();
  68.             return Iterations.addAll(rc.getStatements(null, null, null, false, mdContext), new LinkedHashModel());
  69.         } catch (RepositoryException e) {
  70.             log.error(e.getMessage());
  71.             throw new org.entrystore.repository.RepositoryException("Failed to connect to Repository.", e);
  72.         } finally {
  73.             try {
  74.                 rc.close();
  75.             } catch (RepositoryException e) {
  76.                 log.error(e.getMessage());
  77.             }
  78.         }
  79.     }

  80.     public URI getURI() {
  81.         if (this.uri != null) {
  82.             return URI.create(this.uri.toString());
  83.         } else {
  84.             log.warn("Metadata URI is null of entry: " + this.entry.getEntryURI());
  85.             return null;
  86.         }
  87.     }

  88.     public URI getResourceURI() {
  89.         return URI.create(resourceUri.toString());
  90.     }

  91.     public void setGraph(Model graph) {
  92.         PrincipalManager pm = this.entry.getRepositoryManager().getPrincipalManager();
  93.         if (pm != null) {
  94.             pm.checkAuthenticatedUserAuthorized(entry, AccessProperty.WriteMetadata);
  95.         }
  96.        
  97.         try {
  98.             synchronized (this.entry.repository) {
  99.                 RepositoryConnection rc = this.entry.repository.getConnection();
  100.                 rc.begin();
  101.                 try {
  102.                     Model oldGraph = removeGraphSynchronized(rc);
  103.                     addGraphSynchronized(rc, graph);
  104.                     ProvenanceImpl provenance = (ProvenanceImpl) this.entry.getProvenance();
  105.                     if (provenance != null && !cached) {
  106.                         provenance.addMetadataEntity(oldGraph, rc);
  107.                     }
  108.                     rc.commit();
  109.                     if (cached) {
  110.                         entry.getRepositoryManager().fireRepositoryEvent(new RepositoryEventObject(entry, RepositoryEvent.ExternalMetadataUpdated, graph));
  111.                     } else {
  112.                         entry.getRepositoryManager().fireRepositoryEvent(new RepositoryEventObject(entry, RepositoryEvent.MetadataUpdated, graph));
  113.                     }
  114.                 } catch (AuthorizationException ae) {
  115.                     rc.rollback();
  116.                     log.warn(ae.getMessage());
  117.                     throw ae;
  118.                 } catch (Exception e) {
  119.                     rc.rollback();
  120.                     log.error(e.getMessage());
  121.                     throw new org.entrystore.repository.RepositoryException("Error in connection to repository", e);
  122.                 } finally {
  123.                     rc.close();
  124.                 }
  125.             }
  126.         } catch (RepositoryException e) {
  127.             log.error(e.getMessage());
  128.             throw new org.entrystore.repository.RepositoryException("Failed to connect to Repository.", e);
  129.         }
  130.     }
  131.     public Model removeGraphSynchronized(RepositoryConnection rc) throws RepositoryException {
  132.         String base = this.entry.repositoryManager.getRepositoryURL().toString();
  133.         //Fetch old graph
  134.         Model graph = Iterations.addAll(rc.getStatements(null, null, null, false, mdContext), new LinkedHashModel());

  135.         // Remove relations in other entries inverse relational cache if entry has repository URL.
  136.         if (this.resourceUri.stringValue().startsWith(base)) { //Only check for relations for non external links at this point.
  137.             for (Statement statement : graph) {
  138.                 Value obj = statement.getObject();
  139.                 Resource subj = statement.getSubject();
  140.                 //Check for relations between this resource and another entry (resourceURI (has to be a repository resource), metadataURI, or entryURI)
  141.                 if (obj instanceof IRI
  142.                         && obj.stringValue().startsWith(base)
  143.                         && subj.stringValue().startsWith(base)) {
  144.                     URI entryURI = URI.create(statement.getObject().stringValue());

  145.                     EntryImpl sourceEntry = (EntryImpl) this.entry.getRepositoryManager().getContextManager().getEntry(entryURI);
  146.                     if (sourceEntry != null) {
  147.                         sourceEntry.removeRelationSynchronized(statement, rc);
  148.                     }
  149.                 }
  150.             }
  151.         }
  152.         rc.clear(mdContext);
  153.         return graph;
  154.     }
  155.    
  156.     public void addGraphSynchronized(RepositoryConnection rc, Model graph) throws RepositoryException, DatatypeConfigurationException {
  157.         String base = this.entry.repositoryManager.getRepositoryURL().toString();

  158.         rc.add(graph, mdContext);
  159.         if (cached) {
  160.             ((EntryImpl) this.entry).updateCachedExternalMetadataDateSynchronized(rc, this.entry.repository.getValueFactory());
  161.         } else {
  162.             ((EntryImpl) this.entry).updateModifiedDateSynchronized(rc, this.entry.repository.getValueFactory());
  163.         }

  164.         // Check if there are any relations in the metadata graph.
  165.         // If it is, then add them to the source entry's relation graph.
  166.         //Old graph, remove from target entry relation index.
  167.         if (this.resourceUri.stringValue().startsWith(base)) { //Only check for relations for non external links at this point.
  168.             for (Statement statement : graph) {
  169.                 Value obj = statement.getObject();
  170.                 Resource subj = statement.getSubject();
  171.                 //Check for relations between this resource and another entry (resourceURI (has to be a repository resource), metadataURI, or entryURI)
  172.                 if (obj instanceof IRI
  173.                         && obj.stringValue().startsWith(base)
  174.                         && subj.stringValue().startsWith(base)) {
  175.                     URI entryURI = URI.create(statement.getObject().stringValue());

  176.                     // we fetch the entry without respecting the ACL (in case the modifying user lacks read access), otherwise we
  177.                     // can't update the inverse relational cache and the whole operation would fail
  178.                     EntryImpl sourceEntry = (EntryImpl) ((ContextManagerImpl) this.entry.getRepositoryManager().getContextManager()).getEntryIgnoreACL(entryURI);
  179.                     if (sourceEntry != null) {
  180.                         sourceEntry.addRelationSynchronized(statement, rc);
  181.                     }
  182.                 }
  183.             }
  184.         }
  185.     }

  186. }