View Javadoc

1   /*
2    * Copyright 2004-2005, 2008 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package net.sf.morph.context.contexts;
17  
18  import java.util.Arrays;
19  import java.util.Set;
20  
21  import net.sf.composite.util.ObjectUtils;
22  import net.sf.morph.context.Context;
23  import net.sf.morph.context.ContextException;
24  import net.sf.morph.context.HierarchicalContext;
25  import net.sf.morph.util.ContainerUtils;
26  
27  /**
28   * <p>
29   * Convenient base class for hierarchical Contexts. Validates arguments and
30   * takes care of logging and exception handling. Also implements the
31   * {@link java.util.Map} interface.
32   * </p>
33   *
34   * @author Matt Sgarlata
35   * @since Nov 29, 2004
36   * @see net.sf.morph.context.support.BaseContext
37   * @see net.sf.morph.context.HierarchicalContext
38   */
39  public abstract class BaseHierarchicalContext extends BaseContext implements
40  	HierarchicalContext {
41  
42  	private Context parentContext;
43  
44  	/**
45  	 * Creates a new, empty context.
46  	 */
47  	public BaseHierarchicalContext() {
48  		super();
49  	}
50  
51  	/**
52  	 * Creates a new, empty context with the specified parent.
53  	 */
54  	public BaseHierarchicalContext(Context parentContext) {
55  		super();
56  		this.parentContext = parentContext;
57  	}
58  
59  	protected abstract Object getHierarchicalImpl(String propertyName) throws Exception;
60  
61  	protected abstract String[] getPropertyNamesHierarchicalImpl() throws Exception;
62  
63  	protected abstract void setHierarchicalImpl(String propertyName, Object propertyValue) throws Exception;
64  
65  	protected final Object getImpl(String propertyName) throws Exception {
66  		Object value = null;
67  
68  		if (getLog().isTraceEnabled()) {
69  			getLog().trace("Getting property '" + propertyName + "' from context " + getClass().getName());
70  		}
71  
72  		try {
73  			value = this.getHierarchicalImpl(propertyName);
74  		}
75  		catch (ContextException e) {
76  			if (getLog().isDebugEnabled()) {
77  				getLog().debug("Unable to retrieve property '" + propertyName + "' from context " + getClass().getName() + "; attempting to read property from parent context");
78  			}
79  		}
80  		if (value == null) {
81  			Context parent = getParentContext();
82  			if (parent != null) {
83  				value = parent.get(propertyName);
84  			}
85  		}
86  		return value;
87  
88  //		// search the parent contexts
89  //		Context currentContext = parentContext;
90  //		int indent = 0;
91  //		while (value == null && currentContext != null &&
92  //			currentContext instanceof HierarchicalContext) {
93  //			value = currentContext.get(propertyName);
94  //			indent++;
95  //			if (getLog().isTraceEnabled()) {
96  //				getLog().trace(MorphUtils.repeat("  ", indent) + "Got value " + value + " for property '" + propertyName + "' from " + ObjectUtils.getObjectDescription(this));
97  //			}
98  //			currentContext =
99  //				((HierarchicalContext) currentContext).getParentContext();
100 //		}
101 //		return value;
102 	}
103 
104 	protected final String[] getPropertyNamesImpl() throws Exception {
105 		String[] currentPropertyNames = this.getPropertyNamesHierarchicalImpl();
106 		int size = currentPropertyNames == null ? 0 : currentPropertyNames.length;
107 		Set propertyNames = ContainerUtils.createOrderedSet();
108 		if (!ObjectUtils.isEmpty(currentPropertyNames)) {
109 			propertyNames.addAll(Arrays.asList(currentPropertyNames));
110 		}
111 		Context currentContext = parentContext;
112 		while (currentContext != null &&
113 			currentContext instanceof HierarchicalContext) {
114 			currentPropertyNames = currentContext.getPropertyNames();
115 			if (!ObjectUtils.isEmpty(currentPropertyNames)) {
116 				propertyNames.addAll(
117 					Arrays.asList(currentPropertyNames));
118 			}
119 			currentContext =
120 				((HierarchicalContext) currentContext).getParentContext();
121 		}
122 		return (String[])
123 			propertyNames.toArray(new String[propertyNames.size()]);
124 	}
125 
126 	protected final void setImpl(String propertyName, Object propertyValue)
127 		throws Exception {
128 
129 		if (getLog().isTraceEnabled()) {
130 			getLog().trace("Setting property '" + propertyName + "' to value " + ObjectUtils.getObjectDescription(propertyValue) + " for context " + ObjectUtils.getObjectDescription(this));
131 		}
132 
133 		try {
134 			setHierarchicalImpl(propertyName, propertyValue);
135 		}
136 		catch (Exception e) {
137 			if (getLog().isDebugEnabled()) {
138 				getLog().debug("Unable to retrieve property '" + propertyName + "' from context " + ObjectUtils.getObjectDescription(this) + "; attempting to read property from parent context");
139 			}
140 			if (getParentContext() == null) {
141 				throw e;
142 			}
143 			getParentContext().set(propertyName, propertyValue);
144 		}
145 	}
146 
147 	/**
148 	 * Sets this context's parent context.
149 	 *
150 	 * @param parentContext
151 	 *            this context's parent context
152 	 */
153 	public void setParentContext(Context parentContext) {
154 		this.parentContext = parentContext;
155 	}
156 	public Context getParentContext() {
157 		return parentContext;
158 	}
159 
160 }