View Javadoc

1   package com.atlassian.plugin.web;
2   
3   import com.atlassian.plugin.PluginManager;
4   import com.atlassian.plugin.PluginAccessor;
5   import com.atlassian.plugin.web.descriptors.*;
6   
7   import java.util.*;
8   
9   import com.atlassian.plugin.web.model.WebPanel;
10  import com.google.common.base.Function;
11  import com.google.common.collect.Lists;
12  import org.slf4j.Logger;
13  import org.slf4j.LoggerFactory;
14  
15  /**
16   * Stores and manages flexible web interface sections available in the system.
17   */
18  public class DefaultWebInterfaceManager implements WebInterfaceManager
19  {
20      private PluginAccessor pluginAccessor;
21      private WebFragmentHelper webFragmentHelper;
22      private Map<String, List<WebSectionModuleDescriptor>> sections;
23      private Map<String, List<WebItemModuleDescriptor>> items;
24      private Map<String, List<WebPanelModuleDescriptor>> panels;
25      private static final Logger log = LoggerFactory.getLogger(DefaultWebInterfaceManager.class);
26  
27      public static final WeightedDescriptorComparator WEIGHTED_DESCRIPTOR_COMPARATOR = new WeightedDescriptorComparator();
28  
29      public DefaultWebInterfaceManager()
30      {
31          refresh();
32      }
33  
34      public DefaultWebInterfaceManager(PluginAccessor pluginAccessor, WebFragmentHelper webFragmentHelper)
35      {
36          this.pluginAccessor = pluginAccessor;
37          this.webFragmentHelper = webFragmentHelper;
38          refresh();
39      }
40  
41      public boolean hasSectionsForLocation(String location)
42      {
43          return !getSections(location).isEmpty();
44      }
45  
46      public List<WebSectionModuleDescriptor> getSections(String location)
47      {
48          if (location == null)
49          {
50              return Collections.emptyList();
51          }
52  
53          List<WebSectionModuleDescriptor> result = sections.get(location);
54  
55          if (result == null)
56          {
57              result = new ArrayList<WebSectionModuleDescriptor>(); // use a tree map so we get nice weight sorting
58              List<WebSectionModuleDescriptor> descriptors = pluginAccessor.getEnabledModuleDescriptorsByClass(WebSectionModuleDescriptor.class);
59              for (WebSectionModuleDescriptor descriptor : descriptors) {
60                  if (location.equalsIgnoreCase(descriptor.getLocation()))
61                      result.add(descriptor);
62              }
63  
64              Collections.sort(result, WEIGHTED_DESCRIPTOR_COMPARATOR);
65              sections.put(location, result);
66          }
67  
68          return result;
69      }
70  
71      public List<WebSectionModuleDescriptor> getDisplayableSections(String location, Map<String,Object> context)
72      {
73          return filterFragmentsByCondition(getSections(location), context);
74      }
75  
76      public List<WebItemModuleDescriptor> getItems(String section)
77      {
78          if (section == null)
79          {
80              return Collections.emptyList();
81          }
82  
83          List<WebItemModuleDescriptor> result = items.get(section);
84  
85          if (result == null)
86          {
87              result = new ArrayList<WebItemModuleDescriptor>(); // use a tree map so we get nice weight sorting
88              List<WebItemModuleDescriptor> descriptors = pluginAccessor.getEnabledModuleDescriptorsByClass(WebItemModuleDescriptor.class);
89              for (WebItemModuleDescriptor descriptor : descriptors) {
90                  if (section.equalsIgnoreCase(descriptor.getSection()))
91                      result.add(descriptor);
92              }
93  
94              Collections.sort(result, WEIGHTED_DESCRIPTOR_COMPARATOR);
95              items.put(section, result);
96          }
97  
98          return result;
99      }
100 
101     public List<WebItemModuleDescriptor> getDisplayableItems(String section, Map<String,Object> context)
102     {
103         return filterFragmentsByCondition(getItems(section), context);
104     }
105 
106     public List<WebPanel> getDisplayableWebPanels(String location, Map<String, Object> context)
107     {
108         return toWebPanels(getDisplayableWebPanelDescriptors(location, context));
109     }
110 
111     public List<WebPanelModuleDescriptor> getDisplayableWebPanelDescriptors(String location, Map<String, Object> context)
112     {
113         return filterFragmentsByCondition(getWebPanelDescriptors(location), context);
114     }
115 
116     public List<WebPanel> getWebPanels(String location)
117     {
118         return toWebPanels(getWebPanelDescriptors(location));
119     }
120 
121     private List<WebPanel> toWebPanels(List<WebPanelModuleDescriptor> descriptors)
122     {
123         return Lists.transform(descriptors, new Function<WebPanelModuleDescriptor, WebPanel>()
124         {
125             public WebPanel apply(WebPanelModuleDescriptor from)
126             {
127                 return from.getModule();
128             }
129         });
130     }
131 
132     public List<WebPanelModuleDescriptor> getWebPanelDescriptors(String location)
133     {
134         if (location == null)
135         {
136             return Collections.emptyList();
137         }
138         else
139         {
140             List<WebPanelModuleDescriptor> result = panels.get(location);
141             if (result == null) {
142                 result = new ArrayList<WebPanelModuleDescriptor>(); // use a tree map so we get nice weight sorting
143 
144                 List<WebPanelModuleDescriptor> descriptors = pluginAccessor.getEnabledModuleDescriptorsByClass(WebPanelModuleDescriptor.class);
145                 for (WebPanelModuleDescriptor descriptor : descriptors)
146                 {
147                     if (location.equalsIgnoreCase(descriptor.getLocation()))
148                     {
149                         result.add(descriptor);
150                     }
151                 }
152                 Collections.sort(result, WEIGHTED_DESCRIPTOR_COMPARATOR);
153                 panels.put(location, result);
154             }
155             return result;
156         }
157     }
158 
159     private <T extends ConditionalDescriptor> List<T> filterFragmentsByCondition(List<T> relevantItems, Map<String,Object> context)
160     {
161         if (relevantItems.isEmpty())
162         {
163             return relevantItems;
164         }
165 
166         List<T> result = new ArrayList<T>(relevantItems);
167         for (Iterator<T> iterator = result.iterator(); iterator.hasNext();)
168         {
169             ConditionalDescriptor descriptor = iterator.next();
170             try
171             {
172                 if (descriptor.getCondition() != null && !descriptor.getCondition().shouldDisplay(context))
173                 {
174                     iterator.remove();
175                 }
176             }
177             catch (Throwable t)
178             {
179                 log.error("Could not evaluate condition '" + descriptor.getCondition() + "' for descriptor: " + descriptor, t);
180                 iterator.remove();
181             }
182         }
183 
184         return result;
185     }
186 
187     public void refresh()
188     {
189         sections = Collections.synchronizedMap(new HashMap<String, List<WebSectionModuleDescriptor>>());
190         items = Collections.synchronizedMap(new HashMap<String, List<WebItemModuleDescriptor>>());
191         panels = Collections.synchronizedMap(new HashMap<String, List<WebPanelModuleDescriptor>>());
192     }
193 
194     /**
195      * @deprecated since 2.2.0, use {@link #setPluginAccessor(PluginAccessor)} instead
196      * @param pluginManager
197      */
198     @Deprecated
199     public void setPluginManager(PluginManager pluginManager)
200     {
201         setPluginAccessor(pluginManager);
202     }
203 
204     /**
205      * @param pluginAccessor The plugin accessor to set
206      * @since 2.2.0
207      */
208     public void setPluginAccessor(PluginAccessor pluginAccessor)
209     {
210         this.pluginAccessor = pluginAccessor;
211     }
212 
213     public void setWebFragmentHelper(WebFragmentHelper webFragmentHelper)
214     {
215         this.webFragmentHelper = webFragmentHelper;
216     }
217 
218     public WebFragmentHelper getWebFragmentHelper()
219     {
220         return webFragmentHelper;
221     }
222 
223 }