001: /*
002: * The contents of this file are subject to the
003: * Mozilla Public License Version 1.1 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
009: * See the License for the specific language governing rights and
010: * limitations under the License.
011: *
012: * The Initial Developer of the Original Code is Simulacra Media Ltd.
013: * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
014: *
015: * All Rights Reserved.
016: *
017: * Contributor(s):
018: */
019: package org.openharmonise.rm.resources.metadata.properties.ranges;
020:
021: import java.util.Vector;
022:
023: import org.openharmonise.rm.*;
024: import org.openharmonise.rm.factory.*;
025: import org.openharmonise.rm.publishing.*;
026: import org.openharmonise.rm.resources.publishing.Template;
027: import org.w3c.dom.*;
028:
029: /**
030: * Base abstract implementation of the <code>Range</code> interface
031: * for <code>Property</code> ranges. Handles data which define the restrictions on
032: * allowed property instance values.
033: *
034: *
035: * @author Michael Bell
036: * @version $Revision: 1.2 $
037: *
038: */
039: public abstract class AbstractRange implements Range, Publishable,
040: Cloneable {
041:
042: //XML constants
043: /**
044: * The range XML element name
045: */
046: public static final String TAG_RANGE = "Range";
047:
048: /**
049: * The range details XML element name
050: */
051: public static final String TAG_RANGE_DETAILS = "RangeDetails";
052:
053: /**
054: * The range object XML element name
055: */
056: public static final String TAG_RANGE_OBJECT = "RangeObject";
057:
058: /**
059: * The <code>String</code> representation of all non class type restrictions
060: * for this range
061: */
062: protected String m_sDetails = null;
063:
064: /**
065: * The class name of the class restriction for this range
066: */
067: protected String m_sObjectClassName = null;
068:
069: /**
070: * <code>boolean</code> flag which indicates that this range has been changed
071: * since being populated
072: */
073: private boolean m_bIsChanged = false;
074:
075: /**
076: * Constructs a new range.
077: */
078: public AbstractRange() {
079: }
080:
081: /**
082: * Constructs a range with the specified class type restriction.
083: *
084: * @param sObjectClassName the class name of objects within this range
085: */
086: public AbstractRange(String sObjectClassName) {
087: this (sObjectClassName, null);
088: }
089:
090: /**
091: * Constructs a range with the specified class type and other restrictions.
092: *
093: * @param sObjectClassName the class name of objects within this range
094: * @param sDetails a <code>String</code> representation of the non class
095: * type restrictions
096: */
097: public AbstractRange(String sObjectClassName, String sDetails) {
098: m_sObjectClassName = sObjectClassName;
099: m_sDetails = sDetails;
100: }
101:
102: /**
103: * Returns <code>true</code> if this range has restrictions other than
104: * the class type restriction.
105: *
106: * @return <code>true</code> if this range has restrictions other than
107: * the class type restriction
108: */
109: public boolean hasDetails() {
110: return m_sDetails != null;
111: }
112:
113: /* (non-Javadoc)
114: * @see org.openharmonise.rm.resources.metadata.properties.ranges.Range#getDetails()
115: */
116: public String getDetails() {
117:
118: return m_sDetails;
119: }
120:
121: /* (non-Javadoc)
122: * @see org.openharmonise.rm.resources.metadata.properties.ranges.Range#getObject()
123: */
124: public String getObject() {
125:
126: return m_sObjectClassName;
127: }
128:
129: /* (non-Javadoc)
130: * @see org.openharmonise.rm.resources.metadata.properties.ranges.Range#isValid(java.lang.Object)
131: */
132: abstract public boolean isValid(Object obj);
133:
134: /* (non-Javadoc)
135: * @see org.openharmonise.rm.resources.metadata.properties.ranges.Range#setDetails(java.lang.String)
136: */
137: public void setDetails(String sDetails) {
138: m_sDetails = sDetails;
139:
140: }
141:
142: /* (non-Javadoc)
143: * @see java.lang.Object#clone()
144: */
145: public Object clone() {
146: try {
147: return super .clone();
148: } catch (CloneNotSupportedException e) {
149: return null;
150: }
151: }
152:
153: /* (non-Javadoc)
154: * @see org.openharmonise.rm.publishing.Publishable#getTagName()
155: */
156: public String getTagName() {
157: return TAG_RANGE;
158: }
159:
160: /* (non-Javadoc)
161: * @see org.openharmonise.rm.publishing.Publishable#populate(org.w3c.dom.Element, org.openharmonise.rm.publishing.State)
162: */
163: public void populate(Element xmlElement, State state)
164: throws PopulateException {
165: String sTagName = xmlElement.getTagName();
166: Text txt = null;
167: String sTemp = null;
168:
169: if (sTagName.equals(getTagName()) == true
170: || sTagName.equals(TAG_RANGE) == true) {
171: NodeList nodes = xmlElement.getChildNodes();
172:
173: for (int i = 0; i < nodes.getLength(); i++) {
174: if (nodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
175: continue;
176: }
177:
178: Element el = (Element) nodes.item(i);
179: populate(el, state);
180: }
181: } else if (sTagName.equals(TAG_RANGE_OBJECT)) {
182: NodeList nodes = xmlElement.getChildNodes();
183:
184: //need to loop through to avoid whitespace etc
185: for (int i = 0; i < nodes.getLength(); i++) {
186: Node node = nodes.item(i);
187:
188: if (node.getNodeType() == Node.TEXT_NODE) {
189: txt = (Text) node;
190: String sVal = txt.getNodeValue().trim();
191: if (sVal.length() > 0) {
192: this .m_sObjectClassName = sVal;
193: break;
194: }
195: } else if (node.getNodeType() == Node.ELEMENT_NODE) {
196: try {
197: String sClassname = HarmoniseObjectFactory
198: .getClassName((Element) node);
199: this .m_sObjectClassName = sClassname;
200: break;
201: } catch (HarmoniseFactoryException e) {
202: throw new PopulateException(e);
203: }
204: }
205: }
206:
207: } else if (sTagName.equals(TAG_RANGE_DETAILS)) {
208: txt = (Text) xmlElement.getFirstChild();
209: setDetails(txt.getNodeValue());
210: }
211:
212: }
213:
214: /* (non-Javadoc)
215: * @see org.openharmonise.rm.publishing.Publishable#publish(org.w3c.dom.Element, org.openharmonise.rm.publishing.HarmoniseOutput, org.openharmonise.rm.publishing.State)
216: */
217: public Element publish(Element topEl, HarmoniseOutput output,
218: State state) throws PublishException {
219: Element docEl = null;
220: NodeList nodes = null;
221: Text txt = null;
222: String sTagName = topEl.getTagName();
223:
224: try {
225:
226: if (sTagName.equals(getTagName())
227: || sTagName.equals(TAG_RANGE)) {
228: docEl = output.createElement(getTagName());
229:
230: nodes = topEl.getChildNodes();
231: } else if (sTagName.equals(TAG_RANGE_OBJECT)) {
232: docEl = output.createElement(sTagName);
233: txt = output.createTextNode(getObject());
234: docEl.appendChild(txt);
235: output.copyChildren(docEl, topEl, new Vector());
236: } else if (sTagName.equals(TAG_RANGE_DETAILS)) {
237: docEl = output.createElement(sTagName);
238: txt = output.createTextNode(getDetails());
239: docEl.appendChild(txt);
240: output.copyChildren(docEl, topEl, new Vector());
241: }
242:
243: // recurse through the children if there are any
244: Element formEl;
245: Element el;
246:
247: if (nodes != null) {
248: for (int i = 0; i < nodes.getLength(); i++) {
249: if (nodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
250: continue;
251: }
252:
253: formEl = (Element) nodes.item(i);
254: el = publish(formEl, output, state);
255:
256: if (el != null) {
257: docEl.appendChild(el);
258: }
259: }
260: }
261:
262: } catch (Exception ex) {
263: throw new PublishException(ex.getLocalizedMessage());
264: }
265:
266: return docEl;
267: }
268:
269: /* (non-Javadoc)
270: * @see org.openharmonise.rm.publishing.Publishable#publish(org.openharmonise.rm.resources.publishing.Template, org.openharmonise.rm.publishing.HarmoniseOutput, org.openharmonise.rm.publishing.State)
271: */
272: public Element publish(Template template, HarmoniseOutput output,
273: State state) throws PublishException {
274: Element resultEl = null;
275:
276: try {
277:
278: resultEl = publish(template.getTemplateRootElement(),
279: output, state);
280: } catch (DataAccessException e) {
281: throw new PublishException(e);
282: }
283:
284: return resultEl;
285: }
286:
287: /**
288: * Sets the <code>boolean</code> flag which indicates a change to this range.
289: *
290: * @param bIsChanged <code>true</code> to indicate that this range has been
291: * changed since population
292: */
293: public void isChanged(boolean bIsChanged) {
294: m_bIsChanged = bIsChanged;
295: }
296:
297: /**
298: * Returns <code>true</code> if this range has changed since population.
299: *
300: * @return <code>true</code> if this range has changed since population
301: */
302: public boolean isChanged() {
303: return m_bIsChanged;
304: }
305:
306: /* (non-Javadoc)
307: * @see java.lang.Object#equals(java.lang.Object)
308: */
309: public boolean equals(Object obj) {
310: boolean bResult = false;
311:
312: if (obj instanceof AbstractRange) {
313: AbstractRange range = (AbstractRange) obj;
314:
315: if (this == range) {
316: bResult = true;
317: } else {
318: bResult = true;
319:
320: bResult = m_sObjectClassName.equals(range.getObject());
321:
322: if (bResult == true) {
323:
324: String sDetails = getDetails();
325: String sOtherDetails = range.getDetails();
326:
327: if ((sDetails == null && sOtherDetails != null)
328: || (sOtherDetails == null && sDetails != null)
329: || (sDetails != null && sDetails
330: .equals(sOtherDetails) == false)) {
331: bResult = false;
332: }
333: }
334:
335: }
336: }
337:
338: return bResult;
339: }
340:
341: /* (non-Javadoc)
342: * @see java.lang.Object#toString()
343: */
344: public String toString() {
345: StringBuffer strbuf = new StringBuffer();
346:
347: strbuf.append("range [obj - ").append(m_sObjectClassName)
348: .append("]");
349: strbuf.append("[ details - ").append(m_sDetails).append("]");
350:
351: return strbuf.toString();
352: }
353:
354: /* (non-Javadoc)
355: * @see org.openharmonise.rm.resources.metadata.properties.ranges.Range#getPropertyInstanceClass()
356: */
357: abstract public Class getPropertyInstanceClass()
358: throws ClassNotFoundException;
359:
360: }
|