View Javadoc

1   /*
2    * $Id: CheckAnnotatedTestCase.java 23269 2011-10-27 21:08:47Z mike.schilling $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  package org.mule.config.spring;
11  
12  
13  import org.mule.tck.junit4.AbstractMuleTestCase;
14  import org.mule.util.IOUtils;
15  import org.w3c.dom.Document;
16  
17  import javax.xml.parsers.DocumentBuilder;
18  import javax.xml.parsers.DocumentBuilderFactory;
19  import org.junit.Test;
20  
21  import static org.junit.Assert.assertFalse;
22  import static org.junit.Assert.assertNotNull;
23  import static org.junit.Assert.assertNotSame;
24  import static org.junit.Assert.fail;
25  
26  import org.w3c.dom.Element;
27  import org.w3c.dom.Node;
28  
29  import java.io.InputStream;
30  import java.util.HashSet;
31  import java.util.Set;
32  
33  /**
34   * Check that all top-level elements (direct children of Mule) are instances of
35   * "annotatedType"
36   */
37  public class CheckAnnotatedTestCase extends AbstractMuleTestCase
38  {
39      private Document schema;
40      private Element  top;
41      private Set<String> annotated = new HashSet<String>();
42      private static final String annotatedType = "annotatedType";
43      private static final String annotatedMixedContentType = "annotatedMixedContentType";
44  
45      // Add base annotated types
46      {
47          annotated.add(annotatedType);
48          annotated.add(annotatedMixedContentType);
49      }
50  
51      // Stdio will never support services or models
52      private Set<String> allowedExceptions = new HashSet<String>();
53      {
54          allowedExceptions.add("abstractModelType");
55      }
56  
57      /**
58       * Check that all direct mule-specific children of the <mule/> element support Studio annotations
59       */
60      @Test
61      public void testElementTypes() throws Exception
62      {
63          schema = createDOM(this.getClass().getClassLoader().getResourceAsStream("META-INF/mule.xsd"));
64          top = schema.getDocumentElement();
65          Element muleRootElements = findElement(top, "group", "muleRootElements");
66          assertNotNull(muleRootElements);
67          Set<Element> muleChildren = collectElementChildren(muleRootElements);
68          for (Element elm : muleChildren)
69          {
70              checkElementTypeIsAnnotated(elm);
71          }
72      }
73  
74      /**
75       * Check a single element defined in the schema
76       */
77      private void checkElementTypeIsAnnotated(Element elm)
78      {
79          Element type = getType(elm);
80          checkTypeIsAnnotated(type);
81      }
82  
83      /**
84       * check a single type defined in the schema
85       */
86      private void checkTypeIsAnnotated(Element type)
87      {
88          String typeName = type.getAttribute("name");
89          if (annotated.contains(typeName) || allowedExceptions.contains(typeName))
90          {
91              return;
92          }
93          Element complexContent = findChild(type, "complexContent");
94          Element extension = findChild(complexContent, "extension");
95          String base = extension.getAttribute("base");
96          assertFalse(base.equals(""));
97          checkTypeIsAnnotated(findElement(top, "complexType", base));
98          annotated.add(typeName);
99      }
100 
101     /**
102      * Get the type from the schema
103      */
104     private Element getType(Element elm)
105     {
106         if (!elm.getAttribute("type").equals(""))
107         {
108             return findElement(top, "complexType", elm.getAttribute("type"));
109         }
110         return findChild(elm, "complexType");
111     }
112 
113     /**
114      * Create a DOM from an input stream
115      */
116     private Document createDOM(InputStream input) throws Exception
117     {
118         try
119         {
120             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
121             factory.setNamespaceAware(true);
122             DocumentBuilder builder = factory.newDocumentBuilder();
123             return builder.parse(input);
124         }
125         finally
126         {
127             IOUtils.closeQuietly(input);
128         }
129     }
130 
131     /**
132      * Find a child element in the schema
133      */
134     private Element findElement(Element parent, String type, String name)
135     {
136         for (Node node = parent.getFirstChild(); node != null; node = node.getNextSibling())
137         {
138             if (node instanceof Element && type.equals(node.getLocalName()) &&
139                 ((Element)node).getAttribute("name").equals(name))
140             {
141                 return (Element)node;
142             }
143         }
144         return null;
145     }
146 
147     /**
148      * Find an element, possibly traversing a reference
149      */
150     private Element findElement(Element elm)
151     {
152         if (!elm.getAttribute("name").equals(""))
153         {
154             return elm;
155         }
156         else
157         {
158             return findElement(top, elm.getLocalName(), elm.getAttribute("ref"));
159         }
160     }
161 
162     /**
163      * Collect all the children of an element
164      */
165     private Set<Element> collectElementChildren(Element parent)
166     {
167         Set<Element> children = new HashSet<Element>();
168         for (Node node = parent.getFirstChild(); node != null; node = node.getNextSibling())
169         {
170             if (node instanceof Element)
171             {
172                 Element elm = (Element) node;
173                 if("element".equals(node.getLocalName()))
174                 {
175                     children.add(findElement(elm));
176                 }
177                 else if ("sequence".equals(node.getLocalName()) ||
178                     "choice".equals(node.getLocalName()) ||
179                     "group".equals(node.getLocalName()))
180                 {
181                     Set<Element> elms = collectElementChildren(elm);
182                      for (Element e : elms)
183                      {
184                          children.add(findElement(e));
185                      }
186                 }
187             }
188         }
189 
190         return children;
191     }
192 
193     /**
194      * Find an element child of an element
195      */
196     private Element findChild(Element parent, String localName)
197     {
198         for (Node node = parent.getFirstChild(); node != null; node = node.getNextSibling())
199         {
200             if (localName.equals(node.getLocalName()))
201             {
202                 return (Element) node;
203             }
204         }
205         fail("Cannot find child " + localName + " for " + parent.getAttribute("name"));
206         return null;
207     }
208 }