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  
19  package org.mycore.datamodel.metadata;
20  
21  import java.io.IOException;
22  import java.net.URI;
23  
24  import org.apache.logging.log4j.LogManager;
25  import org.apache.logging.log4j.Logger;
26  import org.jdom2.Document;
27  import org.jdom2.Element;
28  import org.mycore.common.MCRException;
29  import org.mycore.datamodel.classifications2.MCRCategoryDAOFactory;
30  import org.mycore.datamodel.classifications2.MCRCategoryID;
31  import org.mycore.datamodel.common.MCRActiveLinkException;
32  import org.xml.sax.SAXParseException;
33  
34  import com.google.gson.JsonObject;
35  
36  /**
37   * This class holds all information of a metadata object.
38   * For persistence operations see methods of {@link MCRMetadataManager}.
39   *  
40   * @author Jens Kupferschmidt
41   * @author Mathias Hegner
42   * @author Thomas Scheffler (yagee)
43   * @version $Revision$ $Date$
44   */
45  public final class MCRObject extends MCRBase {
46  
47      private static final Logger LOGGER = LogManager.getLogger();
48  
49      public static final String ROOT_NAME = "mycoreobject";
50  
51      /**
52       * constant value for the object id length
53       */
54      public static final int MAX_LABEL_LENGTH = 256;
55  
56      /**
57       * the object content
58       */
59      private final MCRObjectStructure structure;
60  
61      private final MCRObjectMetadata metadata;
62  
63      protected String mcrLabel = null;
64  
65      /**
66       * This is the constructor of the MCRObject class. It creates an instance of
67       * the parser class and the metadata class. <br>
68       * The constructor reads the following information from the property file:
69       * <ul>
70       * <li>MCR.XMLParser.Class</li>
71       * </ul>
72       * 
73       * @exception MCRException
74       *                general Exception of MyCoRe
75       */
76      public MCRObject() throws MCRException {
77          super();
78          structure = new MCRObjectStructure();
79          metadata = new MCRObjectMetadata();
80          mcrLabel = "";
81      }
82  
83      public MCRObject(byte[] bytes, boolean valid) throws SAXParseException {
84          this();
85          setFromXML(bytes, valid);
86      }
87  
88      public MCRObject(Document doc) {
89          this();
90          setFromJDOM(doc);
91      }
92  
93      public MCRObject(URI uri) throws SAXParseException, IOException {
94          this();
95          setFromURI(uri);
96      }
97  
98      /**
99       * This method returns the instance of the MCRObjectMetadata class. If there
100      * was no MCRObjectMetadata found, null will be returned.
101      * 
102      * @return the instance of the MCRObjectMetadata class
103      */
104     public MCRObjectMetadata getMetadata() {
105         return metadata;
106     }
107 
108     /**
109      * This method return the instance of the MCRObjectStructure class. If this
110      * was not found, null was returned.
111      * 
112      * @return the instance of the MCRObjectStructure class
113      */
114     public MCRObjectStructure getStructure() {
115         return structure;
116     }
117 
118     /**
119      * This methode return the object label. If this is not set, null was
120      * returned.
121      * 
122      * @return the lable as a string
123      */
124     public String getLabel() {
125         return mcrLabel;
126     }
127 
128     /**
129      * This method set the object label.
130      * 
131      * @param label
132      *            the object label
133      */
134     public void setLabel(String label) {
135         if (label == null) {
136             mcrLabel = label;
137         } else {
138             mcrLabel = label.trim();
139             if (mcrLabel.length() > MAX_LABEL_LENGTH) {
140                 mcrLabel = mcrLabel.substring(0, MAX_LABEL_LENGTH);
141             }
142         }
143     }
144 
145     /**
146      * The given DOM was convert into an internal view of metadata. This are the
147      * object ID and the object label, also the blocks structure, flags and
148      * metadata.
149      * 
150      * @exception MCRException
151      *                general Exception of MyCoRe
152      */
153     @Override
154     protected void setUp() throws MCRException {
155         super.setUp();
156 
157         setLabel(jdomDocument.getRootElement().getAttributeValue("label"));
158 
159         // get the structure data of the object
160         Element structureElement = jdomDocument.getRootElement().getChild("structure");
161         if (structureElement != null) {
162             structure.setFromDOM(structureElement);
163         }
164 
165         // get the metadata of the object
166         Element metadataElement = jdomDocument.getRootElement().getChild("metadata");
167 
168         if (metadataElement != null) {
169             metadata.setFromDOM(metadataElement);
170         }
171     }
172 
173     /**
174      * This method creates a XML stream for all object data.
175      * 
176      * @exception MCRException
177      *                if the content of this class is not valid
178      * @return a JDOM Document with the XML data of the object as byte array
179      */
180     @Override
181     public Document createXML() throws MCRException {
182         try {
183             Document doc = super.createXML();
184             Element elm = doc.getRootElement();
185             if (mcrLabel != null) {
186                 elm.setAttribute("label", mcrLabel);
187             }
188             elm.addContent(structure.createXML());
189             elm.addContent(metadata.createXML());
190             elm.addContent(mcrService.createXML());
191             return doc;
192         } catch (MCRException exc) {
193             throw new MCRException("The content of '" + mcrId + "' is invalid.", exc);
194         }
195     }
196 
197     /**
198      * Creates the JSON representation of this object. Extends the {@link MCRBase#createJSON()}
199      * method with the following content:
200      * 
201      * <pre>
202      *   {
203      *     id: "mycore_project_00000001",
204      *     version: "3.0"
205      *     label: "my mycore object",
206      *     
207      *     structure: {@link MCRObjectStructure#createJSON},
208      *     metadata: {@link MCRObjectMetadata#createJSON},
209      *     service: {@link MCRObjectService#createJSON},
210      *   }
211      * </pre>
212      * 
213      * @return a json gson representation of this object
214      */
215     @Override
216     public JsonObject createJSON() {
217         JsonObject object = super.createJSON();
218         if (mcrLabel != null) {
219             object.addProperty("label", mcrLabel);
220         }
221         object.add("structure", structure.createJSON());
222         object.add("metadata", metadata.createJSON());
223         object.add("service", mcrService.createJSON());
224         return object;
225     }
226 
227     @Override
228     protected String getRootTagName() {
229         return ROOT_NAME;
230     }
231 
232     /**
233      * The method print all informations about this MCRObject.
234      */
235     public void debug() {
236         if (LOGGER.isDebugEnabled()) {
237             if (mcrId == null) {
238                 LOGGER.debug("MCRObject ID : missing");
239             } else {
240                 LOGGER.debug("MCRObject ID : {}", mcrId);
241             }
242             LOGGER.debug("MCRObject Label : {}", mcrLabel);
243             LOGGER.debug("MCRObject Schema : {}", mcrSchema);
244             LOGGER.debug("");
245         }
246         structure.debug();
247         metadata.debug();
248     }
249 
250     /**
251      * Validates this MCRObject. This method throws an exception if:
252      *  <ul>
253      *  <li>the mcr_id is null</li>
254      *  <li>the XML schema is null or empty</li>
255      *  <li>the service part is null or invalid</li>
256      *  <li>the structure part is null or invalid</li>
257      *  <li>the metadata part is null or invalid</li>
258      *  </ul>
259      * 
260      * @throws MCRException the MCRObject is invalid
261      */
262     @Override
263     public void validate() {
264         super.validate();
265         MCRObjectStructure structure = getStructure();
266         MCRObjectMetadata metadata = getMetadata();
267         if (structure == null) {
268             throw new MCRException("The <structure> part of '" + getId() + "' is undefined.");
269         }
270         if (metadata == null) {
271             throw new MCRException("The <metadata> part of '" + getId() + "' is undefined.");
272         }
273         try {
274             structure.validate();
275         } catch (MCRException exc) {
276             throw new MCRException("The <structure> part of '" + getId() + "' is invalid.", exc);
277         }
278         if (getId().equals(getParent())) {
279             throw new MCRException("This object '" + getId() + "' cannot be parent/child of itself.");
280         }
281         try {
282             metadata.validate();
283         } catch (MCRException exc) {
284             throw new MCRException("The <metadata> part of '" + getId() + "' is invalid.", exc);
285         }
286     }
287 
288     /**
289      * @return true if the MCRObject has got a parent mcrobject, false otherwise 
290      */
291     public boolean hasParent() {
292         return getStructure().getParentID() != null;
293     }
294 
295     public MCRObjectID getParent() {
296         return getStructure().getParentID();
297     }
298 
299     public void checkLinkTargets() {
300         for (int i = 0; i < getMetadata().size(); i++) {
301             MCRMetaElement elm = getMetadata().getMetadataElement(i);
302             for (int j = 0; j < elm.size(); j++) {
303                 MCRMetaInterface inf = elm.getElement(j);
304                 if (inf instanceof MCRMetaClassification) {
305                     String classID = ((MCRMetaClassification) inf).getClassId();
306                     String categID = ((MCRMetaClassification) inf).getCategId();
307                     boolean exists = MCRCategoryDAOFactory.getInstance().exist(new MCRCategoryID(classID, categID));
308                     if (exists) {
309                         continue;
310                     }
311                     MCRActiveLinkException activeLink = new MCRActiveLinkException(
312                         "Failure while adding link!. Destination does not exist.");
313                     String destination = classID + "##" + categID;
314                     activeLink.addLink(getId().toString(), destination);
315                     // throw activeLink;
316                     // TODO: should trigger undo-Event
317                 }
318                 if (inf instanceof MCRMetaLinkID) {
319                     MCRObjectID destination = ((MCRMetaLinkID) inf).getXLinkHrefID();
320                     if (MCRMetadataManager.exists(destination)) {
321                         continue;
322                     }
323                     MCRActiveLinkException activeLink = new MCRActiveLinkException(
324                         "Failure while adding link!. Destination does not exist.");
325                     activeLink.addLink(getId().toString(), destination.toString());
326                     // throw activeLink;
327                     // TODO: should trigger undo-Event
328                 }
329             }
330         }
331     }
332 
333 }