View Javadoc

1   /*
2    * Copyright (c) 2005 Regents of the University of California (Regents). Created
3    * by TELS, Graduate School of Education, University of California at Berkeley.
4    *
5    * This software is distributed under the GNU Lesser General Public License, v2.
6    *
7    * Permission is hereby granted, without written agreement and without license
8    * or royalty fees, to use, copy, modify, and distribute this software and its
9    * documentation for any purpose, provided that the above copyright notice and
10   * the following two paragraphs appear in all copies of this software.
11   *
12   * REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
13   * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
14   * PURPOSE. THE SOFTWAREAND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
15   * HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
16   * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
17   *
18   * IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
19   * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
20   * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
21   * REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22   */
23  package net.sf.sail.core.beans;
24  
25  import java.net.MalformedURLException;
26  import java.net.URL;
27  import java.util.Collection;
28  import java.util.HashMap;
29  import java.util.HashSet;
30  import java.util.Iterator;
31  import java.util.LinkedList;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.Set;
35  import java.util.logging.Level;
36  import java.util.logging.Logger;
37  
38  import net.sf.sail.core.activity.model.ScriptBeanContext;
39  import net.sf.sail.core.beans.assembly.Assignment;
40  import net.sf.sail.core.beans.assembly.PodRegistry;
41  import net.sf.sail.core.beans.assembly.PropertyRef;
42  import net.sf.sail.core.util.SailBeanUtils;
43  import net.sf.sail.core.uuid.PodUuid;
44  
45  /***
46   * Bean representing the reusable Pod container.
47   * 
48   * @author turadg
49   */
50  public class Pod extends ScriptBeanContext {
51  	/***
52  	 * 
53  	 */
54  	private static final long serialVersionUID = 7881255006647471835L;
55  
56  	/***
57  	 * Make this a constant so other classes can use this property name
58  	 */
59  	public static final String PROPERTY_POD_ID = "podId";
60  
61  	/***
62  	 * Logger for this class
63  	 */
64  	private static final Logger logger = Logger.getLogger(Pod.class.getName());
65  
66  	// property
67  	PodUuid podId;
68  
69  	public PodUuid getPodId() {
70  		return podId;
71  	}
72  
73  	public void setPodId(PodUuid podId) {
74  		if (podId == null)
75  			throw new NullPointerException("podId argument was null");
76  		this.podId = podId;
77  		// firePropertyChange(PROPERTY_POD_ID, old, podId);
78  		// property change listener won't do because the pod may have never had
79  		// a podId (and thus not fit yet in the registry)
80  		PodRegistry.getRegistry().reregister(this);
81  	}
82  
83  	// property
84  	Map<String,PropertyRef> vars = new HashMap<String,PropertyRef>();
85  
86  	public Map getVars() {
87  		return vars;
88  	}
89  
90  	public void setVars(Map<String,PropertyRef> vars) {
91  		this.vars = vars;
92  	}
93  
94  	public void bind(String varName, PropertyRef propertyRef,
95  			boolean isTransient) {
96  		vars.put(varName, propertyRef);
97  		if (isTransient)
98  			transientRefs.add(propertyRef);
99  	}
100 
101 	public Object resolve(String varName) {
102 		Object value = null;
103 		try {
104 			value = ((PropertyRef) vars.get(varName)).getCurrentValue();
105 		} catch (Exception e) {
106 			logger.warning("exception: " + e);
107 		}
108 		return value;
109 	}
110 
111 	// property
112 	Set<PropertyRef> transientRefs = new HashSet<PropertyRef>();
113 
114 	public Set getTransientRefs() {
115 		return transientRefs;
116 	}
117 
118 	public void setTransientRefs(Set<PropertyRef> transientRefs) {
119 		this.transientRefs = transientRefs;
120 	}
121 
122 	// property
123 	List assemblyCalls = new LinkedList();
124 
125 	public List getAssemblyCalls() {
126 		return assemblyCalls;
127 	}
128 
129 	public void setAssemblyCalls(List assemblyCalls) {
130 		Object old = this.assemblyCalls;
131 		this.assemblyCalls = assemblyCalls;
132 		firePropertyChange("assemblyCalls", old, assemblyCalls);
133 	}
134 
135 	protected Pod childWithId(PodUuid podId) {
136 		Collection podChildren = SailBeanUtils.childrenOfType(this, Pod.class);
137 		for (Iterator iter = podChildren.iterator(); iter.hasNext();) {
138 			Pod pod = (Pod) iter.next();
139 			if (pod.getPodId().equals(podId))
140 				return pod;
141 		}
142 		return null;
143 	}
144 
145 	public URL getPodArchive() {
146 		try {
147 			return new URL("podar:" + podId);
148 		} catch (MalformedURLException e) {
149 			throw new RuntimeException("impossible error", e);
150 		}
151 	}
152 
153 	// TODO make this throw a checked exception for failed assignments
154 	public void assemble() {
155 		assembleChildren();
156 		PodRegistry registry = PodRegistry.getRegistry();
157 		registry.register(this);
158 		for (Iterator iter = assemblyCalls.iterator(); iter.hasNext();) {
159 			Assignment assignment = (Assignment) iter.next();
160 			try {
161 				assignment.execute();
162 			} catch (Exception e) {
163 				logger.warning("exception: " + e);
164 				throw new RuntimeException("error assembling", e);
165 			}
166 		}
167 	}
168 
169 	// TODO give some way to remove a child pod for good
170 	// TODO write delegate that persists this without exposing it
171 	Set<PodUuid> childPodIds = new HashSet<PodUuid>();
172 
173 	@Override
174 	public boolean add(Object targetChild) {
175 		boolean success = super.add(targetChild);
176 		if (logger.isLoggable(Level.FINE)) {
177 			logger.fine(this + " added " + targetChild + " success:" + success);
178 		}
179 		if (success && targetChild instanceof Pod) {
180 			Pod pod = (Pod) targetChild;
181 			childPodIds.add(pod.getPodId());
182 		}
183 
184 		return success;
185 	}
186 
187 	private void assembleChildren() {
188 		for (Iterator iter = childPodIds.iterator(); iter.hasNext();) {
189 			PodUuid podId = (PodUuid) iter.next();
190 			Pod pod = PodRegistry.getRegistry().getPod(podId);
191 			add(pod);
192 			pod.assemble();
193 		}
194 	}
195 
196 	public Set getChildPodIds() {
197 		return childPodIds;
198 	}
199 
200 	public void setChildPodIds(Set<PodUuid> childPodIds) {
201 		this.childPodIds = childPodIds;
202 	}
203 
204 	/***
205 	 * Returns whether the value is the same as a podvar that is transient.
206 	 * (i.e. should not be marshalled) Assumes instances of Pod cannot be
207 	 * imported.
208 	 * 
209 	 * @param value
210 	 * @return true iff the value matches the current value of one of the refs
211 	 *         in this pod marked transient
212 	 */
213 	public boolean isTransient(Object value) {
214 		if (value instanceof Pod)
215 			return false;
216 		for (Iterator iter = transientRefs.iterator(); iter.hasNext();) {
217 			PropertyRef ref = (PropertyRef) iter.next();
218 			Object importedValue = null;
219 			try {
220 				importedValue = ref.getCurrentValue();
221 			} catch (Exception e) {
222 				logger.warning("exception: " + e);
223 			}
224 			if (value == importedValue)
225 				return true;
226 		}
227 		return false;
228 	}
229 
230 	@Override
231 	public String toString() {
232 		return "Pod@" + podId;
233 	}
234 
235 	// TODO implement this properly with check against BeanContext facilities. a
236 	// unit test even!
237 	@Override
238 	public int hashCode() {
239 		return super.hashCode();
240 		// the code below breaks the BeanContext children facilities
241 		// return new HashCodeBuilder(29, 3).append(podId).append(childPodIds)
242 		// .append(children).append(vars).append(transientRefs).append(
243 		// transientRefs).toHashCode();
244 	}
245 
246 }