1 package net.kwfgrid.gwui.servlets;
2
3 import java.util.*;
4
5 /***
6 * Created by IntelliJ IDEA.
7 * User: Ondrej
8 * Date: 11.8.2006
9 * Time: 9:19:59
10 * To change this template use File | Settings | File Templates.
11 */
12 public class XmlTag
13 {
14 private String name;
15 private String value;
16 private Set subTags;
17 private Map params;
18 private Map nameSpaces;
19
20 private int strstr( String where, String what )
21 {
22 int retv = -1;
23 int ind;
24 for( int i = 0; i < what.length(); i ++ )
25 {
26 ind = where.indexOf( what.charAt( i ) );
27 if( ( ( retv < 0 ) || ( retv > ind ) ) && ( ind >= 0 ) )
28 retv = ind;
29 }
30
31 return retv;
32 }
33
34 public XmlTag( Map nameSpaces )
35 {
36 subTags = new HashSet();
37 this.nameSpaces = nameSpaces;
38 name = "";
39 value = "";
40 params = new HashMap();
41 }
42
43 public void setValue( String value )
44 {
45 this.value = value;
46 }
47
48 public void setName( String name )
49 {
50 this.name = name;
51 }
52
53 public void addParam( String name, String value )
54 {
55 params.put( name, value );
56 }
57
58 public String getName()
59 {
60 return name;
61 }
62
63 public String getValue()
64 {
65 return value;
66 }
67
68 public Map getParams()
69 {
70 return params;
71 }
72
73 private String extractFirstTagName( String treeString )
74 {
75 int start = treeString.charAt( 0 ) == '.' ? 1 : 0;
76 int end = strstr( treeString.substring( 1 ), "._" ) + 1;
77 if( end < 1)
78 return treeString.substring( start );
79 else
80 return treeString.substring( start, end );
81 }
82
83 private String getTreeStringTail( String treeString )
84 {
85 int headEnd = strstr( treeString.substring( 1 ), "._" );
86 if( headEnd < 0 )
87 return "";
88 else
89 return treeString.substring( headEnd + 1 );
90 }
91
92
93 /***
94 * Constructs a XmlTag subtree based on the structure of the string (see below).
95 * @param treeString a string in the prescribed form .tag.tag.tag.....tag or .tag.tag.tag...tag_param
96 * If treeString begins with tag, the XmlTag will
97 * <ul>
98 * <li> take it as its name, if it has not any name now
99 * <li> remove it and create a subtree based on the rest of the string, if it is the same
100 * as its name, if it has a name
101 * <li> create a different subtree, if it has a name and the starting tag name in treeString
102 * differs from it
103 * <li> add parameter for itself, it treeString begins with _
104 * </ul>
105 * @param value the value of either the final tag, or of the parameter (depends on whether <b>treeString</b>
106 * ends with <i>.tag</i> or <i>_param</i>)
107 * @return new XmlTag, which is a peer (has the same parent tag) as this XmlTag, or null, if treeString was
108 * consumed in the subtree of this XmlTag.
109 */
110 public XmlTag createFromString( String treeString, String value )
111 {
112 if( treeString.length() < 1 )
113 return null;
114
115 switch( treeString.charAt( 0 ) )
116 {
117 case '.':
118 String newName = extractFirstTagName( treeString );
119 String newTail = getTreeStringTail( treeString );
120
121 if( newName.length() < 1 )
122 return null;
123
124 if( getName().length() < 1 )
125 {
126 setName( newName );
127 if( ( newTail.length() ) > 0 && ( newTail.charAt( 0 ) == '_' ) )
128 return createFromString( newTail, value );
129 }
130
131 if( newName.equals( getName() ) )
132 {
133 if( newTail.length() > 0 )
134 {
135 if( newTail.startsWith( "_" ) )
136 {
137 createFromString( newTail, value );
138 return null;
139 }
140 String newNewHead = extractFirstTagName( newTail );
141 Iterator iter = subTags.iterator();
142 XmlTag tag;
143 while( iter.hasNext() )
144 {
145 tag = (XmlTag)(iter.next());
146 if( tag.getName().equals( newNewHead) )
147 {
148 tag.createFromString( newTail, value );
149 return null;
150 }
151 }
152 XmlTag newSubTag = new XmlTag( nameSpaces );
153 subTags.add( newSubTag );
154 newSubTag.createFromString( newTail, value );
155 }
156 else
157 setValue( value );
158 return null;
159 }
160 else
161 {
162 XmlTag newPeerTag = new XmlTag( nameSpaces );
163 newPeerTag.createFromString( treeString, value );
164 return newPeerTag;
165 }
166
167 case '_':
168 addParam( treeString.substring( 1 ), value );
169 return null;
170 }
171
172 return null;
173 }
174
175 public String createStringRepresentation( int indent, boolean includeNameSpaces )
176 {
177 StringBuffer retv = new StringBuffer();
178
179 for( int i = 0; i < indent; i ++ )
180 retv.append( '\t' );
181 retv.append( "<" );
182 retv.append( getName() );
183
184 if( includeNameSpaces && ( nameSpaces.size() > 0 ) )
185 {
186 Iterator iter = nameSpaces.entrySet().iterator();
187 Map.Entry entry;
188 while( iter.hasNext() )
189 {
190 entry = (Map.Entry)(iter.next());
191 retv.append( " xmlns" );
192 if( ((String)(entry.getValue())).length() > 0 )
193 retv.append(":" ).append( entry.getKey() ).append( "=\"" ).append( entry.getValue() ).append( "\"" );
194 else
195 retv.append("=\"\"" );
196 }
197 }
198
199 Iterator iter = params.entrySet().iterator();
200 Map.Entry entry;
201 while( iter.hasNext() )
202 {
203 entry = (Map.Entry)(iter.next());
204 retv.append( " " ).append( entry.getKey() ).append( "=\"" ).append( entry.getValue() ).append( "\"" );
205 }
206
207 if( ( getValue().length() < 1 ) && ( subTags.size() < 1 ) )
208 {
209 retv.append( "/>\n");
210 return retv.toString();
211 }
212 retv.append( ">\n" );
213
214 if( getValue().length() > 0 )
215 {
216 for( int i = 0; i < indent + 1; i ++ )
217 retv.append( '\t' );
218 retv.append( getValue() ).append( "\n" );
219 }
220
221 XmlTag subTag;
222 iter = subTags.iterator();
223 while( iter.hasNext() )
224 {
225 subTag = (XmlTag)iter.next();
226 retv.append( subTag.createStringRepresentation( indent + 1, false ) );
227 }
228
229 for( int i = 0; i < indent; i ++ )
230 retv.append( '\t' );
231 retv.append( "</" );
232 retv.append( getName() );
233 retv.append( ">\n" );
234
235 return retv.toString();
236 }
237 }