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.util.HashMap;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Map;
26  
27  /**
28   * 
29   */
30  public class Xpp3DomUtils
31  {
32      /**
33       * @param dominant {@link Xpp3Dom}
34       * @param recessive {@link Xpp3Dom}
35       * @param childMergeOverride true/false.
36       * @return Merged dom.
37       */
38      public static Xpp3Dom mergeXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride )
39      {
40          return dominant != null ? merge( dominant, recessive, childMergeOverride ) : recessive;
41      }
42  
43      /**
44       * @param dominant {@link Xpp3Dom}
45       * @param recessive {@link Xpp3Dom}
46       * @return Merged dom.
47       */
48      public static Xpp3Dom mergeXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive )
49      {
50          return dominant != null ? merge( dominant, recessive, null ) : recessive;
51      }
52  
53      /**
54       * @param dominant {@link Xpp3Dom}
55       * @param recessive {@link Xpp3Dom}
56       * @param childMergeOverride true/false.
57       * @return Merged dom.
58       */
59      public static Xpp3Dom merge( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride )
60      {
61          if ( recessive == null || isCombineSelfOverride( dominant ) )
62          {
63              return dominant;
64          }
65  
66          if ( isEmpty( dominant.getValue() ) )
67          {
68              dominant.setValue( recessive.getValue() );
69          }
70  
71          for ( String attr : recessive.getAttributeNames() )
72          {
73              if ( isEmpty( dominant.getAttribute( attr ) ) )
74              {
75                  dominant.setAttribute( attr, recessive.getAttribute( attr ) );
76              }
77          }
78  
79          if ( recessive.getChildCount() > 0 )
80          {
81              boolean mergeChildren = isMergeChildren( dominant, childMergeOverride );
82  
83              if ( mergeChildren )
84              {
85                  Map<String, Iterator<Xpp3Dom>> commonChildren = getCommonChildren( dominant, recessive );
86                  for ( Xpp3Dom recessiveChild : recessive )
87                  {
88                      Iterator<Xpp3Dom> it = commonChildren.get( recessiveChild.getName() );
89                      if ( it == null )
90                      {
91                          dominant.addChild( new Xpp3Dom( recessiveChild ) );
92                      }
93                      else if ( it.hasNext() )
94                      {
95                          Xpp3Dom dominantChild = it.next();
96                          merge( dominantChild, recessiveChild, childMergeOverride );
97                      }
98                  }
99              }
100             else
101             {
102                 Xpp3Dom[] dominantChildren = dominant.getChildren();
103                 dominant.childList.clear();
104                 for ( Xpp3Dom child : recessive )
105                 {
106                     dominant.addChild( new Xpp3Dom( child ) );
107                 }
108 
109                 for ( Xpp3Dom aDominantChildren : dominantChildren )
110                 {
111                     dominant.addChild( aDominantChildren );
112                 }
113             }
114         }
115         return dominant;
116     }
117 
118     private static Map<String, Iterator<Xpp3Dom>> getCommonChildren( Xpp3Dom dominant, Xpp3Dom recessive )
119     {
120         Map<String, Iterator<Xpp3Dom>> commonChildren = new HashMap<String, Iterator<Xpp3Dom>>();
121 
122         for ( String childName : recessive.childMap.keySet() )
123         {
124             List<Xpp3Dom> dominantChildren = dominant.getChildrenList( childName );
125             if ( dominantChildren.size() > 0 )
126             {
127                 commonChildren.put( childName, dominantChildren.iterator() );
128             }
129         }
130         return commonChildren;
131     }
132 
133     private static boolean isCombineSelfOverride( Xpp3Dom xpp3Dom )
134     {
135         String selfMergeMode = xpp3Dom.getAttribute( Xpp3Dom.SELF_COMBINATION_MODE_ATTRIBUTE );
136         return Xpp3Dom.SELF_COMBINATION_OVERRIDE.equals( selfMergeMode );
137     }
138 
139     private static boolean isMergeChildren( Xpp3Dom dominant, Boolean override )
140     {
141         return override != null ? override : !isMergeChildren( dominant );
142     }
143 
144     private static boolean isMergeChildren( Xpp3Dom dominant )
145     {
146         return Xpp3Dom.CHILDREN_COMBINATION_APPEND.equals(
147             dominant.getAttribute( Xpp3Dom.CHILDREN_COMBINATION_MODE_ATTRIBUTE ) );
148     }
149 
150     /**
151      * @param str The string to be checked.
152      * @return <code>true</code> in case string is empty <code>false</code> otherwise.
153      */
154     public static boolean isEmpty( String str )
155     {
156         return str == null || str.trim().length() == 0;
157     }
158 
159 
160 
161 
162 }