View Javadoc
1   package org.apache.maven.shared.utils.xml;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.StringWriter;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  
30  import javax.annotation.Nonnull;
31  
32  /**
33   * A reimplementation of Plexus Xpp3Dom based on the public interface of Plexus Xpp3Dom.
34   *
35   * @author Kristian Rosenvold
36   */
37  public class Xpp3Dom
38      implements Iterable<Xpp3Dom>
39  {
40      @SuppressWarnings( "UnusedDeclaration" )
41      private static final long serialVersionUID = 2567894443061173996L;
42  
43      private String name; // plexus: protected
44  
45      private String value; // plexus: protected
46  
47      private Map<String, String> attributes; // plexus: protected
48  
49      final List<Xpp3Dom> childList; // plexus: protected
50  
51      final Map<String, Xpp3Dom> childMap; // plexus: protected
52  
53      private Xpp3Dom parent; // plexus: protected
54  
55      public static final String CHILDREN_COMBINATION_MODE_ATTRIBUTE = "combine.children";
56  
57      private static final String CHILDREN_COMBINATION_MERGE = "merge";
58  
59      public static final String CHILDREN_COMBINATION_APPEND = "append";
60  
61      @SuppressWarnings( "UnusedDeclaration" )
62      private static final String DEFAULT_CHILDREN_COMBINATION_MODE = CHILDREN_COMBINATION_MERGE; // plexus: public
63  
64      public static final String SELF_COMBINATION_MODE_ATTRIBUTE = "combine.self";
65  
66      public static final String SELF_COMBINATION_OVERRIDE = "override";  // plexus: public
67  
68      public static final String SELF_COMBINATION_MERGE = "merge";
69  
70      @SuppressWarnings( "UnusedDeclaration" )
71      private static final String DEFAULT_SELF_COMBINATION_MODE = SELF_COMBINATION_MERGE;  // plexus: public
72  
73      private static final String[] EMPTY_STRING_ARRAY = new String[0];
74      private static final Xpp3Dom[] EMPTY_DOM_ARRAY = new Xpp3Dom[0];
75  
76      public Xpp3Dom( String name )
77      {
78          this.name = name;
79          childList = new ArrayList<Xpp3Dom>();
80          childMap = new HashMap<String, Xpp3Dom>();
81      }
82  
83      public Xpp3Dom( Xpp3Dom source )
84      {
85          this( source, source.getName() );
86      }
87  
88      public Xpp3Dom( @Nonnull Xpp3Dom src, String name )
89      {
90          this.name = name;
91  
92          int size = src.getChildCount();
93          childList = new ArrayList<Xpp3Dom>( size );
94          childMap = new HashMap<String, Xpp3Dom>();
95  
96          setValue( src.getValue() );
97  
98          for ( String attributeName : src.getAttributeNames() )
99          {
100             setAttribute( attributeName, src.getAttribute( attributeName ) );
101         }
102 
103         for ( Xpp3Dom xpp3Dom : src.getChildren() )
104         {
105             addChild( new Xpp3Dom( xpp3Dom ) );
106         }
107     }
108 
109     public String getName()
110     {
111         return name;
112     }
113 
114     @Nonnull public String getValue()
115     {
116         return value;
117     }
118 
119     public void setValue( @Nonnull String value )
120     {
121         this.value = value;
122     }
123 
124 
125     public String[] getAttributeNames()
126     {
127         boolean isNothing = attributes == null || attributes.isEmpty();
128         return isNothing ? EMPTY_STRING_ARRAY :  attributes.keySet().toArray( new String[attributes.size()] );
129     }
130 
131 
132     public String getAttribute( String name )
133     {
134         return attributes != null ? attributes.get( name ) : null;
135     }
136 
137     @SuppressWarnings( "ConstantConditions" )
138     public void setAttribute( @Nonnull String name, @Nonnull String value )
139     {
140         if ( value == null )
141         {
142             throw new NullPointerException( "value can not be null" );
143         }
144         if ( name == null )
145         {
146             throw new NullPointerException( "name can not be null" );
147         }
148         if ( attributes == null )
149         {
150             attributes = new HashMap<String, String>();
151         }
152 
153         attributes.put( name, value );
154     }
155 
156     public Xpp3Dom getChild( int i )
157     {
158         return childList.get( i );
159     }
160 
161     public Xpp3Dom getChild( String name )
162     {
163         return childMap.get( name );
164     }
165 
166     public void addChild( Xpp3Dom child )
167     {
168         child.setParent( this );
169         childList.add( child );
170         childMap.put( child.getName(), child );
171     }
172 
173     public Xpp3Dom[] getChildren()
174     {
175         boolean isNothing = childList == null || childList.isEmpty();
176         return isNothing ? EMPTY_DOM_ARRAY : childList.toArray( new Xpp3Dom[childList.size()] );
177     }
178 
179     private List<Xpp3Dom> getChildrenList()
180     {
181         boolean isNothing = childList == null || childList.isEmpty();
182         return isNothing ? Collections.<Xpp3Dom>emptyList() : childList;
183     }
184 
185     public Xpp3Dom[] getChildren( String name )
186     {
187         List<Xpp3Dom> children = getChildrenList( name );
188         return children.toArray( new Xpp3Dom[children.size()] );
189     }
190 
191     List<Xpp3Dom> getChildrenList( String name )
192     {
193         if ( childList == null )
194         {
195             return Collections.emptyList();
196         }
197         else
198         {
199             ArrayList<Xpp3Dom> children = new ArrayList<Xpp3Dom>();
200             for ( Xpp3Dom aChildList : childList )
201             {
202                 if ( name.equals( aChildList.getName() ) )
203                 {
204                     children.add( aChildList );
205                 }
206             }
207             return children;
208         }
209     }
210 
211     public int getChildCount()
212     {
213         if ( childList == null )
214         {
215             return 0;
216         }
217 
218         return childList.size();
219     }
220 
221     public void removeChild( int i )
222     {
223         Xpp3Dom child = childList.remove( i );
224         childMap.values().remove( child );
225         child.setParent( null );
226     }
227 
228     public Xpp3Dom getParent()
229     {
230         return parent;
231     }
232 
233     public void setParent( Xpp3Dom parent )
234     {
235        this.parent = parent;
236     }
237 
238     // Todo: Support writing to serializer (>1.0)
239   //  public void writeToSerializer( String namespace, XmlSerializer serializer )
240     //        throws IOException
241 
242     private static Xpp3Dom merge( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride )
243     {
244         return Xpp3DomUtils.merge( dominant, recessive, childMergeOverride );
245     }
246 
247     public static Xpp3Dom mergeXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride )
248     {
249         return Xpp3DomUtils.mergeXpp3Dom( dominant, recessive, childMergeOverride );
250     }
251 
252     public static Xpp3Dom mergeXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive )
253     {
254         return Xpp3DomUtils.mergeXpp3Dom( dominant, recessive );
255     }
256 
257     public boolean equals( Object obj )
258     {
259         if ( obj == this )
260         {
261             return true;
262         }
263 
264         if ( !( obj instanceof Xpp3Dom ) )
265         {
266             return false;
267         }
268 
269         Xpp3Dom dom = (Xpp3Dom) obj;
270 
271         return !( name == null ? dom.name != null : !name.equals( dom.name ) )
272             && !( value == null ? dom.value != null : !value.equals( dom.value ) )
273             && !( attributes == null ? dom.attributes != null : !attributes.equals( dom.attributes ) )
274             && !( childList == null ? dom.childList != null : !childList.equals( dom.childList ) );
275     }
276 
277     public int hashCode()
278     {
279         int result = 17;
280         result = 37 * result + ( name != null ? name.hashCode() : 0 );
281         result = 37 * result + ( value != null ? value.hashCode() : 0 );
282         result = 37 * result + ( attributes != null ? attributes.hashCode() : 0 );
283         result = 37 * result + ( childList != null ? childList.hashCode() : 0 );
284         return result;
285     }
286 
287     public String toString()
288     {
289         StringWriter writer = new StringWriter();
290         Xpp3DomWriter.write( getPrettyPrintXMLWriter( writer ), this );
291         return writer.toString();
292 
293     }
294 
295     public String toUnescapedString()
296     {
297         StringWriter writer = new StringWriter();
298         Xpp3DomWriter.write( getPrettyPrintXMLWriter( writer ), this, false );
299         return writer.toString();
300     }
301 
302     private PrettyPrintXMLWriter getPrettyPrintXMLWriter( StringWriter writer )
303     {
304         return new PrettyPrintXMLWriter( writer, "UTF-8", null );
305     }
306 
307     public static boolean isNotEmpty( String str )
308     {
309         return str != null && str.length() > 0;
310     }
311 
312     public static boolean isEmpty( String str )
313     {
314         return str == null || str.trim().length() == 0;
315     }
316 
317     public Iterator<Xpp3Dom> iterator()
318     {
319         return getChildrenList().iterator();
320     }
321 }