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.common;
20  
21  import org.mycore.common.content.MCRJDOMContent;
22  import org.mycore.common.xml.MCRXMLParserFactory;
23  import org.mycore.datamodel.metadata.MCRMetaElement;
24  import org.mycore.datamodel.metadata.MCRMetaInterface;
25  import org.mycore.datamodel.metadata.MCRObject;
26  import org.mycore.datamodel.metadata.MCRObjectMetadata;
27  
28  /**
29   * Helper class to merge mycore objects. Only metadata merging is
30   * currently supported.
31   *
32   * @author Matthias Eichner
33   */
34  public class MCRObjectMerger {
35  
36      protected MCRObject target;
37  
38      /**
39       * Creates a new instance of the object merger. The target will be cloned for
40       * further processing. You will receive a copy when calling {@link #get()}.
41       *
42       * @param target the target mycore object
43       */
44      public MCRObjectMerger(MCRObject target) {
45          this.target = new MCRObject(target.createXML());
46      }
47  
48      /**
49       * Merges the metadata of the given source into the target object. Be aware that
50       * performance isn't that good when validation is activated, due checking against
51       * the schema each time a change is made.
52       *
53       * @param source the source which is merged into the target
54       * @param validate If true, every change is tracked and validated against the
55       *          xml schema of the mycore object. When a change is invalid it will be
56       *          canceled and the merging continues.
57       *          When set to false the mycore object will be merged without validation.
58       *          This can result in an invalid object.
59       *
60       * @return true if something was merged
61       */
62      public boolean mergeMetadata(MCRObject source, boolean validate) {
63          MCRObjectMetadata targetMetadata = this.target.getMetadata();
64          boolean merged = false;
65          for (MCRMetaElement metaElementSource : source.getMetadata()) {
66              MCRMetaElement metaElementTarget = targetMetadata.getMetadataElement(metaElementSource.getTag());
67              if (metaElementTarget == null) {
68                  targetMetadata.setMetadataElement(metaElementSource.clone());
69                  if (validate && !validate(this.target)) {
70                      targetMetadata.removeMetadataElement(metaElementSource.getTag());
71                  } else {
72                      merged = true;
73                  }
74              } else {
75                  for (MCRMetaInterface metaInterfaceSource : metaElementSource) {
76                      boolean equal = false;
77                      for (MCRMetaInterface metaInterfaceTarget : metaElementTarget) {
78                          if (metaInterfaceSource.equals(metaInterfaceTarget)) {
79                              equal = true;
80                              break;
81                          }
82                      }
83                      if (!equal) {
84                          metaElementTarget.addMetaObject(metaInterfaceSource.clone());
85                          if (validate && !validate(this.target)) {
86                              metaElementTarget.removeMetaObject(metaInterfaceSource);
87                          } else {
88                              merged = true;
89                          }
90                      }
91                  }
92              }
93          }
94          return merged;
95      }
96  
97      /**
98       * Validates the given mcr object against its own schema.
99       *
100      * @param mcrobj the object to validate
101      * @return true if the object is valid, otherwise false
102      */
103     protected boolean validate(MCRObject mcrobj) {
104         try {
105             MCRXMLParserFactory.getParser(true, true).parseXML(new MCRJDOMContent(mcrobj.createXML()));
106             return true;
107         } catch (Exception exc) {
108             return false;
109         }
110     }
111 
112     /**
113      * Returns a copy of the merged target object.
114      *
115      */
116     public MCRObject get() {
117         return this.target;
118     }
119 
120 }