View Javadoc

1   /*
2    * $Id: AttributeNode.java,v 1.20 2005/06/02 19:43:19 jlerner Exp $
3    *
4    * Copyright (c) 1999-2004, BBN Technologies, LLC.
5    * All rights reserved.
6    * http://www.daml.org/legal/opensource/bbn_license.html
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        //ensure that null QNames or values coming back for not-fully-constructed 
42        //generics don't break anything
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      *  (non-Javadoc)
54      * @see com.bbn.swede.core.dom.OASTNode#allowedChildren()
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           //Swap in a new attribute so an OAST event gets created and dispatched
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           //Nobody's listening - change value and length directly
93           int iDisplacement = sValue.length() - _sValue.length();
94           getRoot().accept(new NodeDisplacementVisitor(_aregions[1].getOffset(), iDisplacement));
95           _sValue = sValue;
96        }
97     }
98  
99     /*
100     *  (non-Javadoc)
101     * @see java.lang.Object#toString()
102     */
103    public String toString()
104    {
105       return getQName() + "=\"" + getValue() + "\"";
106    }
107 
108    /*
109     *  (non-Javadoc)
110     * @see com.bbn.swede.core.dom.OASTNode#generateNodeText()
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     *  (non-Javadoc)
129     * @see com.bbn.swede.core.dom.OASTNode#simplePartitioning()
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">/*package*/ void setValueRegion(int offset)/package-summary.html">class="comment">package*/ 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     *  (non-Javadoc)
154     * @see com.bbn.swede.core.dom.OASTNode#displace(int, int)
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     *  (non-Javadoc)
171     * @see com.bbn.swede.core.dom.OASTNode#duplicateType()
172     */
173    protected OASTNode duplicateType()
174    {
175       return AttributeNode.create(getQName(), getValue());
176    }
177    
178    /*
179     *  (non-Javadoc)
180     * @see java.lang.Object#clone()
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 }