1   package com.atlassian.plugins.codegen.modules.confluence.blueprint;
2   
3   import com.atlassian.plugins.codegen.ArtifactDependency;
4   import com.atlassian.plugins.codegen.ComponentDeclaration;
5   import com.atlassian.plugins.codegen.PluginProjectChangeset;
6   import com.atlassian.plugins.codegen.annotations.ConfluencePluginModuleCreator;
7   import com.atlassian.plugins.codegen.modules.AbstractPluginModuleCreator;
8   import com.atlassian.plugins.codegen.modules.BasicClassModuleProperties;
9   import com.atlassian.plugins.codegen.modules.ClassBasedModuleProperties;
10  import com.atlassian.plugins.codegen.modules.common.ContextProviderProperties;
11  import com.atlassian.plugins.codegen.modules.common.Resource;
12  import com.atlassian.plugins.codegen.modules.common.ResourcedProperties;
13  import com.atlassian.plugins.codegen.modules.common.web.WebItemModuleCreator;
14  import com.atlassian.plugins.codegen.modules.common.web.WebItemProperties;
15  import com.atlassian.plugins.codegen.modules.common.web.WebResourceModuleCreator;
16  import com.atlassian.plugins.codegen.modules.common.web.WebResourceProperties;
17  
18  import static com.atlassian.plugins.codegen.ArtifactDependency.dependency;
19  
20  /**
21   * Creates a Confluence Blueprint module and any dependent modules.
22   *
23   * @since 4.1.8
24   */
25  @ConfluencePluginModuleCreator
26  public class BlueprintModuleCreator extends AbstractPluginModuleCreator<BlueprintProperties>
27  {
28      private static final String MODULE_NAME = "Blueprint";
29      private static final String TEMPLATE_PREFIX = "templates/confluence/blueprint/";
30  
31      private static final String BLUEPRINT_MODULE_TEMPLATE = TEMPLATE_PREFIX + "plugin-module-blueprint.xml.vtl";
32      private static final String CONTENT_TEMPLATE_MODULE_TEMPLATE = TEMPLATE_PREFIX + "plugin-module-content-template.xml.vtl";
33      private static final String CONTENT_TEMPLATE_FILE_TEMPLATE = TEMPLATE_PREFIX + "resource-file-content-template.xml.vtl";
34      private static final String INDEX_PAGE_CONTENT_TEMPLATE_FILE_TEMPLATE = TEMPLATE_PREFIX + "resource-file-index-page-content-template.xml.vtl";
35      private static final String SOY_TEMPLATE_FILE_TEMPLATE = TEMPLATE_PREFIX + "resource-file-soy-template.soy.vtl";
36      private static final String JS_TEMPLATE_FILE_TEMPLATE = TEMPLATE_PREFIX + "resource-file-dialog-wizard.js.vtl";
37      private static final String CSS_TEMPLATE_FILE_TEMPLATE = TEMPLATE_PREFIX + "resource-file-blueprints.css.vtl";
38      // Template name is "jva" not "java" only to avoid IDE headaches with imports.
39      private static final String CONTEXT_PROVIDER_CLASS_TEMPLATE = TEMPLATE_PREFIX + "ContentTemplateContextProvider.jva.vtl";
40      private static final String EVENT_LISTENER_CLASS_TEMPLATE = TEMPLATE_PREFIX + "BlueprintCreatedListener.jva.vtl";
41  
42      @Override
43      public PluginProjectChangeset createModule(BlueprintProperties props) throws Exception
44      {
45          PluginProjectChangeset changeset = new PluginProjectChangeset().with(createModule(props, BLUEPRINT_MODULE_TEMPLATE));
46  
47          ArtifactDependency createContent = dependency("com.atlassian.confluence.plugins", "confluence-create-content-plugin", "1.5.23", ArtifactDependency.Scope.PROVIDED);
48          changeset = changeset.with(createContent);
49  
50          for (ContentTemplateProperties contentTemplateProperties : props.getContentTemplates())
51          {
52              changeset = changeset.with(createModule(contentTemplateProperties, CONTENT_TEMPLATE_MODULE_TEMPLATE));
53  
54              changeset = addResourceFiles(changeset, contentTemplateProperties, CONTENT_TEMPLATE_FILE_TEMPLATE);
55  
56              ContextProviderProperties contextProviderProperties = contentTemplateProperties.getContextProvider();
57              if (contextProviderProperties != null)
58              {
59                  changeset = changeset.with(createClass(contextProviderProperties, CONTEXT_PROVIDER_CLASS_TEMPLATE));
60              }
61          }
62  
63          ContentTemplateProperties indexPageContentTemplate = props.getIndexPageContentTemplate();
64          if (indexPageContentTemplate != null)
65          {
66              changeset = changeset.with(createModule(indexPageContentTemplate, CONTENT_TEMPLATE_MODULE_TEMPLATE));
67              changeset = addResourceFiles(changeset, indexPageContentTemplate, INDEX_PAGE_CONTENT_TEMPLATE_FILE_TEMPLATE);
68          }
69  
70          WebItemProperties webItem = props.getWebItem();
71          if (webItem != null)  // Only ever expected to be null for testing.
72          {
73              changeset = changeset.with(createModule(webItem, WebItemModuleCreator.PLUGIN_MODULE_TEMPLATE));
74          }
75  
76          WebResourceProperties webResource = props.getWebResource();
77          changeset = changeset.with(createModule(webResource, WebResourceModuleCreator.PLUGIN_MODULE_TEMPLATE));
78          changeset = addResourceFiles(changeset, webResource, null); // null means figure the template out...
79  
80          ComponentDeclaration eventListener = props.getEventListener();
81          if (eventListener != null)
82          {
83              changeset = changeset.with(eventListener);   // adds the <component> element
84  
85              ClassBasedModuleProperties classProps = new BasicClassModuleProperties(eventListener.getClassId().getFullName());
86              classProps.setProperty("PLUGIN_KEY", props.getPluginKey());
87              changeset = changeset.with(createClass(classProps, EVENT_LISTENER_CLASS_TEMPLATE));
88          }
89  
90          return changeset;
91      }
92  
93      private PluginProjectChangeset addResourceFiles(PluginProjectChangeset changeset,
94          ResourcedProperties properties, String givenTemplate) throws Exception
95      {
96          for (Resource resource : properties.getResources())
97          {
98              String filePath = resource.getLocation();
99              int lastSlash = filePath.lastIndexOf('/');
100             String path = filePath.substring(0, lastSlash);
101             String filename = filePath.substring(lastSlash + 1);
102 
103             String resourceFileTemplate = getResourceTemplate(givenTemplate, filename);
104             changeset = changeset.with(createResource(properties, path, filename, resourceFileTemplate));
105         }
106         return changeset;
107     }
108 
109     // This method is pretty rough. Where are my String switches?!
110     private String getResourceTemplate(String givenTemplate, String filename)
111     {
112         if (givenTemplate != null)
113             return givenTemplate;
114 
115         if (filename.endsWith(".js"))
116             return JS_TEMPLATE_FILE_TEMPLATE;
117 
118         if (filename.endsWith(".css"))
119             return CSS_TEMPLATE_FILE_TEMPLATE;
120 
121         if (filename.endsWith(".soy"))
122             return SOY_TEMPLATE_FILE_TEMPLATE;
123 
124         throw new UnsupportedOperationException("Can't render resource template for filename: " + filename);
125     }
126 
127     public String getModuleName()
128     {
129         return MODULE_NAME;
130     }
131 }