View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  package org.mycore.oai;
19  
20  import org.apache.logging.log4j.LogManager;
21  import org.apache.logging.log4j.Logger;
22  import org.jdom2.Element;
23  import org.jdom2.output.Format;
24  import org.jdom2.output.XMLOutputter;
25  import org.mycore.common.config.MCRConfiguration2;
26  import org.mycore.common.xml.MCRURIResolver;
27  import org.mycore.datamodel.common.MCRXMLMetadataManager;
28  import org.mycore.datamodel.metadata.MCRMetadataManager;
29  import org.mycore.datamodel.metadata.MCRObjectID;
30  import org.mycore.datamodel.metadata.history.MCRMetadataHistoryManager;
31  import org.mycore.oai.pmh.Header;
32  import org.mycore.oai.pmh.Header.Status;
33  import org.mycore.oai.pmh.MetadataFormat;
34  import org.mycore.oai.pmh.OAIConstants;
35  import org.mycore.oai.pmh.Record;
36  import org.mycore.oai.pmh.SimpleMetadata;
37  
38  /**
39   * Provides an interface to the MyCoRe object engine.
40   * 
41   * @author Matthias Eichner
42   */
43  public class MCROAIObjectManager {
44  
45      protected static final Logger LOGGER = LogManager.getLogger(MCROAIObjectManager.class);
46  
47      protected MCROAIIdentify identify;
48  
49      protected String recordUriPattern;
50  
51      /**
52       * Initialize the object manager. Its important to call this method before you
53       * can retrieve records or headers!
54       * 
55       * @param identify oai repository identifier
56       */
57      public void init(MCROAIIdentify identify) {
58          this.identify = identify;
59          String configPrefix = this.identify.getConfigPrefix();
60          this.recordUriPattern = MCRConfiguration2.getStringOrThrow(configPrefix + "Adapter.RecordURIPattern");
61      }
62  
63      /**
64       * Converts a oai identifier to a mycore id.
65       * 
66       * @param oaiId the oai identifier
67       * @return the mycore identifier
68       */
69      public String getMyCoReId(String oaiId) {
70          return oaiId.substring(oaiId.lastIndexOf(':') + 1);
71      }
72  
73      /**
74       * Converts a mycore id to a oai id.
75       * 
76       * @param mcrId mycore identifier
77       */
78      public String getOAIId(String mcrId) {
79          return getOAIIDPrefix() + mcrId;
80      }
81  
82      public Record getRecord(Header header, MetadataFormat format) {
83          Element recordElement;
84          if (header.isDeleted()) {
85              return new Record(header);
86          }
87          try {
88              recordElement = getJDOMRecord(getMyCoReId(header.getId()), format);
89          } catch (Exception exc) {
90              LOGGER.error("unable to get record {} ({})", header.getId(), format.getPrefix(), exc);
91              return null;
92          }
93          Record record = new Record(header);
94          if (recordElement.getNamespace().equals(OAIConstants.NS_OAI)) {
95              Element metadataElement = recordElement.getChild("metadata", OAIConstants.NS_OAI);
96              if (metadataElement != null && !metadataElement.getChildren().isEmpty()) {
97                  Element metadataChild = metadataElement.getChildren().get(0);
98                  record.setMetadata(new SimpleMetadata(metadataChild.detach()));
99              }
100             Element aboutElement = recordElement.getChild("about", OAIConstants.NS_OAI);
101             if (aboutElement != null) {
102                 for (Element aboutChild : aboutElement.getChildren()) {
103                     record.getAboutList().add(aboutChild.detach());
104                 }
105             }
106         } else {
107             //handle as metadata
108             record.setMetadata(new SimpleMetadata(recordElement));
109         }
110         return record;
111     }
112 
113     /**
114      * Returns a deleted record without metadata by given MyCoRe identifier or null, if the
115      * record is not deleted.
116      * 
117      * @param mcrId id of the deleted record
118      * @return deleted record
119      */
120     public Record getDeletedRecord(String mcrId) {
121         try {
122             // building the query
123             return MCRMetadataHistoryManager.getLastDeletedDate(MCRObjectID.getInstance(mcrId))
124                 .map(deletedDate -> new Record(
125                     new Header(getOAIId(mcrId), deletedDate, Status.deleted)))
126                 .orElse(null);
127         } catch (Exception ex) {
128             LOGGER.warn("Error while retrieving deleted record {}", mcrId, ex);
129         }
130         return null;
131     }
132 
133     protected Element getJDOMRecord(String mcrId, MetadataFormat format) {
134         String uri = formatURI(this.recordUriPattern, mcrId, format.getPrefix());
135         return getURI(uri);
136     }
137 
138     protected Element getURI(String uri) {
139         Element e = MCRURIResolver.instance().resolve(uri).detach();
140         if (LOGGER.isDebugEnabled()) {
141             LOGGER.debug("get {}", uri);
142             XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
143             LOGGER.debug(out.outputString(e));
144         }
145         return e;
146     }
147 
148     protected String formatURI(String uri, String id, String metadataPrefix) {
149         MCRObjectID mcrID = MCRObjectID.isValid(id) ? MCRObjectID.getInstance(id) : null;
150         boolean exists;
151         String objectType;
152         if (mcrID != null) {
153             exists = MCRMetadataManager.exists(mcrID);
154             objectType = mcrID.getTypeId();
155         } else {
156             //TODO remove this code path
157             LOGGER.warn("MCRFileSystemNodes are not supported anymore! id: " + id);
158             exists = false;
159             objectType = "data_file";
160         }
161         return uri.replace("{id}", id).replace("{format}", metadataPrefix).replace("{objectType}", objectType).replace(
162             ":{flag}", !exists ? ":deletedMcrObject" : "");
163     }
164 
165     /**
166      * Checks if a mycore object with the given oai identifier exists.
167      * 
168      * @param oaiId
169      *            e.g. oai:www.mycore.de:Document_document_00000003
170      * @return true if exists, otherwise false
171      */
172     protected boolean exists(String oaiId) {
173         String mcrId = oaiId.substring(getOAIIDPrefix().length());
174         try {
175             MCRObjectID mcrObjId = MCRObjectID.getInstance(mcrId);
176             return MCRXMLMetadataManager.instance().exists(mcrObjId);
177         } catch (Exception ex) {
178             return false;
179         }
180     }
181 
182     private String getOAIIDPrefix() {
183         return "oai:" + this.identify.getIdentifierDescription().getRepositoryIdentifier() + ":";
184     }
185 
186 }