001: package org.columba.core.context.base;
002:
003: import java.io.InputStream;
004: import java.util.Date;
005: import java.util.Hashtable;
006: import java.util.Iterator;
007: import java.util.List;
008: import java.util.Vector;
009:
010: import org.columba.core.context.base.api.IAttributeType;
011: import org.columba.core.context.base.api.IName;
012: import org.columba.core.context.base.api.IStructureType;
013: import org.columba.core.context.base.api.IStructureValue;
014: import org.columba.core.context.base.api.MULTIPLICITY;
015: import org.columba.core.context.base.api.IAttributeType.BASETYPE;
016:
017: // TODO: multiplicity checks
018: public class StructureValue implements IStructureValue {
019:
020: private String name;
021:
022: private String namespace;
023:
024: private IStructureType type;
025:
026: private final List<Object> attributeList = new Vector<Object>();
027:
028: private final Hashtable<IName, Object> attributeMap = new Hashtable<IName, Object>();
029:
030: private final Hashtable<IName, List<IStructureValue>> valueMap = new Hashtable<IName, List<IStructureValue>>();
031:
032: private IStructureValue parent;
033:
034: /**
035: * @param theName
036: * @param theNamespace
037: * @param theType
038: */
039: public StructureValue(final String theName,
040: final String theNamespace, final IStructureType theType) {
041: this .type = theType;
042: this .name = theName;
043: this .namespace = theNamespace;
044: }
045:
046: /**
047: * @param theName
048: * @param theNamespace
049: * @param theType
050: * @param theParent
051: */
052: public StructureValue(final String theName,
053: final String theNamespace, final IStructureType theType,
054: final IStructureValue theParent) {
055: this (theName, theNamespace, theType);
056: this .parent = theParent;
057:
058: }
059:
060: /**
061: * @see org.columba.core.context.base.api.IStructureValue#getType()
062: */
063: public IStructureType getType() {
064: return type;
065: }
066:
067: /**
068: * @see org.columba.core.context.base.api.IStructureValue#getName()
069: */
070: public String getName() {
071: return name;
072: }
073:
074: /**
075: * @see org.columba.core.context.base.api.IStructureValue#getNamespace()
076: */
077: public String getNamespace() {
078: return namespace;
079: }
080:
081: public Object getObject(final String theName,
082: final String theNamespace) {
083: final Object obj = attributeMap.get(new Name(theName,
084: theNamespace));
085: if (obj == null) {
086: // check if default value exists
087: final IAttributeType t = getType().getAttribute(theName,
088: theNamespace);
089: return t.getDefaultValue();
090: }
091:
092: return obj;
093: }
094:
095: public void setObject(final String theName,
096: final String theNamespace, final Object value) {
097: if (theName == null) {
098: throw new IllegalArgumentException("name == null");
099: }
100: if (theNamespace == null) {
101: throw new IllegalArgumentException("namespace");
102: }
103: if (value == null) {
104: throw new IllegalArgumentException("value == null");
105: }
106:
107: final IAttributeType attrType = getType().getAttribute(theName,
108: theNamespace);
109: if (attrType == null) {
110: throw new IllegalArgumentException("attribute type <"
111: + theName + "," + theNamespace + "> does not exist");
112: }
113:
114: // remove old
115: final Object obj = getObject(theName, theNamespace);
116: if (obj != null) {
117: attributeMap.remove(obj);
118: attributeList.remove(obj);
119: }
120:
121: attributeMap.put(new Name(theName, theNamespace), value);
122: attributeList.add(value);
123: }
124:
125: /**
126: * @see org.columba.core.context.base.api.IStructureValue#getParent()
127: */
128: public IStructureValue getParent() {
129: return parent;
130: }
131:
132: /**
133: * @see org.columba.core.context.base.api.IStructureValue#addChild(java.lang.String,
134: * java.lang.String)
135: */
136: public IStructureValue addChild(final String theName,
137: final String theNamespace) {
138: final IStructureType childType = getType().getChild(theName,
139: theNamespace);
140: if (childType == null) {
141: throw new IllegalArgumentException(
142: "child structure type for <" + theName + ","
143: + theNamespace + "> does not exist");
144: }
145:
146: final IStructureValue value = new StructureValue(theName,
147: theNamespace, childType, this );
148: final List<IStructureValue> list = getChildStructureList(
149: theName, theNamespace);
150:
151: if ((childType.getCardinality().equals(MULTIPLICITY.ONE_TO_ONE) || getType()
152: .getCardinality().equals(MULTIPLICITY.ZERO_TO_ONE))
153: && (list.size() == 1)) {
154: // contains already a single element
155: throw new IllegalArgumentException(
156: "multiplicity of ONE_TO_ONE or ZERO_TO_ONE doesn't allow adding more children to this structure");
157: }
158:
159: list.add(value);
160:
161: return value;
162: }
163:
164: /**
165: * @param theName
166: * @param theNamespace
167: * @return
168: */
169: private int getChildStructureCount(final String theName,
170: final String theNamespace) {
171: if (valueMap.containsKey(new Name(theName, theNamespace))) {
172: final List<IStructureValue> list = valueMap.get(new Name(
173: theName, theNamespace));
174: return list.size();
175: }
176: return 0;
177: }
178:
179: /**
180: * @see org.columba.core.context.base.api.IStructureValue#removeChild(java.lang.String,
181: * java.lang.String, int)
182: */
183: public IStructureValue removeChild(final String theName,
184: final String theNamespace, final int index) {
185: final List<IStructureValue> list = valueMap.get(new Name(
186: theName, theNamespace));
187: if (list == null) {
188: throw new IllegalArgumentException("list <" + theName + ","
189: + theNamespace + "> is empty");
190: }
191:
192: final IStructureValue value = list.get(index);
193: if (value == null) {
194: throw new IllegalArgumentException("no element at index "
195: + index);
196: }
197:
198: list.remove(index);
199:
200: return value;
201: }
202:
203: /**
204: * @param theName
205: * @param theNamespace
206: * @return
207: */
208: private List<IStructureValue> getChildStructureList(
209: final String theName, final String theNamespace) {
210: final int count = getChildStructureCount(theName, theNamespace);
211:
212: if (count == 0) {
213: // create empty list
214: final List<IStructureValue> list = new Vector<IStructureValue>();
215: valueMap.put(new Name(theName, theNamespace), list);
216: return list;
217: }
218: final List<IStructureValue> list = valueMap.get(new Name(
219: theName, theNamespace));
220: return list;
221: }
222:
223: @Override
224: public String toString() {
225: final StringBuilder buf = new StringBuilder();
226: buf.append("StructureValue["); //$NON-NLS-1$
227: buf.append("name=" + getName()); //$NON-NLS-1$
228: buf.append(", namespace" + getNamespace()); //$NON-NLS-1$
229: buf.append(']');
230: return buf.toString();
231: }
232:
233: /**
234: * @see org.columba.core.context.base.api.IStructureValue#isValid()
235: */
236: public boolean isValid() {
237: // TODO implement validation
238: return true;
239: }
240:
241: public Iterator<IName> getAllAttributeNames() {
242: return attributeMap.keySet().iterator();
243: }
244:
245: /**
246: * @see org.columba.core.context.base.api.IStructureValue#getAttributeIterator()
247: */
248: public Iterator<Object> getAttributeIterator() {
249: return attributeList.listIterator();
250: }
251:
252: /**
253: * @see org.columba.core.context.base.api.IStructureValue#getChildIterator(java.lang.String,
254: * java.lang.String)
255: */
256: public Iterator<IStructureValue> getChildIterator(
257: final String theName, final String theNamespace) {
258: List<IStructureValue> list = valueMap.get(new Name(theName,
259: theNamespace));
260: if (list == null) {
261: // create empty structure value
262: list = new Vector<IStructureValue>();
263: }
264:
265: return list.listIterator();
266:
267: }
268:
269: /**
270: * @see org.columba.core.context.base.api.IStructureValue#removeAllChildren(java.lang.String,
271: * java.lang.String)
272: */
273: public void removeAllChildren(final String theName,
274: final String theNamespace) {
275: valueMap.remove(new Name(theName, theNamespace));
276: }
277:
278: /**
279: * @see org.columba.core.context.base.api.IStructureValue#getString(java.lang.String,
280: * java.lang.String)
281: */
282: public String getString(final String theName,
283: final String theNamespace) {
284: final IAttributeType t = getType().getAttribute(theName,
285: theNamespace);
286: if (!t.getBaseType().equals(BASETYPE.STRING)) {
287: throw new IllegalArgumentException("attribute <" + theName
288: + "," + theNamespace + "> is not of type String");
289: }
290:
291: return (String) getObject(theName, theNamespace);
292: }
293:
294: public void setString(final String theName,
295: final String theNamespace, final String value) {
296: final IAttributeType t = getType().getAttribute(theName,
297: theNamespace);
298: if (!t.getBaseType().equals(BASETYPE.STRING)) {
299: throw new IllegalArgumentException("attribute <" + theName
300: + "," + theNamespace + "> is not of type String");
301: }
302:
303: setObject(theName, theNamespace, value);
304: }
305:
306: public int getInteger(final String theName,
307: final String theNamespace) {
308: final IAttributeType t = getType().getAttribute(theName,
309: theNamespace);
310: if (!t.getBaseType().equals(BASETYPE.INTEGER)) {
311: throw new IllegalArgumentException("attribute <" + theName
312: + "," + theNamespace + "> is not of type Integer");
313: }
314:
315: return (Integer) getObject(theName, theNamespace);
316: }
317:
318: public void setInteger(final String theName,
319: final String theNamespace, final int value) {
320: final IAttributeType t = getType().getAttribute(theName,
321: theNamespace);
322: if (!t.getBaseType().equals(BASETYPE.INTEGER)) {
323: throw new IllegalArgumentException("attribute <" + theName
324: + "," + theNamespace + "> is not of type Integer");
325: }
326:
327: setObject(theName, theNamespace, value);
328: }
329:
330: public Date getDate(final String theName, final String theNamespace) {
331: final IAttributeType t = getType().getAttribute(theName,
332: theNamespace);
333: if (!t.getBaseType().equals(BASETYPE.DATE)) {
334: throw new IllegalArgumentException("attribute <" + theName
335: + "," + theNamespace + "> is not of type Date");
336: }
337:
338: return (Date) getObject(theName, theNamespace);
339: }
340:
341: public void setDate(final String theName,
342: final String theNamespace, final Date value) {
343: final IAttributeType t = getType().getAttribute(theName,
344: theNamespace);
345: if (!t.getBaseType().equals(BASETYPE.DATE)) {
346: throw new IllegalArgumentException("attribute <" + theName
347: + "," + theNamespace + "> is not of type Date");
348: }
349:
350: setObject(theName, theNamespace, value);
351: }
352:
353: public float getFloat(final String theName,
354: final String theNamespace) {
355: final IAttributeType t = getType().getAttribute(theName,
356: theNamespace);
357: if (!t.getBaseType().equals(BASETYPE.FLOAT)) {
358: throw new IllegalArgumentException("attribute <" + theName
359: + "," + theNamespace + "> is not of type Float");
360: }
361:
362: return (Float) getObject(theName, theNamespace);
363: }
364:
365: public void setFloat(final String theName,
366: final String theNamespace, final float value) {
367: final IAttributeType t = getType().getAttribute(theName,
368: theNamespace);
369: if (!t.getBaseType().equals(BASETYPE.FLOAT)) {
370: throw new IllegalArgumentException("attribute <" + theName
371: + "," + theNamespace + "> is not of type Float");
372: }
373: setObject(theName, theNamespace, value);
374: }
375:
376: public double getDouble(final String theName,
377: final String theNamespace) {
378: final IAttributeType t = getType().getAttribute(theName,
379: theNamespace);
380: if (!t.getBaseType().equals(BASETYPE.DOUBLE)) {
381: throw new IllegalArgumentException("attribute <" + theName
382: + "," + theNamespace + "> is not of type Double");
383: }
384:
385: return (Double) getObject(theName, theNamespace);
386: }
387:
388: public void setDouble(final String theName,
389: final String theNamespace, final double value) {
390: final IAttributeType t = getType().getAttribute(theName,
391: theNamespace);
392: if (!t.getBaseType().equals(BASETYPE.DOUBLE)) {
393: throw new IllegalArgumentException("attribute <" + theName
394: + "," + theNamespace + "> is not of type Double");
395: }
396: setObject(theName, theNamespace, value);
397: }
398:
399: public byte[] getByteArray(final String theName,
400: final String theNamespace) {
401: final IAttributeType t = getType().getAttribute(theName,
402: theNamespace);
403: if (!t.getBaseType().equals(BASETYPE.BINARY)) {
404: throw new IllegalArgumentException("attribute <" + theName
405: + "," + theNamespace + "> is not of type binary");
406: }
407:
408: return (byte[]) getObject(theName, theNamespace);
409: }
410:
411: public void setByteArray(final String theName,
412: final String theNamespace, final byte[] value) {
413: final IAttributeType t = getType().getAttribute(theName,
414: theNamespace);
415: if (!t.getBaseType().equals(BASETYPE.BINARY)) {
416: throw new IllegalArgumentException("attribute <" + theName
417: + "," + theNamespace + "> is not of type binary");
418: }
419: setObject(theName, theNamespace, value);
420: }
421:
422: public InputStream getInputStream(final String theName,
423: final String theNamespace) {
424: final IAttributeType t = getType().getAttribute(theName,
425: theNamespace);
426: if (!t.getBaseType().equals(BASETYPE.INPUTSTREAM)) {
427: throw new IllegalArgumentException("attribute <" + theName
428: + "," + theNamespace
429: + "> is not of type blob (binary inputstream)");
430: }
431:
432: return (InputStream) getObject(theName, theNamespace);
433: }
434:
435: public void setInputStream(final String theName,
436: final String theNamespace, final InputStream value) {
437: final IAttributeType t = getType().getAttribute(theName,
438: theNamespace);
439: if (!t.getBaseType().equals(BASETYPE.INPUTSTREAM)) {
440: throw new IllegalArgumentException("attribute <" + theName
441: + "," + theNamespace
442: + "> is not of type blob (binary inputstream)");
443: }
444: setObject(theName, theNamespace, value);
445: }
446:
447: public Iterator<IName> getAllChildNames() {
448: return valueMap.keySet().iterator();
449: }
450:
451: }
|