1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.millscript.millscript.datatypes;
22
23 import org.millscript.commons.util.IList;
24 import org.millscript.commons.util.MapIterator;
25 import org.millscript.commons.util.list.IArrayList;
26 import org.millscript.commons.xml.api.Attributes;
27 import org.millscript.commons.xml.api.Name;
28 import org.millscript.millscript.render.Renderable;
29 import org.millscript.millscript.render.Renderer;
30
31 import java.io.IOException;
32 import java.io.Serializable;
33
34 /**
35 * XmlElement is a lightweight objects that plays the role of an XML element. It
36 * is deliberately NOT compatible with the W3C DOM interface. That interface
37 * includes "back-pointers" from children to their parents -- a terrible design
38 * error that is slowly but surely being recognized as such.
39 *
40 * @see <a href="http://www.millscript.org/reference/millscript/implementation/">Implementation notes</a>
41 */
42 public final class XmlElement extends AbstractListAware implements Fragment, Renderable, Serializable {
43
44 /**
45 * This is the ID from the release 10.2.0 for future compatibility.
46 */
47 private static final long serialVersionUID = -7905050793300162929L;
48
49 /**
50 * This elements name.
51 */
52 private Name name;
53
54 /**
55 * This elements attributes.
56 */
57 private Attributes attributes;
58
59 /**
60 * This elements children.
61 */
62 private Object[] children;
63
64 /**
65 * Constructs a new XML element with the specified name, attributes and
66 * children.
67 *
68 * @param n the XML elements name
69 * @param a the XML elements attributes
70 * @param c the XML elements children
71 */
72 public XmlElement( final Name n, final Attributes a, final Object[] c ) {
73 this.name = n;
74 this.attributes = a;
75 this.children = c;
76 }
77
78 /**
79 * @see org.millscript.millscript.datatypes.ListAware#asList()
80 */
81 public IList asList() {
82 return new IArrayList< Object >( this.children, true );
83 }
84
85 /**
86 * @see org.millscript.millscript.datatypes.ListAware#asOriginal(org.millscript.commons.util.IList)
87 */
88 public Object asOriginal( final IList< ? > x ) {
89 return new XmlElement( name, attributes, x.toArray() );
90 }
91
92 /**
93 * Returns the child at the specified position in this XML element.
94 *
95 * @param n the position of the required child
96 * @return the child at the specified position
97 */
98 public Object get( final int n ) {
99 return children[ n ];
100 }
101
102 /**
103 * Returns a map containing all the elements attribute names and values.
104 *
105 * @return a Map with this elements attribute name-value pairs
106 */
107 public Attributes getAttributes() {
108 return this.attributes;
109 }
110
111 /**
112 * Returns an array of all this elements children.
113 *
114 * @return an array of this elements children
115 */
116 public Object[] getChildren() {
117 return children;
118 }
119
120 /**
121 * Returns this elements Name.
122 *
123 * @return this elements <code>Name</code>
124 */
125 public Name getName() {
126 return this.name;
127 }
128
129 /**
130 * Outputs an indent for the specified level. e.g. prints a required number
131 * of spaces.
132 *
133 * @param level the level of indentation
134 */
135 static void indent( final int level ) {
136 for ( int i = 0; i < level; i++ ) {
137 System.out.print( "| " );
138 }
139 }
140
141 /**
142 * @see org.millscript.millscript.render.Renderable#render(Renderer)
143 */
144 public void render( final Renderer r ) throws IOException {
145 r.renderXMLElement( this );
146 }
147
148 /**
149 * @see org.millscript.millscript.datatypes.ListAware#sameAs(java.lang.Object)
150 */
151 public boolean sameAs( final Object x ) {
152 return x instanceof XmlElement;
153 }
154
155 /**
156 * Returns the number of children this XML element has.
157 *
158 * @return an int holding the number of children
159 */
160 public int size() {
161 return children.length;
162 }
163
164 /**
165 * Returns the name of the XML element.
166 *
167 * @return a String containing the XML element name
168 */
169 public String tagName() {
170
171 return name.getQName();
172 }
173
174 /**
175 * Returns the name of this XML element as an Atom.
176 *
177 * @return an Atom for this XML elements name
178 */
179 public Atom tagWord() {
180
181 return Atom.make( name.getQName() );
182 }
183
184 /**
185 * @see java.lang.Object#toString()
186 */
187 @Override
188 public String toString() {
189 Object[] kids = this.children;
190 final int nkids = kids.length;
191
192 final StringBuffer sofar = new StringBuffer( "<" );
193 sofar.append( this.name.getQName() );
194 final MapIterator< Name, String > it = this.attributes.iterator( true );
195 while ( it.hasNext() ) {
196 sofar.append( " " );
197 sofar.append( it.nextKey().getQName() );
198 if ( it.currentValue() != null ) {
199 sofar.append( "=\"" );
200 sofar.append( it.currentValue() );
201 sofar.append( "\"" );
202 }
203 }
204
205 if ( nkids == 0 ) {
206 sofar.append( "/>" );
207 } else {
208 sofar.append( ">" );
209 for ( int i = 0; i < nkids; i++ ) {
210 if ( kids[ i ] != null ) {
211 sofar.append( kids[ i ] );
212 }
213 }
214 sofar.append( "</" );
215 sofar.append( this.name.getQName() );
216 sofar.append( ">" );
217 }
218 return sofar.toString();
219 }
220
221 }