View Javadoc
1   /**
2    * This file Copyright (c) 2003-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.importexport.filters;
35  
36  import java.util.ArrayList;
37  import java.util.List;
38  
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  import org.xml.sax.Attributes;
42  import org.xml.sax.SAXException;
43  import org.xml.sax.XMLReader;
44  import org.xml.sax.helpers.AttributesImpl;
45  import org.xml.sax.helpers.XMLFilterImpl;
46  
47  
48  /**
49   * A base abstract filter that can be sub-classed in order to easily implement removal of properties based on their
50   * name/content.
51   *
52   * @deprecated since 5.4.4. Use {@link info.magnolia.importexport.command.JcrExportCommand} with {@link info.magnolia.importexport.command.JcrExportCommand.DefaultFilter} with {@link info.magnolia.jcr.predicate.PropertyFilteringPredicate} instead.
53   */
54  @Deprecated
55  public abstract class SkipNodePropertyFilter extends XMLFilterImpl {
56  
57      protected Logger log = LoggerFactory.getLogger(getClass());
58  
59      protected String lastNodeName;
60  
61      protected boolean skipProperty;
62  
63      protected boolean invalue;
64  
65      private List<BufferedElement> elementBuffer = new ArrayList<BufferedElement>();
66  
67      /**
68       * Instantiates a new filter.
69       *
70       * @param parent wrapped XMLReader
71       */
72      public SkipNodePropertyFilter(XMLReader parent) {
73          super(parent);
74      }
75  
76      /**
77       * {@inheritDoc}
78       */
79      @Override
80      public void endElement(String uri, String localName, String qName) throws SAXException {
81  
82          if (skipProperty) {
83              if ("sv:property".equals(qName)) {
84                  skipProperty = false;
85                  invalue = false;
86                  elementBuffer.clear();
87              }
88              return;
89          }
90  
91          super.endElement(uri, localName, qName);
92      }
93  
94      /**
95       * {@inheritDoc}
96       */
97      @Override
98      public void characters(char[] ch, int start, int length) throws SAXException {
99          if (!skipProperty) {
100             super.characters(ch, start, length);
101         } else {
102             if (invalue) {
103                 invalue = false;
104                 // Arrays.copyOfRange(ch, start, start + length)
105                 char[] range = new char[length];
106                 System.arraycopy(ch, start, range, 0, length);
107                 String textContent = new String(range);
108 
109                 // skip only if filter() say so
110                 boolean skip = filter(textContent, lastNodeName);
111 
112                 if (!skip) {
113                     while (!elementBuffer.isEmpty()) {
114                         BufferedElement be = elementBuffer.remove(0);
115                         super.startElement(be.getUri(), be.getLocalName(), be.getQName(), be.getAtts());
116                     }
117                     super.characters(ch, start, length);
118                     skipProperty = false;
119                 }
120             }
121 
122         }
123     }
124 
125     /**
126      * {@inheritDoc}
127      */
128     @Override
129     public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
130 
131         String svname = atts.getValue("sv:name");
132         if ("sv:node".equals(qName)) {
133             lastNodeName = svname;
134         } else if ("sv:property".equals(qName) && (getFilteredPropertyName().equals(svname))) {
135             elementBuffer.add(new BufferedElement(uri, localName, qName, new AttributesImpl(atts)));
136 
137             skipProperty = true;
138             invalue = false;
139         } else if (skipProperty && "sv:value".equals(qName)) {
140             elementBuffer.add(new BufferedElement(uri, localName, qName, new AttributesImpl(atts)));
141             invalue = true;
142         }
143 
144         if (skipProperty) {
145             return;
146         }
147         super.startElement(uri, localName, qName, atts);
148 
149     }
150 
151     /**
152      * Implement this method to specify the name of the property you want to filter.
153      *
154      * @return filtered property name
155      */
156     protected abstract String getFilteredPropertyName();
157 
158     /**
159      * Implement this method to specificy if a given property (given its value and the parent node name) should be
160      * removed.
161      *
162      * @param propertyValue property value
163      * @param parentNodeName parent node name
164      * @return <code>true</code> if this property should be removed
165      */
166     protected abstract boolean filter(String propertyValue, String parentNodeName);
167 
168     /**
169      * Temporary element storage node.
170      */
171     public static class BufferedElement {
172 
173         private String uri;
174 
175         private String localName;
176 
177         private String qName;
178 
179         private Attributes atts;
180 
181         public BufferedElement(String uri, String localName, String qName, Attributes atts) {
182             this.atts = atts;
183             this.localName = localName;
184             this.qName = qName;
185             this.uri = uri;
186         }
187 
188         /**
189          * Returns the uri.
190          *
191          * @return the uri
192          */
193         public String getUri() {
194             return uri;
195         }
196 
197         /**
198          * Sets the uri.
199          *
200          * @param uri the uri to set
201          */
202         public void setUri(String uri) {
203             this.uri = uri;
204         }
205 
206         /**
207          * Returns the localName.
208          *
209          * @return the localName
210          */
211         public String getLocalName() {
212             return localName;
213         }
214 
215         /**
216          * Sets the localName.
217          *
218          * @param localName the localName to set
219          */
220         public void setLocalName(String localName) {
221             this.localName = localName;
222         }
223 
224         /**
225          * Returns the qName.
226          *
227          * @return the qName
228          */
229         public String getQName() {
230             return qName;
231         }
232 
233         /**
234          * Sets the qName.
235          *
236          * @param name the qName to set
237          */
238         public void setQName(String name) {
239             qName = name;
240         }
241 
242         /**
243          * Returns the atts.
244          *
245          * @return the atts
246          */
247         public Attributes getAtts() {
248             return atts;
249         }
250 
251         /**
252          * Sets the atts.
253          *
254          * @param atts the atts to set
255          */
256         public void setAtts(Attributes atts) {
257             this.atts = atts;
258         }
259     }
260 }