001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.page.document.proxy;
018:
019: import java.lang.reflect.Method;
020: import java.lang.reflect.Proxy;
021: import java.util.ArrayList;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Collections;
025:
026: import org.apache.jetspeed.om.folder.Folder;
027: import org.apache.jetspeed.om.folder.MenuDefinition;
028: import org.apache.jetspeed.page.document.Node;
029: import org.apache.jetspeed.portalsite.view.SiteView;
030: import org.apache.jetspeed.portalsite.view.SiteViewMenuDefinitionLocator;
031: import org.apache.jetspeed.portalsite.view.SiteViewProxy;
032:
033: /**
034: * This class proxies Node instances to create a logical
035: * view of site content.
036: *
037: * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
038: * @version $Id: NodeProxy.java 516448 2007-03-09 16:25:47Z ate $
039: */
040: public abstract class NodeProxy extends SiteViewProxy {
041: /**
042: * *_METHOD - Node method constants
043: */
044: protected static final Method EQUALS_METHOD = reflectMethod(
045: Object.class, "equals", new Class[] { Object.class });
046: protected static final Method GET_PARENT_METHOD = reflectMethod(
047: Node.class, "getParent", null);
048: protected static final Method GET_PATH_METHOD = reflectMethod(
049: Node.class, "getPath", null);
050: protected static final Method GET_URL_METHOD = reflectMethod(
051: Node.class, "getUrl", null);
052: protected static final Method HASH_CODE_METHOD = reflectMethod(
053: Object.class, "hashCode", null);
054: protected static final Method IS_HIDDEN_METHOD = reflectMethod(
055: Node.class, "isHidden", null);
056: protected static final Method TO_STRING_METHOD = reflectMethod(
057: Object.class, "toString", null);
058:
059: /**
060: * parent - view parent proxy folder instance
061: */
062: private Folder parent;
063:
064: /**
065: * path - view path
066: */
067: private String path;
068:
069: /**
070: * hidden - hidden status of this or parent node
071: */
072: private boolean hidden;
073:
074: /**
075: * menuDefinitionLocators - menu definitions aggregated by name saved in
076: * menu definition locators
077: */
078: private List menuDefinitionLocators;
079:
080: /**
081: * menuDefinitionLocatorsAggregated - boolean flag to indicate
082: * menuDefinitionLocators aggregated
083: */
084: private boolean menuDefinitionLocatorsAggregated;
085:
086: /**
087: * menuDefinitions - menu definitions aggregated by name
088: */
089: private List menuDefinitions;
090:
091: /**
092: * menuDefinitionsAggregated - boolean flag to indicate menuDefinitions
093: * aggregated from menuDefinitionLocators
094: */
095: private boolean menuDefinitionsAggregated;
096:
097: /**
098: * NodeProxy - constructor
099: *
100: * @param view site view owner of this proxy
101: * @param locatorName profile locator name associated with
102: * the derived delegate of this proxy in
103: * the site view
104: * @param parent view parent proxy folder
105: * @param name name of node to proxy
106: * @param hidden hidden status of node to proxy
107: */
108: protected NodeProxy(SiteView view, String locatorName,
109: Folder parent, String name, boolean hidden) {
110: super (view, locatorName);
111: this .parent = parent;
112: if ((parent != null) && (name != null)) {
113: NodeProxy parentProxy = getNodeProxy(parent);
114: String parentPath = parentProxy.getPath();
115: if (parentPath.endsWith(Folder.PATH_SEPARATOR)) {
116: this .path = parentPath + name;
117: } else {
118: this .path = parentPath + Folder.PATH_SEPARATOR + name;
119: }
120: this .hidden = (hidden || parentProxy.isHidden());
121: } else {
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: return parent;
134: }
135:
136: /**
137: * getPath - proxy implementation of Node.getPath()
138: *
139: * @return pages relative path used to identify proxy
140: */
141: public String getPath() {
142: return path;
143: }
144:
145: /**
146: * getPath - proxy implementation of Node.isHidden()
147: *
148: * @return hidden status of node or parent
149: */
150: public boolean isHidden() {
151: return hidden;
152: }
153:
154: /**
155: * getUrl - proxy implementation of Node.getUrl()
156: *
157: * @return pages relative url used to navigate to folder
158: */
159: public String getUrl() {
160: return path;
161: }
162:
163: /**
164: * getMenuDefinitions - proxy implementation of Folder.getMenuDefinitions()
165: * and Page.getMenuDefinitions()
166: *
167: * @return definition list
168: */
169: public List getMenuDefinitions() {
170: // get menu definitions aggregated by name from
171: // aggregated menu definition locators
172: if (!menuDefinitionsAggregated) {
173: List locators = getMenuDefinitionLocators();
174: if (locators != null) {
175: menuDefinitions = Collections
176: .synchronizedList(new ArrayList(locators.size()));
177: Iterator locatorsIter = locators.iterator();
178: while (locatorsIter.hasNext()) {
179: menuDefinitions
180: .add(((SiteViewMenuDefinitionLocator) locatorsIter
181: .next()).getMenuDefinition());
182: }
183: }
184: menuDefinitionsAggregated = true;
185: }
186: return menuDefinitions;
187: }
188:
189: /**
190: * getMenuDefinitionLocators - get list of menu definition locators
191: * aggregated by name for this folder or page
192: *
193: * @return definition locator list
194: */
195: public List getMenuDefinitionLocators() {
196: // get menu definition locators aggregated by name
197: if (!menuDefinitionLocatorsAggregated) {
198: aggregateMenuDefinitionLocators();
199: menuDefinitionLocatorsAggregated = true;
200: }
201: return menuDefinitionLocators;
202: }
203:
204: /**
205: * getMenuDefinitionLocator - get menu definition locator by name
206: *
207: * @param name menu definition name
208: * @return menu definition locator
209: */
210: public SiteViewMenuDefinitionLocator getMenuDefinitionLocator(
211: String name) {
212: // get menu definition locators and find by name
213: List locators = getMenuDefinitionLocators();
214: if (locators != null) {
215: return findMenuDefinitionLocator(name);
216: }
217: return null;
218: }
219:
220: /**
221: * aggregateMenuDefinitionLocators - aggregate all menu definition locators
222: * in site view for this folder or page
223: */
224: protected void aggregateMenuDefinitionLocators() {
225: // no menu definition locators by default
226: }
227:
228: /**
229: * mergeMenuDefinitionLocators - utilty to merge menu definition locator lists
230: * to be used by derived implementations to aggregate
231: * menu definition locators
232: *
233: * @param definitions list of menu definitions to merge
234: * @param node page or folder node that defines menu definitions
235: */
236: protected void mergeMenuDefinitionLocators(List definitions,
237: Node node) {
238: // merge definitions into aggregated menu definition
239: // locators if defined
240: if (definitions != null) {
241: Iterator definitionsIter = definitions.iterator();
242: while (definitionsIter.hasNext()) {
243: // aggregate menu definition by valid name
244: MenuDefinition definition = (MenuDefinition) definitionsIter
245: .next();
246: String definitionName = definition.getName();
247: if (definitionName != null) {
248: // add unique menu definition to end of
249: // ordered menu definition locators list
250: if (!menuDefinitionLocatorsContains(definitionName)) {
251: if (menuDefinitionLocators == null) {
252: menuDefinitionLocators = Collections
253: .synchronizedList(new ArrayList(
254: definitions.size() * 2));
255: }
256: menuDefinitionLocators
257: .add(new SiteViewMenuDefinitionLocator(
258: definition, node));
259: }
260: }
261: }
262: }
263: }
264:
265: /**
266: * mergeMenuDefinitionLocators - utilty to merge menu definition locator lists
267: * to be used by derived implementations to aggregate
268: * menu definition locators
269: *
270: * @param locators list of menu definition locators to merge
271: */
272: protected void mergeMenuDefinitionLocators(List locators) {
273: // merge locators into aggregated menu definition
274: // locators if defined
275: if (locators != null) {
276: Iterator locatorsIter = locators.iterator();
277: while (locatorsIter.hasNext()) {
278: // aggregate menu definition by valid name
279: SiteViewMenuDefinitionLocator locator = (SiteViewMenuDefinitionLocator) locatorsIter
280: .next();
281: String definitionName = locator.getName();
282:
283: // add unique menu definition to end of
284: // ordered menu definition locators list
285: if (!menuDefinitionLocatorsContains(definitionName)) {
286: if (menuDefinitionLocators == null) {
287: menuDefinitionLocators = Collections
288: .synchronizedList(new ArrayList(
289: locators.size() * 2));
290: }
291: menuDefinitionLocators.add(locator);
292: }
293: }
294: }
295: }
296:
297: /**
298: * menuDefinitionLocatorsContains - contains test for menu definition locators by name
299: *
300: * @param name menu definition name
301: * @return contains name result
302: */
303: private boolean menuDefinitionLocatorsContains(String name) {
304: // test for matching name in menu definition locators
305: return (findMenuDefinitionLocator(name) != null);
306: }
307:
308: /**
309: * findMenuDefinitionLocator - find menu definition locator by name
310: *
311: * @param name menu definition name
312: * @return menu definition locator
313: */
314: private SiteViewMenuDefinitionLocator findMenuDefinitionLocator(
315: String name) {
316: // find matching menu definition locator by name
317: if ((menuDefinitionLocators != null) && (name != null)) {
318: synchronized (menuDefinitionLocators) {
319: Iterator locatorsIter = menuDefinitionLocators
320: .iterator();
321: while (locatorsIter.hasNext()) {
322: SiteViewMenuDefinitionLocator locator = (SiteViewMenuDefinitionLocator) locatorsIter
323: .next();
324: if (name.equals(locator.getName())) {
325: return locator;
326: }
327: }
328: }
329: }
330: return null;
331: }
332:
333: /**
334: * equals - proxy implementation of Object.equals()
335: *
336: * @param object test instance
337: * @return equals test result
338: */
339: public boolean equals(Object object) {
340: if (object != null) {
341: // trivial compare
342: if (object == this ) {
343: return true;
344: }
345:
346: // compare as NodeProxy
347: if (!(object instanceof NodeProxy)) {
348: object = getNodeProxy(object);
349: }
350: if (object instanceof NodeProxy) {
351: return path.equals(((NodeProxy) object).path);
352: }
353: }
354: return false;
355: }
356:
357: /**
358: * toString - proxy implementation of Object.toString()
359: *
360: * @return string representation of proxy path
361: */
362: public String toString() {
363: return path;
364: }
365:
366: /**
367: * hashCode - proxy implementation of Object.hashCode()
368: *
369: * @return hash code based on proxy path
370: */
371: public int hashCode() {
372: return path.hashCode();
373: }
374:
375: /**
376: * getNodeProxy - utility method to access NodeProxy handler
377: * from Node proxy instance
378: *
379: * @param node node proxy instance
380: * @return node proxy invocation handler instance
381: */
382: public static NodeProxy getNodeProxy(Object node) {
383: if ((node != null) && Proxy.isProxyClass(node.getClass())) {
384: Object nodeProxyHandler = Proxy.getInvocationHandler(node);
385: if (nodeProxyHandler instanceof NodeProxy) {
386: return (NodeProxy) nodeProxyHandler;
387: }
388: }
389: return null;
390: }
391: }
|