001: package com.jcorporate.expresso.kernel.digester;
002:
003: /* ====================================================================
004: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
005: *
006: * Copyright (c) 1995-2003 Jcorporate Ltd. All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * 1. Redistributions of source code must retain the above copyright
013: * notice, this list of conditions and the following disclaimer.
014: *
015: * 2. Redistributions in binary form must reproduce the above copyright
016: * notice, this list of conditions and the following disclaimer in
017: * the documentation and/or other materials provided with the
018: * distribution.
019: *
020: * 3. The end-user documentation included with the redistribution,
021: * if any, must include the following acknowledgment:
022: * "This product includes software developed by Jcorporate Ltd.
023: * (http://www.jcorporate.com/)."
024: * Alternately, this acknowledgment may appear in the software itself,
025: * if and wherever such third-party acknowledgments normally appear.
026: *
027: * 4. "Jcorporate" and product names such as "Expresso" must
028: * not be used to endorse or promote products derived from this
029: * software without prior written permission. For written permission,
030: * please contact info@jcorporate.com.
031: *
032: * 5. Products derived from this software may not be called "Expresso",
033: * or other Jcorporate product names; nor may "Expresso" or other
034: * Jcorporate product names appear in their name, without prior
035: * written permission of Jcorporate Ltd.
036: *
037: * 6. No product derived from this software may compete in the same
038: * market space, i.e. framework, without prior written permission
039: * of Jcorporate Ltd. For written permission, please contact
040: * partners@jcorporate.com.
041: *
042: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
043: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
044: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
045: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
046: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
047: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
048: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
049: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
050: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
051: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
052: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
053: * SUCH DAMAGE.
054: * ====================================================================
055: *
056: * This software consists of voluntary contributions made by many
057: * individuals on behalf of the Jcorporate Ltd. Contributions back
058: * to the project(s) are encouraged when you make modifications.
059: * Please send them to support@jcorporate.com. For more information
060: * on Jcorporate Ltd. and its products, please see
061: * <http://www.jcorporate.com/>.
062: *
063: * Portions of this software are based upon other open source
064: * products and are subject to their respective licenses.
065: */
066:
067: import java.util.ArrayList;
068: import java.util.Collections;
069: import java.util.HashMap;
070: import java.util.Iterator;
071: import java.util.Map;
072:
073: /**
074: * This class represents the configuration of a component as parsed from the
075: * xxpresso-services.xml file. It is set by the Digester that fills it.
076: * <p>This is different from the ConfigurationBean used in the kernel package in
077: * that all data is string based. It is up to the system factory to convert the string
078: * data to the appropriate data type as specified by the component's metadata</p>
079: *
080: * @author Michael Rimov
081: */
082: public class ComponentConfig implements java.io.Serializable {
083:
084: private String name;
085: private String className;
086: private Map properties;
087: private Map indexedProperties;
088: private Map mappedProperties;
089:
090: private ArrayList childComponents;
091:
092: /**
093: * Default initialization system.
094: */
095: public ComponentConfig() {
096: name = null;
097: className = null;
098: properties = new HashMap();
099: childComponents = new ArrayList();
100: indexedProperties = new HashMap();
101: mappedProperties = new HashMap();
102: }
103:
104: /**
105: * Retrieve the name of the component
106: *
107: * @return java.lang.String
108: */
109: public String getName() {
110: return name;
111: }
112:
113: /**
114: * Sets the name of the component
115: *
116: * @param name java.lang.String
117: */
118: public void setName(String name) {
119: this .name = name;
120: }
121:
122: /**
123: * Sets the classname for this component
124: *
125: * @param className java.lang.String (Should be a valid class)
126: */
127: public void setClassName(String className) {
128: this .className = className;
129: }
130:
131: /**
132: * Retrieve the classname for this component.
133: *
134: * @return java.lang.String
135: */
136: public String getClassName() {
137: return className;
138: }
139:
140: /**
141: * Add a property for the component
142: *
143: * @param name the name of the property
144: * @param value the value of the named property.
145: */
146: public void addProperty(String name, String value) {
147: properties.put(name, value);
148: }
149:
150: /**
151: * Add a mapped property.
152: *
153: * @param name the name of the mapped property
154: * @param key the property key
155: * @param value the value of the key
156: */
157: public void addMappedProperty(String name, String key, String value) {
158: if (mappedProperties == null) {
159: mappedProperties = new HashMap();
160: }
161:
162: if (!mappedProperties.containsKey(name)) {
163: mappedProperties.put(name, new HashMap());
164: }
165:
166: Map keyedProperties = (Map) mappedProperties.get(name);
167: keyedProperties.put(key, value);
168:
169: }
170:
171: /**
172: * Add an indexed property (often seen in the javabean world as arrays)
173: *
174: * @param name the name of the property
175: * @param index the index of the property
176: * @param value the value of the property at the given index.
177: */
178: public void addIndexedProperty(String name, int index, String value) {
179: if (indexedProperties == null) {
180: indexedProperties = new HashMap();
181: }
182:
183: if (!indexedProperties.containsKey(name)) {
184: HashMap internalArray = new HashMap(index);
185: indexedProperties.put(name, internalArray);
186: }
187:
188: Map indexKeyMap = (Map) indexedProperties.get(name);
189: indexKeyMap.put(new Integer(index), value);
190:
191: }
192:
193: /**
194: * Retrieve the value of a property
195: *
196: * @param name the name of the property
197: * @return java.lang.String
198: */
199: public String getProperty(String name) {
200: return (String) properties.get(name);
201: }
202:
203: /**
204: * Sets the value of a particular property
205: *
206: * @param name the name of the property
207: * @param value the value of the property.
208: */
209: public void setProperty(String name, String value) {
210: if (properties == null) {
211: properties = new HashMap();
212: }
213: properties.put(name, value);
214: }
215:
216: /**
217: * Retrieve the value of a mapped property
218: *
219: * @param name the property name
220: * @param key the key in the mapped property
221: * @return java.lang.String the actual property value
222: */
223: public String getMappedProperty(String name, String key) {
224: if (mappedProperties == null) {
225: return null;
226: }
227:
228: Map oneMapped = (Map) mappedProperties.get(name);
229: if (oneMapped == null) {
230: return null;
231: } else {
232: return (String) oneMapped.get(key);
233: }
234: }
235:
236: /**
237: * Sets an mapped property value.
238: *
239: * @param key The property name
240: * @param name the name of the property
241: * @param value the value for the property.
242: */
243: public void setMappedProperty(String key, String name, String value) {
244: if (mappedProperties == null) {
245: mappedProperties = new HashMap();
246: }
247:
248: Map oneProperty = (Map) mappedProperties.get(key);
249: if (oneProperty == null) {
250: oneProperty = new HashMap();
251: mappedProperties.put(key, oneProperty);
252: }
253:
254: oneProperty.put(name, value);
255: }
256:
257: /**
258: * Retrieve all mapped property key/value pairs for a given property name
259: *
260: * @param name the name of the property
261: * @return String:String Map that corresponds to all mapped values for this
262: * given property
263: */
264: public Map getMappedProperties(String name) {
265: if (mappedProperties == null) {
266: return null;
267: }
268:
269: return (Map) mappedProperties.get(name);
270: }
271:
272: /**
273: * <p>Retrieve a map of all mapped properties. All objects in the map are Strings
274: * and are the format:</p>
275: * <p>Map keyed by property names</p>
276: * <p> Map for each property name keyed by 'key'</p>
277: * <p> The actual property values</p>
278: *
279: * @return java.util.Map
280: */
281: public Map getAllMappedProperties() {
282: return mappedProperties;
283: }
284:
285: /**
286: * Retrieve a map of index properties. The keys in the map correspond to
287: * the indexes in a typical array as they are used in a javabean.
288: *
289: * @param name the name of the property to retrieve
290: * @return java.util.Map keyed by java.lang.Integer
291: */
292: public Map getIndexedProperties(String name) {
293: if (indexedProperties == null) {
294: return null;
295: } else {
296: return (Map) indexedProperties.get(name);
297: }
298: }
299:
300: /**
301: * Retrieve a map of all indexed properties. The map is keyed by strings which in
302: * turn point to maps that are keyed by Integers representing the array
303: * indexes for each property name.
304: *
305: * @return java.util.Map
306: */
307: public Map getAllIndexedProperties() {
308: return indexedProperties;
309: }
310:
311: /**
312: * Retrieve a particular indexed property.
313: *
314: * @param key the property name
315: * @param index the index of the property who's value we wish to retrieve
316: * @return java.lang.String
317: */
318: public String getIndexedProperty(String key, int index) {
319: Map oneProperty = getIndexedProperties(key);
320: if (oneProperty == null) {
321: return null;
322: } else {
323: return (String) oneProperty.get(new Integer(index));
324: }
325: }
326:
327: /**
328: * Sets an indexed property value.
329: *
330: * @param key The property name
331: * @param index the index of the property
332: * @param value the value for the property.
333: */
334: public void setIndexedProperty(String key, int index, String value) {
335: if (indexedProperties == null) {
336: indexedProperties = new HashMap();
337: }
338: Map oneProperty = (Map) indexedProperties.get(key);
339: if (oneProperty == null) {
340: oneProperty = new HashMap();
341: indexedProperties.put(key, oneProperty);
342: }
343:
344: oneProperty.put(new Integer(index), value);
345: }
346:
347: /**
348: * Adds a nested ComponentConfig bean to represent nested components.
349: *
350: * @param newComponent the new ComponentConfig bean
351: */
352: public void addChildComponent(ComponentConfig newComponent) {
353: childComponents.add(newComponent);
354: }
355:
356: /**
357: * Retrieves a list of child component configurations.
358: *
359: * @return an unmodifiable list of child components.
360: */
361: public java.util.List getChildComponents() {
362: return Collections.unmodifiableList(childComponents);
363: }
364:
365: /**
366: * Search for a child component by the given component name
367: *
368: * @param componentName the name of the component to retrieve
369: * @return ComponentConfig if one is found or null if it couldn't be found
370: * @throws IllegalArgumentException if componentName is null or zero length
371: */
372: public ComponentConfig getChildComponent(String componentName) {
373: if (componentName == null || componentName.length() == 0) {
374: throw new IllegalArgumentException(
375: "Cannot have a null or zero length component name");
376: }
377: for (Iterator i = childComponents.iterator(); i.hasNext();) {
378: ComponentConfig oneComponent = (ComponentConfig) i.next();
379: if (componentName.equals(oneComponent.getName())) {
380: return oneComponent;
381: }
382: }
383:
384: return null;
385: }
386:
387: /**
388: * Retrieve a read-only map of all 'normal' properties keyed by the property name.
389: *
390: * @return java.util.Map
391: */
392: public Map getProperties() {
393: return Collections.unmodifiableMap(properties);
394: }
395:
396: /**
397: * Determine if two component configuration beans are equal by checking
398: * all fields and all child component's configurations.
399: *
400: * @param parm1 the other object to check against
401: * @return true if this function determines that the two beans are equal.
402: */
403: public boolean equals(Object parm1) {
404: if (parm1 == null) {
405: return false;
406: }
407:
408: if (!(parm1 instanceof ComponentConfig)) {
409: return false;
410: }
411:
412: ComponentConfig other = (ComponentConfig) parm1;
413:
414: if ((className == null) ^ (other.className == null)) {
415: return false;
416: }
417:
418: if (name == null ^ other.name == null) {
419: return false;
420: }
421:
422: if (properties.size() != other.properties.size()) {
423: return false;
424: }
425:
426: if (indexedProperties.size() != other.indexedProperties.size()) {
427: return false;
428: }
429:
430: if (mappedProperties.size() != other.mappedProperties.size()) {
431: return false;
432: }
433:
434: if (this .getChildComponents().size() != other
435: .getChildComponents().size()) {
436: return false;
437: }
438:
439: //
440: //Ok, we're done with the numerically easy issues, now it's time to do
441: //things one at a time
442: //
443: boolean returnValue = true;
444:
445: returnValue &= properties.equals(other.properties);
446: if (returnValue == false) {
447: return false;
448: }
449: returnValue &= indexedProperties
450: .equals(other.indexedProperties);
451: if (returnValue == false) {
452: return false;
453: }
454: returnValue &= mappedProperties.equals(other.mappedProperties);
455: if (returnValue == false) {
456: return false;
457: }
458:
459: for (Iterator i = childComponents.iterator(), j = other.childComponents
460: .iterator(); (i.hasNext() && j.hasNext());) {
461: ComponentConfig this Child = (ComponentConfig) i.next();
462: ComponentConfig otherChild = (ComponentConfig) j.next();
463:
464: returnValue &= this Child.equals(otherChild);
465: if (returnValue == false) {
466: return false;
467: }
468: }
469:
470: return returnValue;
471: }
472:
473: /**
474: * A semi-copy constructor that allows you to update the configuration for
475: * this component only, not it's children. Overrites the current properties,
476: * etc for everything except childComponents
477: *
478: * @param newConfiguration the new configuration to update
479: */
480: public void updateConfig(ComponentConfig newConfiguration) {
481: className = newConfiguration.className;
482: indexedProperties = new HashMap(
483: newConfiguration.indexedProperties);
484: mappedProperties = new HashMap(
485: newConfiguration.mappedProperties);
486: name = newConfiguration.name;
487: properties = new HashMap(newConfiguration.properties);
488: }
489:
490: /**
491: * Custom hashcode... name and classname basically make a unique
492: * component config.
493: *
494: * @return integer
495: */
496: public int hashCode() {
497: return className.hashCode() ^ name.hashCode();
498: }
499:
500: }
|