View Javadoc
1   /**
2    * This file Copyright (c) 2003-2015 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  public abstract class SkipNodePropertyFilter extends XMLFilterImpl {
53  
54      protected Logger log = LoggerFactory.getLogger(getClass());
55  
56      protected String lastNodeName;
57  
58      protected boolean skipProperty;
59  
60      protected boolean invalue;
61  
62      private List<BufferedElement> elementBuffer = new ArrayList<BufferedElement>();
63  
64      /**
65       * Instantiates a new filter.
66       * @param parent wrapped XMLReader
67       */
68      public SkipNodePropertyFilter(XMLReader parent) {
69          super(parent);
70      }
71  
72      /**
73       * {@inheritDoc}
74       */
75      @Override
76      public void endElement(String uri, String localName, String qName) throws SAXException {
77  
78          if (skipProperty) {
79              if ("sv:property".equals(qName)) {
80                  skipProperty = false;
81                  invalue = false;
82                  elementBuffer.clear();
83              }
84              return;
85          }
86  
87          super.endElement(uri, localName, qName);
88      }
89  
90      /**
91       * {@inheritDoc}
92       */
93      @Override
94      public void characters(char[] ch, int start, int length) throws SAXException {
95          if (!skipProperty) {
96              super.characters(ch, start, length);
97          }
98          else {
99              if (invalue) {
100                 invalue = false;
101                 // Arrays.copyOfRange(ch, start, start + length)
102                 char[] range = new char[length];
103                 System.arraycopy(ch, start, range, 0, length);
104                 String textContent = new String(range);
105 
106                 // skip only if filter() say so
107                 boolean skip = filter(textContent, lastNodeName);
108 
109                 if (!skip) {
110                     while (!elementBuffer.isEmpty()) {
111                         BufferedElement be = elementBuffer.remove(0);
112                         super.startElement(be.getUri(), be.getLocalName(), be.getQName(), be.getAtts());
113                     }
114                     super.characters(ch, start, length);
115                     skipProperty = false;
116                 }
117             }
118 
119         }
120     }
121 
122     /**
123      * {@inheritDoc}
124      */
125     @Override
126     public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
127 
128         String svname = atts.getValue("sv:name");
129         if ("sv:node".equals(qName)) {
130             lastNodeName = svname;
131         }
132         else if ("sv:property".equals(qName) && (getFilteredPropertyName().equals(svname))) {
133             elementBuffer.add(new BufferedElement(uri, localName, qName, new AttributesImpl(atts)));
134 
135             skipProperty = true;
136             invalue = false;
137         }
138         else if (skipProperty && "sv:value".equals(qName)) {
139             elementBuffer.add(new BufferedElement(uri, localName, qName, new AttributesImpl(atts)));
140             invalue = true;
141         }
142 
143         if (skipProperty) {
144             return;
145         }
146         super.startElement(uri, localName, qName, atts);
147 
148     }
149 
150     /**
151      * Implement this method to specify the name of the property you want to filter.
152      * @return filtered property name
153      */
154     protected abstract String getFilteredPropertyName();
155 
156     /**
157      * Implement this method to specificy if a given property (given its value and the parent node name) should be
158      * removed.
159      * @param propertyValue property value
160      * @param parentNodeName parent node name
161      * @return <code>true</code> if this property should be removed
162      */
163     protected abstract boolean filter(String propertyValue, String parentNodeName);
164 
165     /**
166      * Temporary element storage node.
167      */
168     public static class BufferedElement {
169 
170         private String uri;
171 
172         private String localName;
173 
174         private String qName;
175 
176         private Attributes atts;
177 
178         public BufferedElement(String uri, String localName, String qName, Attributes atts) {
179             this.atts = atts;
180             this.localName = localName;
181             this.qName = qName;
182             this.uri = uri;
183         }
184 
185         /**
186          * Returns the uri.
187          * @return the uri
188          */
189         public String getUri() {
190             return uri;
191         }
192 
193         /**
194          * Sets the uri.
195          * @param uri the uri to set
196          */
197         public void setUri(String uri) {
198             this.uri = uri;
199         }
200 
201         /**
202          * Returns the localName.
203          * @return the localName
204          */
205         public String getLocalName() {
206             return localName;
207         }
208 
209         /**
210          * Sets the localName.
211          * @param localName the localName to set
212          */
213         public void setLocalName(String localName) {
214             this.localName = localName;
215         }
216 
217         /**
218          * Returns the qName.
219          * @return the qName
220          */
221         public String getQName() {
222             return qName;
223         }
224 
225         /**
226          * Sets the qName.
227          * @param name the qName to set
228          */
229         public void setQName(String name) {
230             qName = name;
231         }
232 
233         /**
234          * Returns the atts.
235          * @return the atts
236          */
237         public Attributes getAtts() {
238             return atts;
239         }
240 
241         /**
242          * Sets the atts.
243          * @param atts the atts to set
244          */
245         public void setAtts(Attributes atts) {
246             this.atts = atts;
247         }
248     }
249 }