1
2
3
4
5
6
7
8 package com.bbn.swede.core.dom;
9
10 import org.eclipse.jface.text.IRegion;
11
12 import com.bbn.swede.core.dom.rdf.About;
13 import com.bbn.swede.core.dom.rdf.ID;
14 import com.bbn.swede.core.dom.rdf.NodeID;
15 import com.bbn.swede.core.dom.rdf.ParseType;
16 import com.bbn.swede.core.dom.rdf.Resource;
17
18 /***
19 * Common implementation for nodes representing XML attributes.
20 * @author jlerner
21 */
22 public abstract class AttributeNode extends OASTNode
23 {
24 /***
25 * Creates an attribute node.
26 * @param sValue The value of the attribute.
27 */
28 public AttributeNode(String sValue)
29 {
30 _sValue = sValue;
31 initRegions();
32 }
33
34 /***
35 * Initializes the simple partitioning of the attribute node.
36 */
37 protected void initRegions()
38 {
39 String sQName = getQName();
40 String sValue = getValue();
41
42
43 if (sQName == null || sValue == null)
44 {
45 return;
46 }
47
48 _iLength = sQName.length() + sValue.length() + 3;
49 setValueRegion(getOffset() + sQName.length() + 1);
50 }
51
52
53
54
55
56 protected final int[] allowedChildren()
57 {
58 return null;
59 }
60
61 /***
62 * The value of this attribute.
63 */
64 protected String _sValue;
65
66 /***
67 * Retrieves the attribute value.
68 * @return The attribute value.
69 */
70 public String getValue()
71 {
72 return _sValue;
73 }
74
75 /***
76 * Sets the attribute's value.
77 * @param sValue The new attribute value.
78 * @throws OASTException if this node is attached to a read-only OAST
79 */
80 public void setValue(String sValue) throws OASTException
81 {
82 if (getOWLAbstractSyntaxTree() != null)
83 {
84
85 OASTNode parent = getParent();
86 AttributeNode attNew = AttributeNode.create(getQName(), sValue);
87 attNew.accept(new NodeDisplacementVisitor(0, getOffset()));
88 parent.replace(this, attNew);
89 }
90 else
91 {
92
93 int iDisplacement = sValue.length() - _sValue.length();
94 getRoot().accept(new NodeDisplacementVisitor(_aregions[1].getOffset(), iDisplacement));
95 _sValue = sValue;
96 }
97 }
98
99
100
101
102
103 public String toString()
104 {
105 return getQName() + "=\"" + getValue() + "\"";
106 }
107
108
109
110
111
112 public String generateNodeText()
113 {
114 StringBuffer sb = new StringBuffer(getLength());
115 for (int i = 0; i < getLength(); i++)
116 {
117 sb.append(" ");
118 }
119 String s = getQName();
120 sb.replace(0, s.length(), s);
121 sb.replace(_aregions[1].getOffset() - getOffset() - 1,
122 _aregions[1].getOffset() - getOffset() + _sValue.length() + 2, "=\"" + _sValue + "\"");
123 return sb.toString();
124 }
125
126 private IRegion[] _aregions = new IRegion[2];
127
128
129
130
131 public IRegion[] simplePartitioning()
132 {
133 return _aregions;
134 }
135
136 /***
137 * <p>Sets the portion of the attribute node region that contains the value.
138 * Only an offset for the beginning of the value region needs to be provided,
139 * as it is assumed to end at the same offset as the attribute node itself.</p>
140 *
141 * <p>This method also implicitly sets the attribute name region to start at
142 * the attribute node's starting offset and end right before the value region.</p>
143 * @param offset The starting offset of the value region.
144 */
145 /*package*/ void setValueRegion(int offset)/package-summary/html">class="comment">package*/ void setValueRegion(int offset)/package-summary.html"> void setValueRegion(int offset)
146 {
147 _aregions[0] = new DisplaceableRegion(getOffset(), offset - getOffset(), true);
148 _aregions[1] =
149 new DisplaceableRegion(offset, getLength() - _aregions[0].getLength(), true);
150 }
151
152
153
154
155
156 public boolean displace(int offset, int length)
157 {
158 if (!super.displace(offset, length))
159 {
160 return false;
161 }
162
163 ((DisplaceableRegion) _aregions[0]).displace(offset, length);
164 ((DisplaceableRegion) _aregions[1]).displace(offset, length);
165
166 return true;
167 }
168
169
170
171
172
173 protected OASTNode duplicateType()
174 {
175 return AttributeNode.create(getQName(), getValue());
176 }
177
178
179
180
181
182 public Object clone()
183 {
184 AttributeNode newAtt = (AttributeNode)super.clone();
185 newAtt._aregions = new IRegion[_aregions.length];
186 for (int i = 0; i < _aregions.length; i++)
187 {
188 DisplaceableRegion dr = (DisplaceableRegion)_aregions[i];
189 newAtt._aregions[i] = new DisplaceableRegion(dr.getOffset(), dr.getLength(), dr.moveIfEqual());
190 }
191 newAtt._sValue = _sValue;
192 return newAtt;
193 }
194
195 /***
196 * Factory method for creating attribute nodes. Returns a node of the
197 * specified type with no parent and no children.
198 * @param iNodeType A node type constant specifying an attribute type. This
199 * includes RDF_ABOUT, RDF_ID, RDF_RESOURCE, RDF_NODEID,
200 * RDF_PARSETYPE, and BASE. This method cannot create generic
201 * attributes or XML namespace declarations.
202 * @see #create(String, String)
203 * @param sValue Value of the attribute
204 * @return A node of the specified type, or <code>null</code> if an unknown
205 * or non-attribute node type is specified.
206 */
207 private static AttributeNode create(int iNodeType, String sValue)
208 {
209 switch (iNodeType)
210 {
211 case RDF_ABOUT :
212 return new About(sValue);
213 case RDF_ID :
214 return new ID(sValue);
215 case RDF_RESOURCE :
216 return new Resource(sValue);
217 case RDF_NODEID :
218 return new NodeID(sValue);
219 case RDF_PARSETYPE :
220 return new ParseType(sValue);
221 case BASE :
222 return new Base(sValue);
223 default :
224 return null;
225 }
226 }
227
228 /***
229 * Factory method for creating attribute nodes. If the specified QName is
230 * recognized as an attribute from the RDF, RDFS, or OWL language, a custom
231 * node of the appropriate type will be created and returned. Otherwise,
232 * a generic attribute is created. The new attribute node will have no
233 * parent and no children.
234 * @param sQName The qualified name for the attribute node
235 * @param sValue The value of the attribute
236 * @return An attribute node of the specified type, or a generic attribute
237 * if an unknown or non-attribute node type is specified.
238 */
239 public static AttributeNode create(String sQName, String sValue)
240 {
241 if (sQName.startsWith("xmlns"))
242 {
243 Namespace ns = new Namespace(sQName, sValue);
244 return ns;
245 }
246 int iPos = sQName.indexOf(':');
247 String sNS = (iPos >= 0 ? sQName.substring(0, iPos) : "");
248 String sName = (iPos >= 0 ? sQName.substring(iPos + 1) : "");
249 int iNodeType = 0;
250 int iBase = -1;
251 String[] asTags = null;
252 if (sNS.equals("rdf"))
253 {
254 iBase = RDF;
255 asTags = AS_RDF;
256 }
257 else if (sNS.equals("rdfs"))
258 {
259 iBase = RDFS;
260 asTags = AS_RDFS;
261 }
262 else if (sNS.equals("owl"))
263 {
264 iBase = OWL;
265 asTags = AS_OWL;
266 }
267 else if (sQName.equals("xml:base"))
268 {
269 return create(BASE, sValue);
270 }
271 else
272 {
273 return new GenericAttribute(sQName, sValue);
274 }
275 int i;
276 for (i = 0; i < asTags.length; i++)
277 {
278 if (asTags[i].equals(sName))
279 {
280 break;
281 }
282 }
283 if (i >= asTags.length)
284 {
285 return new GenericAttribute(sQName, sValue);
286 }
287 iNodeType = iBase + i;
288 AttributeNode an = create(iNodeType, sValue);
289 if (an == null)
290 {
291 return new GenericAttribute(sQName, sValue);
292 }
293 return an;
294 }
295 }