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.xml.xam;
043:
044: /**
045: * Represents reference to a component. On writing, this indirection help serialize
046: * the referenced component as an attribute string value. On reading, the referenced
047: * can be resolved on demand.
048: * <p>
049: * Note: Client code should always check for brokeness before access the referenced.
050: *
051: * @author rico
052: * @author Nam Nguyen
053: * @author Chris Webster
054: */
055: public abstract class AbstractReference<T extends Referenceable>
056: implements Reference<T> {
057:
058: private T referenced;
059: private Class<T> classType;
060: private AbstractComponent parent;
061: protected String refString;
062:
063: /**
064: * Constructor for writing.
065: * @param referenced the component being referenced
066: * @param referencedType type of the referenced component
067: * @param parent referencing component on which the referenced is serialized
068: * as an attribute string value.
069: */
070: public AbstractReference(T referenced, Class<T> referencedType,
071: AbstractComponent parent) {
072: if (referenced == null) {
073: throw new IllegalArgumentException(
074: "Referenced component null"); //NOI18N
075: }
076: checkParentAndType(parent, referencedType);
077: this .referenced = referenced;
078: this .classType = referencedType;
079: this .parent = parent;
080: }
081:
082: /**
083: * Constructor for reading.
084: * @param referencedType type of the referenced component
085: * @param parent referencing component on which the referenced is serialized
086: * as an attribute string value.
087: * @param ref the string value used in resolving.
088: */
089: public AbstractReference(Class<T> referencedType,
090: AbstractComponent parent, String ref) {
091: checkParentAndType(parent, referencedType);
092: this .refString = ref;
093: this .classType = referencedType;
094: this .parent = parent;
095: }
096:
097: /**
098: * Access method for referenced.
099: */
100: protected T getReferenced() {
101: return referenced;
102: }
103:
104: /**
105: * Accessor method for referenced.
106: */
107: protected void setReferenced(T referenced) {
108: this .referenced = referenced;
109: }
110:
111: /**
112: * Returns type of the referenced component
113: */
114: public Class<T> getType() {
115: return classType;
116: }
117:
118: /**
119: * Returns true if the reference cannot be resolved in the current document
120: */
121: public boolean isBroken() {
122: try {
123: return get() == null;
124: } catch (IllegalStateException ise) {
125: referenced = null;
126: return false;
127: }
128: }
129:
130: /**
131: * Returns true if this reference refers to the target component.
132: */
133: public boolean references(T target) {
134: return get() == target;
135: }
136:
137: /**
138: * @return string to use in persiting the reference as attribute value of
139: * the containing component
140: */
141: public String getRefString() {
142: return refString;
143: }
144:
145: @Override
146: public String toString() {
147: return getRefString();
148: }
149:
150: protected AbstractComponent getParent() {
151: return parent;
152: }
153:
154: private void checkParentAndType(AbstractComponent parent,
155: Class<T> classType) {
156: if (parent == null) {
157: throw new IllegalArgumentException("parent == null"); //NOI18N
158: }
159: if (classType == null) {
160: throw new IllegalArgumentException("classType == null"); //NOI18N
161: }
162: }
163:
164: @Override
165: public boolean equals(Object obj) {
166: if (obj == null)
167: return false;
168: if (obj instanceof AbstractReference) {
169: AbstractReference<T> that = (AbstractReference<T>) obj;
170: return refString.equals(that.getRefString())
171: && parent.equals(that.parent)
172: && getType().equals(that.getType());
173: } else {
174: return super .equals(obj);
175: }
176: }
177:
178: @Override
179: public int hashCode() {
180: return parent.hashCode();
181: }
182:
183: }
|