View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.page.document.proxy;
18  
19  import java.lang.reflect.Method;
20  import java.lang.reflect.Proxy;
21  import java.util.ArrayList;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Collections;
25  
26  import org.apache.jetspeed.om.folder.Folder;
27  import org.apache.jetspeed.om.folder.MenuDefinition;
28  import org.apache.jetspeed.page.document.Node;
29  import org.apache.jetspeed.portalsite.view.SiteView;
30  import org.apache.jetspeed.portalsite.view.SiteViewMenuDefinitionLocator;
31  import org.apache.jetspeed.portalsite.view.SiteViewProxy;
32  
33  /***
34   * This class proxies Node instances to create a logical
35   * view of site content.
36   * 
37   * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
38   * @version $Id: NodeProxy.java 516448 2007-03-09 16:25:47Z ate $
39   */
40  public abstract class NodeProxy extends SiteViewProxy
41  {
42      /***
43       * *_METHOD - Node method constants
44       */
45      protected static final Method EQUALS_METHOD = reflectMethod(Object.class, "equals", new Class[]{Object.class});
46      protected static final Method GET_PARENT_METHOD = reflectMethod(Node.class, "getParent", null);
47      protected static final Method GET_PATH_METHOD = reflectMethod(Node.class, "getPath", null);
48      protected static final Method GET_URL_METHOD = reflectMethod(Node.class, "getUrl", null);
49      protected static final Method HASH_CODE_METHOD = reflectMethod(Object.class, "hashCode", null);
50      protected static final Method IS_HIDDEN_METHOD = reflectMethod(Node.class, "isHidden", null);
51      protected static final Method TO_STRING_METHOD = reflectMethod(Object.class, "toString", null);
52  
53      /***
54       * parent - view parent proxy folder instance
55       */
56      private Folder parent;
57  
58      /***
59       * path - view path
60       */
61      private String path;
62  
63      /***
64       * hidden - hidden status of this or parent node
65       */
66      private boolean hidden;
67  
68      /***
69       * menuDefinitionLocators - menu definitions aggregated by name saved in
70       *                          menu definition locators
71       */
72      private List menuDefinitionLocators;
73  
74      /***
75       * menuDefinitionLocatorsAggregated - boolean flag to indicate
76       *                                    menuDefinitionLocators aggregated
77       */
78      private boolean menuDefinitionLocatorsAggregated;
79  
80      /***
81       * menuDefinitions - menu definitions aggregated by name
82       */
83      private List menuDefinitions;
84  
85      /***
86       * menuDefinitionsAggregated - boolean flag to indicate menuDefinitions
87       *                             aggregated from menuDefinitionLocators
88       */
89      private boolean menuDefinitionsAggregated;
90  
91      /***
92       * NodeProxy - constructor
93       *
94       * @param view site view owner of this proxy
95       * @param locatorName profile locator name associated with
96       *                    the derived delegate of this proxy in
97       *                    the site view
98       * @param parent view parent proxy folder
99       * @param name name of node to proxy
100      * @param hidden hidden status of node to proxy
101      */
102     protected NodeProxy(SiteView view, String locatorName, Folder parent, String name, boolean hidden)
103     {
104         super(view, locatorName);
105         this.parent = parent;
106         if ((parent != null) && (name != null))
107         {
108             NodeProxy parentProxy = getNodeProxy(parent);
109             String parentPath = parentProxy.getPath();
110             if (parentPath.endsWith(Folder.PATH_SEPARATOR))
111             {
112                 this.path = parentPath + name;
113             }
114             else
115             {
116                 this.path = parentPath + Folder.PATH_SEPARATOR + name;
117             }
118             this.hidden = (hidden || parentProxy.isHidden());
119         }
120         else
121         {
122             this.path = Folder.PATH_SEPARATOR;
123             this.hidden = hidden;
124         }
125     }
126     
127     /***
128      * getParent - proxy implementation of Node.getParent()
129      *
130      * @return parent folder
131      */
132     public Node getParent()
133     {
134         return parent;
135     }
136 
137     /***
138      * getPath - proxy implementation of Node.getPath()
139      * 
140      * @return pages relative path used to identify proxy
141      */
142     public String getPath()
143     {
144         return path;
145     }
146 
147     /***
148      * getPath - proxy implementation of Node.isHidden()
149      * 
150      * @return hidden status of node or parent
151      */
152     public boolean isHidden()
153     {
154         return hidden;
155     }
156 
157     /***
158      * getUrl - proxy implementation of Node.getUrl()
159      * 
160      * @return pages relative url used to navigate to folder
161      */
162     public String getUrl()
163     {
164         return path;
165     }
166 
167     /***
168      * getMenuDefinitions - proxy implementation of Folder.getMenuDefinitions()
169      *                      and Page.getMenuDefinitions()
170      *
171      * @return definition list
172      */
173     public List getMenuDefinitions()
174     {
175         // get menu definitions aggregated by name from
176         // aggregated menu definition locators
177         if (! menuDefinitionsAggregated)
178         {
179             List locators = getMenuDefinitionLocators();
180             if (locators != null)
181             {
182                 menuDefinitions = Collections.synchronizedList(new ArrayList(locators.size()));
183                 Iterator locatorsIter = locators.iterator();
184                 while (locatorsIter.hasNext())
185                 {
186                     menuDefinitions.add(((SiteViewMenuDefinitionLocator)locatorsIter.next()).getMenuDefinition());
187                 }
188             }
189             menuDefinitionsAggregated = true;
190         }
191         return menuDefinitions;
192     }
193 
194     /***
195      * getMenuDefinitionLocators - get list of menu definition locators
196      *                             aggregated by name for this folder or page
197      *
198      * @return definition locator list
199      */
200     public List getMenuDefinitionLocators()
201     {
202         // get menu definition locators aggregated by name
203         if (! menuDefinitionLocatorsAggregated)
204         {
205             aggregateMenuDefinitionLocators();
206             menuDefinitionLocatorsAggregated = true;
207         }
208         return menuDefinitionLocators;
209     }
210 
211     /***
212      * getMenuDefinitionLocator - get menu definition locator by name
213      *
214      * @param name menu definition name
215      * @return menu definition locator
216      */
217     public SiteViewMenuDefinitionLocator getMenuDefinitionLocator(String name)
218     {
219         // get menu definition locators and find by name
220         List locators = getMenuDefinitionLocators();
221         if (locators != null)
222         {
223             return findMenuDefinitionLocator(name);
224         }
225         return null;
226     }
227 
228     /***
229      * aggregateMenuDefinitionLocators - aggregate all menu definition locators
230      *                                   in site view for this folder or page
231      */
232     protected void aggregateMenuDefinitionLocators()
233     {
234         // no menu definition locators by default
235     }
236 
237     /***
238      * mergeMenuDefinitionLocators - utilty to merge menu definition locator lists
239      *                               to be used by derived implementations to aggregate
240      *                               menu definition locators
241      *
242      * @param definitions list of menu definitions to merge
243      * @param node page or folder node that defines menu definitions
244      */
245     protected void mergeMenuDefinitionLocators(List definitions, Node node)
246     {
247         // merge definitions into aggregated menu definition
248         // locators if defined
249         if (definitions != null)
250         {
251             Iterator definitionsIter = definitions.iterator();
252             while (definitionsIter.hasNext())
253             {
254                 // aggregate menu definition by valid name
255                 MenuDefinition definition = (MenuDefinition)definitionsIter.next();
256                 String definitionName = definition.getName();
257                 if (definitionName != null)
258                 {
259                     // add unique menu definition to end of
260                     // ordered menu definition locators list
261                     if (!menuDefinitionLocatorsContains(definitionName))
262                     {
263                         if (menuDefinitionLocators == null)
264                         {
265                             menuDefinitionLocators = Collections.synchronizedList(new ArrayList(definitions.size() * 2));
266                         }
267                         menuDefinitionLocators.add(new SiteViewMenuDefinitionLocator(definition, node));
268                     }
269                 }
270             }
271         }
272     }
273 
274     /***
275      * mergeMenuDefinitionLocators - utilty to merge menu definition locator lists
276      *                               to be used by derived implementations to aggregate
277      *                               menu definition locators
278      *
279      * @param locators list of menu definition locators to merge
280      */
281     protected void mergeMenuDefinitionLocators(List locators)
282     {
283         // merge locators into aggregated menu definition
284         // locators if defined
285         if (locators != null)
286         {
287             Iterator locatorsIter = locators.iterator();
288             while (locatorsIter.hasNext())
289             {
290                 // aggregate menu definition by valid name
291                 SiteViewMenuDefinitionLocator locator = (SiteViewMenuDefinitionLocator)locatorsIter.next();
292                 String definitionName = locator.getName();
293 
294                 // add unique menu definition to end of
295                 // ordered menu definition locators list
296                 if (!menuDefinitionLocatorsContains(definitionName))
297                 {
298                     if (menuDefinitionLocators == null)
299                     {
300                         menuDefinitionLocators = Collections.synchronizedList(new ArrayList(locators.size() * 2));
301                     }
302                     menuDefinitionLocators.add(locator);
303                 }
304             }
305         }
306     }
307 
308     /***
309      * menuDefinitionLocatorsContains - contains test for menu definition locators by name
310      *
311      * @param name menu definition name
312      * @return contains name result
313      */
314     private boolean menuDefinitionLocatorsContains(String name)
315     {
316         // test for matching name in menu definition locators
317         return (findMenuDefinitionLocator(name) != null);
318     }
319 
320     /***
321      * findMenuDefinitionLocator - find menu definition locator by name
322      *
323      * @param name menu definition name
324      * @return menu definition locator
325      */
326     private SiteViewMenuDefinitionLocator findMenuDefinitionLocator(String name)
327     {
328         // find matching menu definition locator by name
329         if ((menuDefinitionLocators != null) && (name != null))
330         {
331             synchronized (menuDefinitionLocators) {
332                 Iterator locatorsIter = menuDefinitionLocators.iterator();
333                 while (locatorsIter.hasNext())
334                 {
335                     SiteViewMenuDefinitionLocator locator = (SiteViewMenuDefinitionLocator)locatorsIter.next();
336                     if (name.equals(locator.getName()))
337                     {
338                         return locator;
339                     }
340                 }
341             }
342         }
343         return null;
344     }
345 
346     /***
347      * equals - proxy implementation of Object.equals()
348      * 
349      * @param object test instance
350      * @return equals test result
351      */
352     public boolean equals(Object object)
353     {
354         if (object != null)
355         {
356             // trivial compare
357             if (object == this)
358             {
359                 return true;
360             }
361 
362             // compare as NodeProxy
363             if (!(object instanceof NodeProxy))
364             {
365                 object = getNodeProxy(object);
366             }
367             if (object instanceof NodeProxy)
368             {
369                 return path.equals(((NodeProxy)object).path);
370             }
371         }
372         return false;
373     }
374 
375     /***
376      * toString - proxy implementation of Object.toString()
377      * 
378      * @return string representation of proxy path
379      */
380     public String toString()
381     {
382         return path;
383     }
384 
385     /***
386      * hashCode - proxy implementation of Object.hashCode()
387      * 
388      * @return hash code based on proxy path
389      */
390     public int hashCode()
391     {
392         return path.hashCode();
393     }
394 
395     /***
396      * getNodeProxy - utility method to access NodeProxy handler
397      *                from Node proxy instance
398      *
399      * @param node node proxy instance
400      * @return node proxy invocation handler instance
401      */
402     public static NodeProxy getNodeProxy(Object node)
403     {
404         if ((node != null) && Proxy.isProxyClass(node.getClass()))
405         {
406             Object nodeProxyHandler = Proxy.getInvocationHandler(node);
407             if (nodeProxyHandler instanceof NodeProxy)
408             {
409                 return (NodeProxy)nodeProxyHandler;
410             }
411         }
412         return null;
413     }
414 }