1   package com.atlassian.plugins.codegen.util;
2   
3   import java.io.File;
4   import java.io.FileInputStream;
5   import java.io.FileOutputStream;
6   import java.io.IOException;
7   import java.io.InputStream;
8   import java.io.OutputStream;
9   import java.io.OutputStreamWriter;
10  import java.util.List;
11  import java.util.Map;
12  
13  import com.atlassian.plugins.codegen.ClassId;
14  import com.atlassian.plugins.codegen.ComponentDeclaration;
15  import com.atlassian.plugins.codegen.ComponentImport;
16  
17  import org.apache.commons.lang.Validate;
18  import org.dom4j.Document;
19  import org.dom4j.DocumentException;
20  import org.dom4j.DocumentHelper;
21  import org.dom4j.Element;
22  import org.dom4j.Node;
23  import org.dom4j.io.OutputFormat;
24  import org.dom4j.io.SAXReader;
25  import org.dom4j.io.XMLWriter;
26  
27  import static org.apache.commons.io.IOUtils.closeQuietly;
28  
29  /**
30   *
31   */
32  public class PluginXmlHelper
33  {
34      private final Document document;
35  
36      public PluginXmlHelper(File pluginXml) throws DocumentException, IOException
37      {
38          this(new FileInputStream(pluginXml));
39      }
40  
41      public PluginXmlHelper(InputStream input) throws DocumentException, IOException
42      {
43          Validate.notNull(input);
44  
45          this.document = createDocument(input);
46      }
47      
48      public void addModuleAsLastChild(String fragment) throws DocumentException
49      {
50          Document fragDoc = DocumentHelper.parseText(fragment);
51          Element pluginRoot = document.getRootElement();
52          pluginRoot.add(fragDoc.getRootElement());
53      }
54  
55      public void addI18nResource(String name) throws DocumentException, IOException
56      {
57          String xpath = "//resource[@type='i18n' and @location='" + name + "']";
58          Node resourceNode = document.selectSingleNode(xpath);
59  
60          if (null == resourceNode)
61          {
62              Element pluginRoot = document.getRootElement();
63              Document fragDoc = DocumentHelper.parseText("<resource type=\"i18n\" name=\"i18n\" location=\"" + name + "\" />");
64              pluginRoot.add(fragDoc.getRootElement());
65          }
66      }
67  
68      public void addPluginInfoParam(String name, String value)
69      {
70          Element pluginInfo = (Element) document.selectSingleNode("//plugin-info");
71          if (pluginInfo == null)
72          {
73              pluginInfo = document.addElement("plugin-info");
74          }
75          pluginInfo.addElement("param").addAttribute("name", name).setText(value);
76      }
77      
78      public void addComponentImport(ComponentImport componentImport) throws DocumentException
79      {
80          String key = componentImport.getKey().getOrElse(createKeyFromClass(componentImport.getInterfaceClass()));
81          Element element = createModule("component-import");
82          element.addAttribute("key", key);
83          element.addAttribute("interface", componentImport.getInterfaceClass().getFullName());
84          for (String filter : componentImport.getFilter())
85          {
86              element.addAttribute("filter", filter);
87          }
88      }
89      
90      public void addComponentDeclaration(ComponentDeclaration component) throws DocumentException
91      {
92          Element element = createModule("component");
93          element.addAttribute("key", component.getKey());
94          element.addAttribute("class", component.getClassId().getFullName());
95          for (String name : component.getName())
96          {
97              element.addAttribute("name", name);
98          }
99          for (String nameI18nKey : component.getNameI18nKey())
100         {
101             element.addAttribute("i18n-name-key", nameI18nKey);
102         }
103         if (component.getVisibility() == ComponentDeclaration.Visibility.PUBLIC)
104         {
105             element.addAttribute("public", "true");
106         }
107         for (String alias : component.getAlias())
108         {
109             element.addAttribute("alias", alias);
110         }
111         for (String description : component.getDescription())
112         {
113             Element eDesc = element.addElement("description");
114             eDesc.setText(description);
115             for (String descI18nKey : component.getDescriptionI18nKey())
116             {
117                 eDesc.addAttribute("key", descI18nKey);
118             }
119         }
120         for (ClassId interfaceId : component.getInterfaceId())
121         {
122             element.addElement("interface").setText(interfaceId.getFullName());
123         }
124         if (!component.getServiceProperties().isEmpty())
125         {
126             Element eProps = element.addElement("service-properties");
127             for (Map.Entry<String, String> entry : component.getServiceProperties().entrySet())
128             {
129                 Element eEntry = eProps.addElement("entry");
130                 eEntry.addAttribute("key", entry.getKey());
131                 eEntry.addAttribute("value", entry.getValue());
132             }
133         }
134     }
135     
136     protected String createKeyFromClass(ClassId classId)
137     {
138         return lowercaseFirst(classId.getName());
139     }
140     
141     protected String lowercaseFirst(String input)
142     {
143         return input.equals("") ? input : (input.substring(0, 1).toLowerCase() + input.substring(1));
144     }
145     
146     public String getPluginXmlAsString()
147     {
148         return document.asXML();
149     }
150 
151     protected Document getDocument()
152     {
153         return document;
154     }
155 
156     protected Document createDocument(final InputStream source) throws DocumentException, IOException
157     {
158         final SAXReader reader = new SAXReader();
159         reader.setMergeAdjacentText(true);
160         reader.setStripWhitespaceText(false);
161         return reader.read(source);
162     }
163     
164     protected Element createModule(String type)
165     {
166         Element newElement = document.getRootElement().addElement(type);
167         List existingModules = document.getRootElement().elements(type);
168         if (!existingModules.isEmpty())
169         {
170             newElement.detach();
171             existingModules.add(newElement);
172         }
173         return newElement;
174     }
175     
176     public void savePluginXml(File file) throws IOException
177     {
178         FileOutputStream out = new FileOutputStream(file);
179         try
180         {
181             savePluginXml(out);
182         }
183         finally
184         {
185             closeQuietly(out);
186         }
187     }
188     
189     public void savePluginXml(OutputStream out) throws IOException
190     {
191         OutputFormat format = OutputFormat.createPrettyPrint();
192         XMLWriter writer = new XMLWriter(new OutputStreamWriter(out), format);
193         try
194         {
195             writer.write(document);
196         }
197         finally
198         {
199             writer.close();
200         }
201     }
202 }