View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2001-2004 Open World Ltd
4   // Copyright (C) 2005 Kevin Rogers
5   //
6   // This file is part of MillScript.
7   //
8   // MillScript is free software; you can redistribute it and/or modify it under
9   // the terms of the GNU General Public License as published by the Free
10  // Software Foundation; either version 2 of the License, or (at your option)
11  // any later version.
12  //
13  // MillScript is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  // more details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA  02111-1307  USA
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             // Compile everything but the leading '?'
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             // The element is in the template namespace, so check it's local
159             // name
160             final SpecialTemplateName specialName = this.specialTemplateElements.get( token.getName() );
161             if ( specialName == null ) {
162                 // Unsupported template element
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                 // End this element
172                 this.tokenVisitor = this.tokenVisitor.parentTokenVisitor;
173             }
174         } else {
175             // The element isn't in the template namespace, so it's just an
176             // ordinary element
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             // The element is in the template namespace, so check it's local
188             // name
189             if ( this.specialTemplateElements.containsKey( token.getName() ) ) {
190                 // ok, we allow these special elements through, just start another
191                 // normal element
192                 this.tokenVisitor = new BasicTemplateLoaderElementTokenVisitor( this, this.tokenVisitor, token );
193             } else {
194                 // Unsupported template element
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 }