001 package biz.hammurapi.config;
002
003 import java.util.ArrayList;
004 import java.util.Collection;
005 import java.util.Collections;
006 import java.util.Iterator;
007 import java.util.LinkedHashMap;
008 import java.util.List;
009 import java.util.Map;
010 import java.util.Set;
011
012 import biz.hammurapi.metrics.MeasurementCollector;
013 import biz.hammurapi.metrics.MeasurementConsumer;
014 import biz.hammurapi.util.Attributable;
015 import biz.hammurapi.util.CollectionVisitable;
016 import biz.hammurapi.util.VisitableBase;
017 import biz.hammurapi.util.Visitor;
018
019 public class GenericContainer extends VisitableBase implements Component, Command, Attributable, Context, MeasurementCollector, MeasurementConsumer {
020
021 private Map componentMap = new LinkedHashMap();
022
023 protected Map getComponentMap() {
024 return componentMap;
025 }
026
027 private boolean started;
028 private Object owner;
029
030 private PathNavigator pathNavigator = new PathNavigator(this) {
031
032 protected Object getParent() {
033 return owner;
034 }
035
036 protected Object getChild(String name) {
037 return componentMap.get(name);
038 }
039
040 };
041
042 private LinkedHashMap attributes = new LinkedHashMap();
043 private MeasurementConsumer measurementConsumer;
044
045 /**
046 * Looks up component in component tree.
047 * @param name
048 * @return
049 */
050 public Object get(String name) {
051 return pathNavigator.get(name);
052 }
053
054 /**
055 * Adds component and starts it.
056 * @param name
057 * @param component
058 * @throws ConfigurationException
059 */
060 public void addComponent(String name, Object component) throws ConfigurationException {
061 if (name==null) {
062 name = "Anonymous component "+componentMap.size();
063 }
064
065 // Remove previous component
066 Object prevComponent=componentMap.remove(name);
067 if (prevComponent!=null) {
068 if (prevComponent instanceof Component) {
069 if (started) {
070 ((Component) prevComponent).stop();
071 }
072 ((Component) prevComponent).setOwner(null);
073 }
074
075 if (prevComponent instanceof MeasurementCollector) {
076 ((MeasurementCollector) prevComponent).setMeasurementConsumer(null);
077 }
078 }
079
080 if (component!=null) {
081 if (component instanceof MeasurementCollector) {
082 final String componentName = name;
083 MeasurementConsumer cmc = new MeasurementConsumer() {
084 public void addMeasurement(String mName, double value, long time) {
085 if (measurementConsumer!=null) {
086 measurementConsumer.addMeasurement(componentName+"."+mName, value, time==0 ? System.currentTimeMillis() : time);
087 }
088 }
089 };
090 ((MeasurementCollector) component).setMeasurementConsumer(cmc);
091 }
092
093 if (component instanceof NamedComponent) {
094 ((NamedComponent) component).setName(name);
095 }
096
097 // Add new component
098 if (component instanceof Component) {
099 Component theComponent = (Component) component;
100 theComponent.setOwner(this);
101 if (started) {
102 theComponent.start();
103 }
104 }
105
106 if (name!=null) {
107 componentMap.put(name, component);
108 }
109
110 }
111 }
112
113 public void start() throws ConfigurationException {
114 if (getMeasurementConsumer() instanceof Component) {
115 ((Component) getMeasurementConsumer()).start();
116 }
117
118 Iterator it=componentMap.values().iterator();
119 while (it.hasNext()) {
120 Object component = it.next();
121 if (component instanceof Component) {
122 ((Component) component).start();
123 }
124 }
125 started=true;
126 }
127
128 public void stop() throws ConfigurationException {
129 started=false;
130 List reverseComponentList=new ArrayList(componentMap.values());
131 Collections.reverse(reverseComponentList);
132 Iterator it=reverseComponentList.iterator();
133 while (it.hasNext()) {
134 Object component = it.next();
135 if (component instanceof Component) {
136 ((Component) component).stop();
137 }
138 }
139 if (getMeasurementConsumer() instanceof Component) {
140 ((Component) getMeasurementConsumer()).stop();
141 }
142 }
143
144 public void setOwner(Object owner) {
145 this.owner=owner;
146 }
147
148 /**
149 * Invokes execute() of executable components sequentially.
150 */
151 public void execute(Object executionContext) {
152 Iterator it=componentMap.values().iterator();
153 while (it.hasNext()) {
154 Object component = it.next();
155 if (component instanceof Command) {
156 ((Command) component).execute(executionContext);
157 }
158 }
159 }
160
161 protected void acceptChildren(Visitor visitor) {
162 new CollectionVisitable(componentMap.values(), false).accept(visitor);
163 }
164
165 protected Collection getComponents() {
166 return componentMap.values();
167 }
168
169 public Set getComponentNames() {
170 return Collections.unmodifiableSet(componentMap.keySet());
171 }
172
173 public void setAttribute(Object key, Object value) {
174 attributes.put(key, value);
175 }
176
177 public Object getAttribute(Object key) {
178 return attributes.get(key);
179 }
180
181 public Object removeAttribute(Object key) {
182 return attributes.remove(key);
183 }
184
185 public void setMeasurementConsumer(MeasurementConsumer measurementConsumer) {
186 this.measurementConsumer = measurementConsumer;
187 if (measurementConsumer instanceof Component) {
188 ((Component) measurementConsumer).setOwner(this);
189 }
190 }
191
192 public MeasurementConsumer getMeasurementConsumer() {
193 return measurementConsumer;
194 }
195
196 public void addMeasurement(String name, double value, long time) {
197 if (measurementConsumer!=null) {
198 measurementConsumer.addMeasurement(name, value, time);
199 }
200 }
201
202 /**
203 * Finds component owner of particular type.
204 * @param ownerType
205 * @return Owner which is an instance of specified type or null if no such owner is found.
206 */
207 public Object getOwner(Class ownerType) {
208 if (owner==null || ownerType.isInstance(owner)) {
209 return owner;
210 }
211
212 if (owner instanceof ComponentBase) {
213 return ((ComponentBase) owner).getOwner(ownerType);
214 }
215
216 if (owner instanceof GenericContainer) {
217 return ((GenericContainer) owner).getOwner(ownerType);
218 }
219
220 return null;
221 }
222 }