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-2006 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:
042: package org.netbeans.modules.dbschema;
043:
044: import java.beans.PropertyChangeListener;
045: import java.beans.PropertyChangeSupport;
046: import java.text.Collator;
047:
048: /** Base class for representations of elements corresponding to the database metadata.
049: */
050: public abstract class DBElement implements Comparable,
051: DBElementProperties {
052:
053: /** Implementation */
054: Impl impl;
055:
056: /** Default constructor.
057: */
058: public DBElement() {
059: }
060:
061: /** Creates a new element with the provided implementation. The implementation
062: * is responsible for storing all properties of the object.
063: * @param impl the implementation to use
064: */
065: protected DBElement(Impl impl) {
066: this .impl = impl;
067: impl.attachToElement(this );
068: }
069:
070: /** Returns the implementation of the element.
071: * @return implementation for the element
072: */
073: public final Impl getElementImpl() {
074: return (DBElement.Impl) impl;
075: }
076:
077: /** Sets the implementation factory of this database element.
078: * This method should only be used internally and for cloning
079: * and archiving.
080: * @param impl the implementation to use
081: */
082: public void setElementImpl(DBElement.Impl anImpl) {
083: impl = anImpl;
084:
085: if (impl != null)
086: impl.attachToElement(this );
087: }
088:
089: /** Gets the name of this element.
090: * @return the name
091: */
092: public DBIdentifier getName() { //cannot be final because of overriding in ColumnPairElement
093: DBIdentifier name = getElementImpl().getName();
094:
095: return name;
096: }
097:
098: /** Sets the name of this element.
099: * @param name the name
100: * @throws DBException if impossible
101: */
102: public final void setName(DBIdentifier name) throws DBException {
103: getElementImpl().setName(name);
104: }
105:
106: /** Add a property change listener.
107: * @param l the listener to add
108: * @see DBElementProperties
109: */
110: public final void addPropertyChangeListener(PropertyChangeListener l) {
111: getElementImpl().addPropertyChangeListener(l);
112: }
113:
114: /** Remove a property change listener.
115: * @param l the listener to remove
116: * @see DBElementProperties
117: */
118: public final void removePropertyChangeListener(
119: PropertyChangeListener l) {
120: getElementImpl().removePropertyChangeListener(l);
121: }
122:
123: /** Gets a string representation of the element.
124: * @return the string
125: */
126: public String toString() {
127: return getName().toString();
128: }
129:
130: /** Compares two elements.
131: * @param obj the reference object with which to compare.
132: * @return the value 0 if the argument object is equal to
133: * this object; -1 if this object is less than the object
134: * argument; and 1 if this object is greater than the object argument.
135: * Null objects are "smaller".
136: */
137: public int compareTo(Object obj) {
138: // null is not allowed
139: if (obj == null)
140: throw new ClassCastException();
141: if (obj == this )
142: return 0;
143:
144: String this Name = getName().getFullName();
145: String otherName = ((DBElement) obj).getName().getFullName();
146:
147: if (this Name == null)
148: return (otherName == null) ? 0 : -1;
149:
150: if (otherName == null)
151: return 1;
152:
153: int ret = Collator.getInstance().compare(this Name, otherName);
154: // if both names are equal, both objects might have different types.
155: // If so order both objects by their type names
156: // (necessary to be consistent with equals)
157: if ((ret == 0) && (getClass() != obj.getClass()))
158: ret = getClass().getName().compareTo(
159: obj.getClass().getName());
160:
161: return ret;
162: }
163:
164: /** Indicates whether some other object is "equal to" this one.
165: * @return true if this object is the same as the obj argument; false otherwise.
166: */
167: public boolean equals(Object obj) {
168: if (obj == null)
169: return false;
170: if (obj == this )
171: return true;
172:
173: // check for the right class and then do the name check
174: // by calling compareTo.
175: return (getClass() == obj.getClass()) && (compareTo(obj) == 0);
176: }
177:
178: /** Returns a hash code value for the element.
179: * @return a hash code value for this object.
180: */
181: public int hashCode() {
182: return (getName() != null && getName().getFullName() != null) ? getName()
183: .getFullName().hashCode()
184: : 0;
185: }
186:
187: /** Pluggable implementation of the storage of element properties.
188: * @see DBElement#DBElement
189: */
190: public interface Impl {
191: /** Add some items. */
192: public static final int ADD = 1;
193: /** Remove some items. */
194: public static final int REMOVE = -1;
195: /** Set some items, replacing the old ones. */
196: public static final int SET = 0;
197:
198: /** Called to attach the implementation to a specific
199: * element. Will be called in the element's constructor.
200: * Allows implementors of this interface to store a reference to the
201: * holder class, useful for implementing the property change listeners.
202: *
203: * @param element the element to attach to
204: */
205: public void attachToElement(DBElement el);
206:
207: /** Get the name of this element.
208: * @return the name
209: */
210: public DBIdentifier getName();
211:
212: /** Set the name of this element.
213: * @param name the name
214: * @throws DBException if impossible
215: */
216: public void setName(DBIdentifier name) throws DBException;
217:
218: /** Add a property change listener.
219: * @param l the listener to add
220: */
221: public void addPropertyChangeListener(PropertyChangeListener l);
222:
223: /** Remove a property change listener.
224: * @param l the listener to remove
225: */
226: public void removePropertyChangeListener(
227: PropertyChangeListener l);
228: }
229:
230: /** Default implementation of the Impl interface.
231: * It just holds the property values.
232: */
233: static abstract class Memory implements DBElement.Impl {
234: /** the element for this implementation */
235: protected DBElement _element;
236:
237: /** Name of this element */
238: private DBIdentifier _name;
239:
240: /** Property change support */
241: private PropertyChangeSupport support;
242:
243: /** Constructor */
244: public Memory() {
245: super ();
246: }
247:
248: /** Copy */
249: public Memory(DBElement el) {
250: super ();
251: _name = el.getName();
252: }
253:
254: /** Attaches to element */
255: public void attachToElement(DBElement element) {
256: _element = element;
257: }
258:
259: /** Getter for name of the element.
260: * @return the name
261: */
262: public final synchronized DBIdentifier getName() {
263: if (_name == null) // lazy initialization !?
264: _name = DBIdentifier.create(""); //NOI18N
265:
266: return _name;
267: }
268:
269: /** Setter for name of the element.
270: * @param name the name of the element
271: */
272: public synchronized void setName(DBIdentifier name) {
273: DBIdentifier old = _name;
274:
275: _name = name;
276: firePropertyChange(PROP_NAME, old, name);
277: }
278:
279: /** Fires property change event.
280: * @param name property name
281: * @param o old value
282: * @param n new value
283: */
284: protected final void firePropertyChange(String name, Object o,
285: Object n) {
286: if (support != null)
287: support.firePropertyChange(name, o, n);
288: }
289:
290: /** Adds property listener */
291: public synchronized void addPropertyChangeListener(
292: PropertyChangeListener l) {
293: if (support == null)
294: synchronized (this ) {
295: // new test under synchronized block
296: if (support == null)
297: support = new PropertyChangeSupport(_element);
298: }
299:
300: support.addPropertyChangeListener(l);
301: }
302:
303: /** Removes property listener */
304: public void removePropertyChangeListener(
305: PropertyChangeListener l) {
306: if (support != null)
307: support.removePropertyChangeListener(l);
308: }
309: }
310: }
|