View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.config.spring.parsers.processors;
8   
9   import org.mule.config.spring.parsers.PreProcessor;
10  import org.mule.config.spring.parsers.assembly.configuration.PropertyConfiguration;
11  import org.mule.config.spring.util.SpringXMLUtils;
12  
13  import java.util.ArrayList;
14  import java.util.Arrays;
15  import java.util.Collection;
16  import java.util.List;
17  
18  import org.w3c.dom.Attr;
19  import org.w3c.dom.Element;
20  import org.w3c.dom.NamedNodeMap;
21  
22  /**
23   * Attributes from two different sets cannot appear together
24   */
25  public class CheckExclusiveAttributes implements PreProcessor
26  {
27      private Collection<AttributeSet> attributeSets;
28  
29      public CheckExclusiveAttributes(String[][] attributeNames)
30      {
31          super();
32          
33          attributeSets = new ArrayList<AttributeSet>();
34          for (int i = 0; i < attributeNames.length; i++)
35          {
36              String[] attributes = attributeNames[i];
37              attributeSets.add(new AttributeSet(attributes));
38          }            
39      }
40  
41      public void preProcess(PropertyConfiguration config, Element element)
42      {
43          Collection<AttributeSet> allMatchingSets = new ArrayList<AttributeSet>(attributeSets);
44          boolean atLeastOneAttributeDidMatch = false;
45  
46          // itereate over all attribute names in 'element'
47          NamedNodeMap attributes = element.getAttributes();
48          int length = attributes.getLength();
49          for (int i = 0; i < length; i++)
50          {
51              String alias = SpringXMLUtils.attributeName((Attr) attributes.item(i));
52              if (isOptionalAttribute(alias))
53              {
54                  continue;
55              }
56  
57              allMatchingSets = filterMatchingSets(allMatchingSets, alias);
58              atLeastOneAttributeDidMatch = true;
59          }
60          
61          if (atLeastOneAttributeDidMatch && allMatchingSets.size() == 0)
62          {
63              CheckExclusiveAttributesException ex = 
64                  CheckExclusiveAttributesException.createForDisjunctGroups(element, attributeSets);
65            throw ex;
66  
67          }
68          else if (atLeastOneAttributeDidMatch && allMatchingSets.size() > 1)
69          {
70              CheckExclusiveAttributesException ex = 
71                  CheckExclusiveAttributesException.createForInsufficientAttributes(element, allMatchingSets);
72              throw ex;
73          }
74      }
75  
76      private Collection<AttributeSet> filterMatchingSets(Collection<AttributeSet> allMatchingSets, 
77          String attributeName)
78      {
79          Collection<AttributeSet> newMatchingSets = new ArrayList<AttributeSet>();
80          for (AttributeSet currentSet : allMatchingSets)
81          {
82              if (currentSet.containsAttribute(attributeName))
83              {
84                  newMatchingSets.add(currentSet);
85              }
86          }
87          return newMatchingSets;
88      }
89  
90      private boolean isOptionalAttribute(String name)
91      {
92          return findMatchingAttributeSets(name).size() == 0;
93      }
94  
95      private Collection<AttributeSet> findMatchingAttributeSets(String alias)
96      {
97          List<AttributeSet> matchingSets = new ArrayList<AttributeSet>();
98          for (AttributeSet currentSet : attributeSets)
99          {
100             if (currentSet.containsAttribute(alias))
101             {
102                 matchingSets.add(currentSet);
103             }
104         }
105         return matchingSets;
106     }
107 
108     private static class AttributeSet
109     {
110         private String[] attributeNames;
111 
112         public AttributeSet(String[] attributeNames)
113         {
114             super();
115             this.attributeNames = attributeNames;
116         }
117 
118         public boolean containsAttribute(String name)
119         {
120             for (int i = 0; i < attributeNames.length; i++)
121             {
122                 String element = attributeNames[i];
123                 if (element.equals(name))
124                 {
125                     return true;
126                 }
127             }
128             return false;
129         }
130 
131         @Override
132         public String toString()
133         {
134             return Arrays.toString(attributeNames);
135         }
136     }
137     
138     public static class CheckExclusiveAttributesException extends IllegalStateException
139     {
140         public static CheckExclusiveAttributesException createForDisjunctGroups(Element element,
141             Collection<AttributeSet> allMatchingSets)
142         {
143             String message = createMessage(element, allMatchingSets);
144             return new CheckExclusiveAttributesException(message);
145         }
146 
147         private static String createMessage(Element element, Collection<AttributeSet> allMatchingSets)
148         {
149             StringBuilder buf = new StringBuilder("The attributes of Element ");
150             buf.append(SpringXMLUtils.elementToString(element));
151             buf.append(" do not match the exclusive groups");
152             
153             for (AttributeSet match : allMatchingSets)
154             {
155                 buf.append(" ");
156                 buf.append(match.toString());
157             }
158             
159             return buf.toString();
160         }
161         
162         public static CheckExclusiveAttributesException createForInsufficientAttributes(Element element,
163             Collection<AttributeSet> attributeSets)
164         {
165             StringBuilder buf = new StringBuilder("Attributes of Element ");
166             buf.append(SpringXMLUtils.elementToString(element));
167             buf.append(" do not satisfy the exclusive groups");
168             
169             for (AttributeSet attributeSet : attributeSets)
170             {
171                 buf.append(" ");
172                 buf.append(attributeSet);
173             }
174             buf.append(".");
175             
176             return new CheckExclusiveAttributesException(buf.toString());
177         }
178         
179         private CheckExclusiveAttributesException(String message)
180         {
181             super(message);
182         }
183     }
184 }