1 package com.bonevich.erj.model;
2
3 import com.bonevich.erj.ErjConstants;
4 import com.bonevich.util.dependency.Dynamic;
5 import com.bonevich.java.util.ImmutableIterator;
6
7 import java.util.*;
8
9 /*** A class that represents an attribute of a relation
10 * (i.e. a column in a table). Attributes must have a type
11 * (which may be a predefined {@link DataType DataType} or
12 * a user-defined {@link Domain Domain}, both of which
13 * implement the {@link AttributeType AttributeType}
14 * typing interface) and a constraint (NULL or NOTNULL as
15 * defined by {@link AttributeConstraint AttributeConstraint}).
16 * Attributes also may optionally have a default value and
17 * a set of associated keys.
18 *
19 * @see Relation
20 * @see AttributeType
21 * @see AttributeConstraint
22 * @see KeyConstraint
23 * @author Jeffrey D. Bonevich <bonevich@telocity.com>
24 */
25 public final class Attribute extends ModelElement
26 {
27 //////////////////////////////////////////////////////////
28 // Constants
29 public static final String NEW_ATTRIBUTE_STR = "attr_";
30
31 /////////////////////////////////////////////////////////
32 // Attributes
33 // defined in super-class, initialized here
34 {
35 _name = ErjConstants.EMPTY_STR;
36 _identifier = ErjConstants.EMPTY_STR;
37 _description = ErjConstants.EMPTY_STR;
38 }
39
40 /////////////////////////////////////////////////////////
41 // Associations
42 private Relation _relation;
43 private AttributeType _type = (AttributeType)DataType.SQL92_CHAR_VARYING.clone();
44 private DefaultValue _default = DefaultValue.NULL;
45 private AttributeConstraint _constraint = AttributeConstraint.DEFAULT;
46 private List _keys = new LinkedList(); //of KeyConstraints
47
48 /////////////////////////////////////////////////////////
49 // Dynamic Sentries
50 private Dynamic _dyn_type = new Dynamic();
51 private Dynamic _dyn_default = new Dynamic();
52 private Dynamic _dyn_constraint = new Dynamic();
53 private Dynamic _dyn_keys = new Dynamic();
54
55 //////////////////////////////////////////////////////////
56 // Constructors
57 /*** Create a new attribute for a given <code>Relation</code>.
58 * You should use <code>Relation.createAttribute()</code>
59 */
60 public Attribute(Relation relation)
61 {
62 setRelation(relation);
63 setIdentifier(NEW_ATTRIBUTE_STR + _relation.getAttributeCount());
64 setName(getIdentifier());
65 }
66
67 protected Attribute(Relation relation, Attribute that)
68 {
69 this(relation);
70 if (that != null)
71 {
72 String id = that.getIdentifier();
73 String anotherId = id;
74 int uniquifier = 0;
75 Attribute another = null;
76 while ((another = relation.getAttribute(anotherId)) != null)
77 {
78 anotherId = id + "_" + (++uniquifier);
79 }
80 setIdentifier(anotherId);
81 setName(that.getName());
82 setDescription(that.getDescription());
83 setType(that.getType());
84 setConstraint(that.getConstraint());
85 }
86 }
87
88 /*** Default constructor needed for diagram loading. */
89 public Attribute() { }
90
91 /////////////////////////////////////////////////////////
92 // Getter/Setters
93 public AttributeType getType()
94 {
95 _dyn_type.onGet();
96 return _type;
97 }
98 public void setType(AttributeType type)
99 {
100 if (_type != type)
101 {
102 _dyn_type.onSet();
103 _type = type;
104 }
105 }
106
107 public DefaultValue getDefaultValue()
108 {
109 _dyn_default.onGet();
110 return _default;
111 }
112 public void setDefaultValue(DefaultValue value)
113 {
114 if (!_default.equals(value))
115 {
116 _dyn_default.onSet();
117 _default = value;
118 }
119 }
120
121 public void setConstraint(AttributeConstraint constraint)
122 {
123 if (_constraint != constraint)
124 {
125 _dyn_constraint.onSet();
126 _constraint = constraint;
127 if (_constraint == AttributeConstraint.NOTNULL &&
128 _default == DefaultValue.NULL)
129 {
130 setDefaultValue(DefaultValue.EMPTY);
131 }
132 }
133 }
134 public AttributeConstraint getConstraint()
135 {
136 _dyn_constraint.onGet();
137 return _constraint;
138 }
139
140 public Relation getRelation()
141 {
142 return _relation;
143 }
144 private void setRelation(Relation relation)
145 {
146 _relation = relation;
147 }
148
149 /////////////////////////////////////////////////////////
150 // Operations
151 public void addKey(KeyConstraint key)
152 {
153 if (!_keys.contains(key))
154 {
155 _dyn_keys.onSet();
156 _keys.add(key);
157 }
158 }
159 public void removeKey(KeyConstraint key)
160 {
161 _dyn_keys.onSet();
162 _keys.remove(key);
163 }
164 public Iterator getKeyIterator()
165 {
166 _dyn_keys.onGet();
167 return new ImmutableIterator(_keys.iterator());
168 }
169
170 //FIXME: cache info on first iteration so we don't have to iter every time?
171 public boolean isPrimaryKey()
172 {
173 Iterator keys = getKeyIterator();
174 boolean found = false;
175 while (keys.hasNext())
176 {
177 if (keys.next() instanceof PrimaryKey)
178 {
179 found = true;
180 break;
181 }
182 }
183 return found;
184 }
185 public boolean isUniqueKey()
186 {
187 Iterator keys = getKeyIterator();
188 boolean found = false;
189 while (keys.hasNext())
190 {
191 if (keys.next() instanceof UniqueKey)
192 {
193 found = true;
194 break;
195 }
196 }
197 return found;
198 }
199 public boolean isForeignKey()
200 {
201 Iterator keys = getKeyIterator();
202 boolean found = false;
203 while (keys.hasNext())
204 {
205 if (keys.next() instanceof ForeignKey)
206 {
207 found = true;
208 break;
209 }
210 }
211 return found;
212 }
213
214 /***
215 * Delete all keys of which this attribute is a member.
216 */
217 public void dispose()
218 {
219 Relation relation = getRelation();
220 Iterator itr = getKeyIterator();
221 while (itr.hasNext())
222 {
223 relation.deleteKey((KeyConstraint) itr.next());
224 }
225 _keys.clear();
226 }
227
228 public boolean equals(Object rhs)
229 {
230 if (rhs != null && rhs instanceof Attribute)
231 {
232 Attribute that = (Attribute)rhs;
233 if (getRelation() == that.getRelation() &&
234 that.getIdentifier().equals(getIdentifier())
235 )
236 {
237 return true;
238 }
239 }
240 return false;
241 }
242
243 public void accept(ModelElementVisitor visitor)
244 {
245 visitor.visitAttribute(this);
246 }
247
248 } /* end class Attribute */
This page was automatically generated by Maven