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.frontend.xeditor;
20  
21  import java.util.List;
22  
23  import org.jaxen.BaseXPath;
24  import org.jaxen.JaxenException;
25  import org.jaxen.dom.DocumentNavigator;
26  import org.jaxen.expr.Expr;
27  import org.jaxen.expr.LocationPath;
28  import org.jaxen.expr.Step;
29  import org.jdom2.Element;
30  import org.jdom2.JDOMException;
31  import org.mycore.common.config.MCRConfiguration2;
32  import org.mycore.common.xml.MCRNodeBuilder;
33  import org.mycore.frontend.xeditor.tracker.MCRAddedElement;
34  import org.mycore.frontend.xeditor.tracker.MCRSwapElements;
35  
36  public class MCRRepeatBinding extends MCRBinding {
37  
38      private int repeatPosition;
39  
40      private int maxRepeats;
41  
42      private static final String DEFAULT_METHOD = MCRConfiguration2.getString("MCR.XEditor.InsertTarget.DefaultMethod")
43          .orElse("build");
44  
45      private String method = DEFAULT_METHOD; // build|clone
46  
47      public MCRRepeatBinding(String xPath, MCRBinding parent, int minRepeats, int maxRepeats, String method)
48          throws JaxenException,
49          JDOMException {
50          this(xPath, parent, method);
51  
52          while (getBoundNodes().size() < minRepeats) {
53              insert(getBoundNodes().size());
54          }
55  
56          this.maxRepeats = maxRepeats < 1 ? Integer.MAX_VALUE : maxRepeats;
57          this.maxRepeats = Math.max(this.maxRepeats, getBoundNodes().size());
58      }
59  
60      public MCRRepeatBinding(String xPath, MCRBinding parent, String method) throws JaxenException, JDOMException {
61          super(xPath, true, parent);
62          this.method = "clone".equals(method) ? "clone" : "build".equals(method) ? "build" : DEFAULT_METHOD;
63          this.maxRepeats = Integer.MAX_VALUE;
64      }
65  
66      public int getRepeatPosition() {
67          return repeatPosition;
68      }
69  
70      public MCRBinding bindRepeatPosition() throws JDOMException, JaxenException {
71          repeatPosition++;
72          return new MCRBinding(repeatPosition, this);
73      }
74  
75      public int getMaxRepeats() {
76          return maxRepeats;
77      }
78  
79      public String getMethod() {
80          return method;
81      }
82  
83      public Element getParentElement() {
84          return ((Element) getBoundNode()).getParentElement();
85      }
86  
87      @SuppressWarnings("unchecked")
88      public String getElementNameWithPredicates() throws JaxenException {
89          BaseXPath baseXPath = new BaseXPath(xPath, new DocumentNavigator());
90          Expr rootExpr = baseXPath.getRootExpr();
91          LocationPath locationPath = (LocationPath) rootExpr;
92          List<Step> steps = locationPath.getSteps();
93          Step lastStep = steps.get(steps.size() - 1);
94          return MCRNodeBuilder.simplify(lastStep.getText());
95      }
96  
97      public void swap(int pos) {
98          Element parent = getParentElement();
99          Element elementA = (Element) (getBoundNodes().get(pos - 1));
100         Element elementB = (Element) (getBoundNodes().get(pos));
101         track(MCRSwapElements.swap(parent, elementA, elementB));
102     }
103 
104     public void insert(int pos) throws JaxenException {
105         if ("build".equals(method)) {
106             Element parentElement = getParentElement();
107             Element precedingElement = (Element) (getBoundNodes().get(pos - 1));
108             int posOfPrecedingInParent = parentElement.indexOf(precedingElement);
109             int targetPos = posOfPrecedingInParent + 1;
110             String pathToBuild = getElementNameWithPredicates();
111             Element newElement = (Element) (new MCRNodeBuilder().buildNode(pathToBuild, null, null));
112             parentElement.addContent(targetPos, newElement);
113             boundNodes.add(pos, newElement);
114             track(MCRAddedElement.added(newElement));
115         } else {
116             cloneBoundElement(pos - 1);
117         }
118     }
119 }