blob: bd825f4ca5bcdc898e53174736452b8d9b667477 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.dbschema;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.text.Collator;
/** Base class for representations of elements corresponding to the database metadata.
*/
public abstract class DBElement implements Comparable, DBElementProperties {
/** Implementation */
Impl impl;
/** Default constructor.
*/
public DBElement() {
}
/** Creates a new element with the provided implementation. The implementation
* is responsible for storing all properties of the object.
* @param impl the implementation to use
*/
protected DBElement(Impl impl) {
this.impl = impl;
impl.attachToElement(this);
}
/** Returns the implementation of the element.
* @return implementation for the element
*/
public final Impl getElementImpl() {
return impl;
}
/** Sets the implementation factory of this database element.
* This method should only be used internally and for cloning
* and archiving.
* @param impl the implementation to use
*/
public void setElementImpl (DBElement.Impl anImpl) {
impl = anImpl;
if (impl != null)
impl.attachToElement(this);
}
/** Gets the name of this element.
* @return the name
*/
public DBIdentifier getName() { //cannot be final because of overriding in ColumnPairElement
DBIdentifier name = getElementImpl().getName();
return name;
}
/** Sets the name of this element.
* @param name the name
* @throws DBException if impossible
*/
public final void setName(DBIdentifier name) throws DBException {
getElementImpl().setName(name);
}
/** Add a property change listener.
* @param l the listener to add
* @see DBElementProperties
*/
public final void addPropertyChangeListener(PropertyChangeListener l) {
getElementImpl().addPropertyChangeListener(l);
}
/** Remove a property change listener.
* @param l the listener to remove
* @see DBElementProperties
*/
public final void removePropertyChangeListener(PropertyChangeListener l) {
getElementImpl().removePropertyChangeListener(l);
}
/** Gets a string representation of the element.
* @return the string
*/
public String toString() {
return getName().toString();
}
/** Compares two elements.
* @param obj the reference object with which to compare.
* @return the value 0 if the argument object is equal to
* this object; -1 if this object is less than the object
* argument; and 1 if this object is greater than the object argument.
* Null objects are "smaller".
*/
public int compareTo(Object obj) {
// null is not allowed
if (obj == null)
throw new ClassCastException();
if (obj == this)
return 0;
String thisName = getName().getFullName();
String otherName = ((DBElement) obj).getName().getFullName();
if (thisName == null)
return (otherName == null) ? 0 : -1;
if (otherName == null)
return 1;
int ret = Collator.getInstance().compare(thisName, otherName);
// if both names are equal, both objects might have different types.
// If so order both objects by their type names
// (necessary to be consistent with equals)
if ((ret == 0) && (getClass() != obj.getClass()))
ret = getClass().getName().compareTo(obj.getClass().getName());
return ret;
}
/** Indicates whether some other object is "equal to" this one.
* @return true if this object is the same as the obj argument; false otherwise.
*/
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
// check for the right class and then do the name check
// by calling compareTo.
return (getClass() == obj.getClass()) && (compareTo(obj) == 0);
}
/** Returns a hash code value for the element.
* @return a hash code value for this object.
*/
public int hashCode() {
return (getName() != null && getName().getFullName() != null) ? getName().getFullName().hashCode() : 0;
}
/** Pluggable implementation of the storage of element properties.
* @see DBElement#DBElement
*/
public interface Impl {
/** Add some items. */
public static final int ADD = 1;
/** Remove some items. */
public static final int REMOVE = -1;
/** Set some items, replacing the old ones. */
public static final int SET = 0;
/** Called to attach the implementation to a specific
* element. Will be called in the element's constructor.
* Allows implementors of this interface to store a reference to the
* holder class, useful for implementing the property change listeners.
*
* @param element the element to attach to
*/
public void attachToElement(DBElement el);
/** Get the name of this element.
* @return the name
*/
public DBIdentifier getName();
/** Set the name of this element.
* @param name the name
* @throws DBException if impossible
*/
public void setName(DBIdentifier name) throws DBException;
/** Add a property change listener.
* @param l the listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener l);
/** Remove a property change listener.
* @param l the listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener l);
}
/** Default implementation of the Impl interface.
* It just holds the property values.
*/
static abstract class Memory implements DBElement.Impl {
/** the element for this implementation */
protected DBElement _element;
/** Name of this element */
private DBIdentifier _name;
/** Property change support */
private PropertyChangeSupport support;
/** Constructor */
public Memory() {
super();
}
/** Copy */
public Memory(DBElement el) {
super();
_name = el.getName();
}
/** Attaches to element */
public void attachToElement(DBElement element) {
_element = element;
}
/** Getter for name of the element.
* @return the name
*/
public final synchronized DBIdentifier getName() {
if (_name == null) // lazy initialization !?
_name = DBIdentifier.create(""); //NOI18N
return _name;
}
/** Setter for name of the element.
* @param name the name of the element
*/
public synchronized void setName(DBIdentifier name) {
DBIdentifier old = _name;
_name = name;
firePropertyChange(PROP_NAME, old, name);
}
/** Fires property change event.
* @param name property name
* @param o old value
* @param n new value
*/
protected final void firePropertyChange(String name, Object o, Object n) {
if (support != null)
support.firePropertyChange(name, o, n);
}
/** Adds property listener */
public synchronized void addPropertyChangeListener(PropertyChangeListener l) {
if (support == null)
synchronized (this) {
// new test under synchronized block
if (support == null)
support = new PropertyChangeSupport(_element);
}
support.addPropertyChangeListener(l);
}
/** Removes property listener */
public void removePropertyChangeListener (PropertyChangeListener l) {
if (support != null)
support.removePropertyChangeListener(l);
}
}
}