1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.millscript.millscript.loaders;
23
24 import org.millscript.commons.util.map.EHashMap;
25 import org.millscript.commons.xml.api.Name;
26 import org.millscript.commons.xml.api.token.EndTagToken;
27 import org.millscript.commons.xml.api.token.StartTagToken;
28 import org.millscript.commons.xml.tokenizer.UnprefixedName;
29 import org.millscript.millscript.alert.Alerts;
30 import org.millscript.millscript.expr.ConstantExpr;
31 import org.millscript.millscript.expr.Expr;
32 import org.millscript.millscript.expr.LambdaExpr;
33 import org.millscript.millscript.expr.NameExpr;
34
35 /**
36 * This class implements the MillScript XML template loader. The specified file
37 * is loaded as an XML file, but the elements <code>arg</code> and
38 * <code>item</code> in the
39 * <code>http://www.millscript.org/namespace/template</code> namespace and
40 * attribute values starting with <code>?</code> take on special meaning.
41 */
42 public final class XMLTemplateLoader extends BasicTemplateLoader {
43
44 /**
45 * The XML namespace for MillScripts XML templates.
46 */
47 public static final String XML_TEMPLATE_NAMESPACE = "http://www.millscript.org/namespace/template";
48
49 /**
50 * A mapping from special element names to their handler.
51 */
52 private final EHashMap< Name, SpecialTemplateName > specialTemplateElements = new EHashMap< Name, SpecialTemplateName >();
53
54 /**
55 * Constructs a new XML template loader which supports XML namespaces, with
56 * the default set of special elements.
57 */
58 public XMLTemplateLoader() {
59 super( true );
60 specialTemplateElements.insert(
61 new UnprefixedName(
62 XML_TEMPLATE_NAMESPACE,
63 "item"
64 ),
65 new ItemName( this )
66 );
67 specialTemplateElements.insert(
68 new UnprefixedName(
69 XML_TEMPLATE_NAMESPACE,
70 "arg"
71 ),
72 new ArgName( this )
73 );
74 specialTemplateElements.insert(
75 new UnprefixedName(
76 XML_TEMPLATE_NAMESPACE,
77 "arg1"
78 ),
79 new ShortcutArgName( this, 1 )
80 );
81 specialTemplateElements.insert(
82 new UnprefixedName(
83 XML_TEMPLATE_NAMESPACE,
84 "arg2"
85 ),
86 new ShortcutArgName( this, 2 )
87 );
88 specialTemplateElements.insert(
89 new UnprefixedName(
90 XML_TEMPLATE_NAMESPACE,
91 "arg3"
92 ),
93 new ShortcutArgName( this, 3 )
94 );
95 specialTemplateElements.insert(
96 new UnprefixedName(
97 XML_TEMPLATE_NAMESPACE,
98 "arg4"
99 ),
100 new ShortcutArgName( this, 4 )
101 );
102 specialTemplateElements.insert(
103 new UnprefixedName(
104 XML_TEMPLATE_NAMESPACE,
105 "arg5"
106 ),
107 new ShortcutArgName( this, 5 )
108 );
109 specialTemplateElements.insert(
110 new UnprefixedName(
111 XML_TEMPLATE_NAMESPACE,
112 "arg6"
113 ),
114 new ShortcutArgName( this, 6 )
115 );
116 specialTemplateElements.insert(
117 new UnprefixedName(
118 XML_TEMPLATE_NAMESPACE,
119 "arg7"
120 ),
121 new ShortcutArgName( this, 7 )
122 );
123 specialTemplateElements.insert(
124 new UnprefixedName(
125 XML_TEMPLATE_NAMESPACE,
126 "arg8"
127 ),
128 new ShortcutArgName( this, 8 )
129 );
130 specialTemplateElements.insert(
131 new UnprefixedName(
132 XML_TEMPLATE_NAMESPACE,
133 "arg9"
134 ),
135 new ShortcutArgName( this, 9 )
136 );
137 }
138
139 /**
140 * @see org.millscript.millscript.loaders.BasicTemplateLoader#compAttributeValue(java.lang.String)
141 */
142 @Override
143 public Expr compAttributeValue( final String value ) {
144 if ( value.length() > 0 && value.charAt( 0 ) == '?' ) {
145
146 return compSpecialString( value.substring( 1, value.length() ) );
147 } else {
148 return new ConstantExpr( value );
149 }
150 }
151
152 /**
153 * @see org.millscript.millscript.loaders.BasicTemplateLoader#compileEndTag(org.millscript.commons.xml.api.token.EndTagToken)
154 */
155 @Override
156 public void compileEndTag( final EndTagToken token ) {
157 if ( XML_TEMPLATE_NAMESPACE.equals( token.getName().getNamespace() ) ) {
158
159
160 final SpecialTemplateName specialName = this.specialTemplateElements.get( token.getName() );
161 if ( specialName == null ) {
162
163 throw(
164 Alerts.template(
165 "Unrecognized XML template element (spelling error?)",
166 "XML templates support 'item' and 'arg' tags for custom content"
167 ).decorate( token ).mishap()
168 );
169 } else {
170 specialName.handle();
171
172 this.tokenVisitor = this.tokenVisitor.parentTokenVisitor;
173 }
174 } else {
175
176
177 super.compileEndTag( token );
178 }
179 }
180
181 /**
182 * @see org.millscript.millscript.loaders.BasicTemplateLoader#compileStartTag(org.millscript.commons.xml.api.token.StartTagToken)
183 */
184 @Override
185 public void compileStartTag( final StartTagToken token ) {
186 if ( XML_TEMPLATE_NAMESPACE.equals( token.getName().getNamespace() ) ) {
187
188
189 if ( this.specialTemplateElements.containsKey( token.getName() ) ) {
190
191
192 this.tokenVisitor = new BasicTemplateLoaderElementTokenVisitor( this, this.tokenVisitor, token );
193 } else {
194
195 throw(
196 Alerts.template(
197 "Unrecognized XML template element (spelling error?)",
198 "XML templates support 'item' and 'arg' tags for custom content"
199 ).decorate( token ).mishap()
200 );
201 }
202 } else {
203 super.compileStartTag( token );
204 }
205 }
206
207 /**
208 * @see org.millscript.millscript.loaders.BasicTemplateLoader#makeLambda(java.lang.String, org.millscript.millscript.expr.Expr)
209 */
210 @Override
211 public Expr makeLambda( final String theName, final Expr body ) {
212 return (
213 new LambdaExpr(
214 theName,
215 null,
216 new NameExpr( "arg" ),
217 body
218 )
219 );
220 }
221
222 }