001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.sql.framework.model.impl;
042:
043: import java.util.ArrayList;
044: import java.util.Collection;
045: import java.util.HashMap;
046: import java.util.Iterator;
047: import java.util.List;
048: import java.util.Map;
049:
050: import org.netbeans.modules.sql.framework.common.utils.TagParserUtility;
051: import org.netbeans.modules.sql.framework.common.utils.XmlUtil;
052: import org.netbeans.modules.sql.framework.model.SQLConstants;
053: import org.netbeans.modules.sql.framework.model.SQLObject;
054: import org.w3c.dom.Element;
055: import org.w3c.dom.Node;
056: import org.w3c.dom.NodeList;
057: import net.java.hulp.i18n.Logger;
058: import com.sun.sql.framework.exception.BaseException;
059: import com.sun.sql.framework.utils.Attribute;
060: import org.netbeans.modules.etl.logger.Localizer;
061: import org.netbeans.modules.etl.logger.LogUtil;
062:
063: /**
064: * This basic class provides sql framework functionality to all SQLObjects
065: *
066: * @author Ritesh Adval
067: * @version $Revision$
068: */
069: public abstract class AbstractSQLObject implements SQLObject {
070: /* Log4J category string */
071:
072: private static final String LOG_CATEGORY = AbstractSQLObject.class
073: .getName();
074: private static transient final Logger mLogger = LogUtil
075: .getLogger(AbstractSQLObject.class.getName());
076: private static transient final Localizer mLoc = Localizer.get();
077: /**
078: * Map of attributes; used by concrete implementations to store class-specific fields
079: * without hardcoding them as member variables
080: */
081: protected Map attributes = new HashMap();
082: /** User-modifiable display name for this object */
083: protected transient String displayName;
084: /** Unique handle for SQLObject-related referencing purposes */
085: protected transient String id;
086: /** String representation of object type */
087: protected transient String objectType;
088: /** Object instance that "owns" this AbstractSQLObject instance. */
089: protected transient Object parentObject;
090: /** int representation of object type */
091: protected int type;
092: private transient boolean isIdSet = false;
093:
094: /** Creates a new instance of SQLBasicObject */
095: public AbstractSQLObject() {
096: }
097:
098: /**
099: * all sql objects are cloneable
100: *
101: * @return cloned SQL object
102: * @throws CloneNotSupportedException - exception
103: */
104: public Object cloneSQLObject() throws CloneNotSupportedException {
105: return this .clone();
106: }
107:
108: /**
109: * Copy
110: *
111: * @param source - source
112: */
113: public void copyFromSource(SQLObject source) {
114: if (source == null) {
115: throw new java.lang.IllegalArgumentException(
116: "Require non-null SQLObject instance:" + source);
117: }
118: this .displayName = source.getDisplayName();
119: // id is set only once for an object
120: if (this .getId() == null) {
121: this .id = source.getId();
122: }
123:
124: this .type = source.getObjectType();
125: this .parentObject = source.getParentObject();
126:
127: // clone attributes
128: Collection attrNames = source.getAttributeNames();
129: Iterator it = attrNames.iterator();
130:
131: while (it.hasNext()) {
132: String name = (String) it.next();
133: Attribute attr = source.getAttribute(name);
134: if (attr != null) {
135: try {
136: Attribute copiedAttr = (Attribute) attr.clone();
137: this .attributes.put(name, copiedAttr);
138: } catch (CloneNotSupportedException ex) {
139: // log me
140: mLogger
141: .errorNoloc(
142: mLoc
143: .t(
144: "PRSR105: Failed to copy source objects{0}",
145: LOG_CATEGORY), ex);
146: }
147: }
148: }
149: }
150:
151: /**
152: * Overrides default implementation to compute hashcode based on any associated
153: * attributes as well as values of non-transient member variables.
154: *
155: * @param o Object to test for equality with this
156: * @return hashcode for this instance
157: */
158: public boolean equals(Object o) {
159: if (o == null) {
160: return false;
161: } else if (o == this ) {
162: return true;
163: }
164:
165: boolean response = false;
166:
167: if (o instanceof AbstractSQLObject) {
168: AbstractSQLObject target = (AbstractSQLObject) o;
169:
170: // check for type
171: response = (type == target.type);
172:
173: // check for display name
174: response &= (this .getDisplayName() != null) ? this
175: .getDisplayName().equals(target.getDisplayName())
176: : (target.getDisplayName() == null);
177:
178: // check for attributes
179: response &= (attributes != null) ? attributes
180: .equals(target.attributes)
181: : (target.attributes == null);
182:
183: // check for id
184: // FOR NOW we check if both ids are avialable then only do equal
185: // comparison, TODO: in future we should always do id comparison
186: // we need to make sure that id is always available for that.
187: if (this .id != null && target.id != null) {
188: response &= (this .id != null) ? this .id.equals(target
189: .getId()) : (target.getId() == null);
190: }
191: }
192:
193: return response;
194: }
195:
196: /**
197: * Gets an attribute based on its name
198: *
199: * @param attrName attribute Name
200: * @return Attribute instance associated with attrName, or null if none exists
201: */
202: public Attribute getAttribute(String attrName) {
203: return (Attribute) attributes.get(attrName);
204: }
205:
206: /**
207: * @see SQLObject#getAttributeNames
208: */
209: public Collection getAttributeNames() {
210: return attributes.keySet();
211: }
212:
213: /**
214: * @see SQLObject#getAttributeObject
215: */
216: public Object getAttributeObject(String attrName) {
217: Attribute attr = getAttribute(attrName);
218: return (attr != null) ? attr.getAttributeValue() : null;
219: }
220:
221: /**
222: * Gets List of child SQLObjects belonging to this instance.
223: *
224: * @return List of child SQLObjects
225: */
226: public List getChildSQLObjects() {
227: return new ArrayList(1);
228: }
229:
230: /**
231: * @see SQLObject#getDisplayName
232: */
233: public String getDisplayName() {
234: return this .displayName;
235: }
236:
237: /**
238: * @see SQLObject#getFooter
239: */
240: public String getFooter() {
241: StringBuilder buf = new StringBuilder();
242: buf.append("</").append(TAG_SQLOBJECT).append(">\n");
243: return buf.toString();
244: }
245:
246: /**
247: * @see SQLObject#getHeader
248: */
249: public String getHeader() {
250: String strType = "";
251: try {
252: strType = TagParserUtility.getStringType(this
253: .getObjectType());
254: } catch (BaseException e) {
255: mLogger.infoNoloc(mLoc.t(
256: "PRSR106: Failed to get type attr.{0}",
257: LOG_CATEGORY));
258: strType = "UNKNOWN_TYPE";
259: }
260: StringBuilder buffer = new StringBuilder();
261: buffer.append("<" + TAG_SQLOBJECT + " " + OBJECT_TYPE + "=\"");
262: if (strType != null) {
263: buffer.append(strType);
264: }
265:
266: buffer.append("\" " + ID + "=\"");
267: if (id != null) {
268: buffer.append(id.trim());
269: }
270:
271: buffer.append("\" " + DISPLAY_NAME + "=\"");
272: if (this .getDisplayName() != null) {
273: buffer.append(XmlUtil.escapeXML(this .getDisplayName()
274: .trim()));
275: }
276: buffer.append("\">\n");
277:
278: return buffer.toString();
279: }
280:
281: /**
282: * @see SQLObject#getId
283: */
284: public String getId() {
285: return this .id;
286: }
287:
288: /**
289: * @see SQLObject#getJdbcType
290: */
291: public int getJdbcType() {
292: return SQLConstants.JDBCSQL_TYPE_UNDEFINED;
293: }
294:
295: /**
296: * @see SQLObject#getObjectType
297: */
298: public int getObjectType() {
299: return type;
300: }
301:
302: /**
303: * @see SQLObject#getOutput(java.lang.String)
304: */
305: public SQLObject getOutput(String argName) throws BaseException {
306: return this ;
307: }
308:
309: /**
310: * @see SQLObject#getParentObject
311: */
312: public Object getParentObject() {
313: return this .parentObject;
314: }
315:
316: /**
317: * Overrides default implementation to compute hashcode based on any associated
318: * attributes as well as values of non-transient member variables.
319: *
320: * @return hashcode for this instance
321: */
322: public int hashCode() {
323: return type + ((id != null) ? id.hashCode() : 0)
324: + ((attributes != null) ? attributes.hashCode() : 0);
325: }
326:
327: /**
328: * @see SQLObject#parseXML
329: */
330: public void parseXML(Element xmlElement) throws BaseException {
331: parseCommonAttributesAndTags(xmlElement);
332: }
333:
334: /**
335: * Clear id and parent object
336: */
337: public void reset() {
338: this .id = null;
339: this .isIdSet = false;
340: this .parentObject = null;
341: }
342:
343: /**
344: * @see SQLObject#secondPassParse
345: */
346: public void secondPassParse(Element element) throws BaseException {
347: }
348:
349: /**
350: * @see SQLObject#setAttribute
351: */
352: public void setAttribute(String attrName, Object val) {
353: Attribute attr = getAttribute(attrName);
354: if (attr != null) {
355: attr.setAttributeValue(val);
356: } else {
357: attr = new Attribute(attrName, val);
358: attributes.put(attrName, attr);
359: }
360: }
361:
362: /**
363: * @see SQLObject#setDisplayName
364: */
365: public void setDisplayName(String newName) {
366: displayName = (newName != null) ? newName.trim() : "";
367: }
368:
369: /**
370: * @see SQLObject#setId
371: */
372: public void setId(String newId) throws BaseException {
373: // ID will be set only once in this object's lifetime.
374: if (isIdSet) {
375: return;
376: }
377:
378: if (newId == null) {
379: throw new BaseException(
380: "Must supply non-null String ref for newId.");
381: }
382:
383: isIdSet = true;
384: this .id = newId;
385: }
386:
387: /**
388: * @see SQLObject#setJdbcType(int)
389: */
390: public void setJdbcType(int newType) {
391: // Ignore for default implementation.
392: }
393:
394: /**
395: * @see SQLObject#setParentObject
396: */
397: public void setParentObject(Object newParent) throws BaseException {
398: if (newParent == null) {
399: throw new BaseException(
400: "Must supply non-null Object ref for newParent.");
401: }
402: this .parentObject = newParent;
403: }
404:
405: /**
406: * Generates XML document representing this object's content, using the given String
407: * as a prefix for each line.
408: *
409: * @param prefix String to be prepended to each line of the generated XML document
410: * @return String containing XML representation
411: * @exception BaseException - exception
412: * @see SQLObject#toXMLString(java.lang.String)
413: */
414: public String toXMLString(String prefix) throws BaseException {
415: StringBuilder buf = new StringBuilder(200);
416:
417: buf.append(prefix).append(getHeader());
418: buf.append(toXMLAttributeTags(prefix));
419: buf.append(prefix).append(getFooter());
420:
421: return buf.toString();
422: }
423:
424: /**
425: * Parse common attributes
426: *
427: * @param xmlElement - element
428: * @throws BaseException - exception
429: */
430: protected void parseCommonAttributesAndTags(Element xmlElement)
431: throws BaseException {
432: // Some sql framework parsing elements can be in AbstractSQLObject.
433: if (xmlElement == null) {
434: throw new BaseException("xmlElement is null");
435: }
436: if (this .parentObject == null) {
437: throw new BaseException("ParentObject is null");
438: }
439:
440: setDisplayName(xmlElement.getAttribute(SQLObject.DISPLAY_NAME));
441: setId(xmlElement.getAttribute(SQLObject.ID));
442:
443: NodeList list = xmlElement.getChildNodes();
444: parseAttributeList(list);
445: }
446:
447: /**
448: * Generates XML elements representing this object's associated attributes.
449: *
450: * @param prefix Prefix string to be prepended to each element
451: * @return String containing XML representation of attributes
452: */
453: protected String toXMLAttributeTags(String prefix) {
454: StringBuilder buf = new StringBuilder(100);
455:
456: Iterator iter = attributes.values().iterator();
457: while (iter.hasNext()) {
458: Attribute attr = (Attribute) iter.next();
459: if (attr.getAttributeValue() != null) {
460: buf.append(attr.toXMLString(prefix + "\t"));
461: }
462: }
463:
464: return buf.toString();
465: }
466:
467: private void parseAttributeList(NodeList list) throws BaseException {
468: for (int i = 0; i < list.getLength(); i++) {
469: if (list.item(i).getNodeType() == Node.ELEMENT_NODE) {
470: Element elem = (Element) list.item(i);
471: if (elem.getNodeName().equals(Attribute.TAG_ATTR)) {
472: Attribute attr = new Attribute();
473: attr.parseXMLString(elem);
474: this.attributes.put(attr.getAttributeName(), attr);
475: }
476: }
477: }
478: }
479: }
|