View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2005 Open World Ltd, Kevin Rogers
4   //
5   // This file is part of MillScript.
6   //
7   // MillScript is free software; you can redistribute it and/or modify it under
8   // the terms of the GNU General Public License as published by the Free
9   // Software Foundation; either version 2 of the License, or (at your option)
10  // any later version.
11  //
12  // MillScript is distributed in the hope that it will be useful, but WITHOUT
13  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  // more details.
16  //
17  // You should have received a copy of the GNU General Public License along with
18  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
19  // Place, Suite 330, Boston, MA  02111-1307  USA
20  ////////////////////////////////////////////////////////////////////////////////
21  package org.millscript.millscript.render;
22  
23  import org.millscript.commons.alert.Alert;
24  import org.millscript.commons.util.IList;
25  import org.millscript.commons.util.IMap;
26  import org.millscript.commons.util.ListIterator;
27  import org.millscript.commons.util.MapIterator;
28  import org.millscript.commons.util.Maplet;
29  import org.millscript.commons.vfs.VFile;
30  import org.millscript.millscript.conf.Configuration;
31  import org.millscript.millscript.datatypes.XmlElement;
32  
33  import java.io.IOException;
34  import java.nio.charset.Charset;
35  import java.util.Iterator;
36  import java.util.List;
37  import java.util.Map;
38  
39  /**
40   * 
41   */
42  public final class PropertiesRenderer extends AbstractRenderer {
43  
44      /**
45       * Properties files always use the ISO-8859-1 character encoding.
46       */
47      private static final Charset PROPERTIES_CHARSET = Charset.forName( "ISO-8859-1" );
48  
49      /**
50       * The line separator we will use.
51       */
52      private static final String LINE_SEPARATOR = System.getProperty( "line.separator" );
53  
54      /**
55       * @param conf
56       * @param file
57       */
58      public PropertiesRenderer( final Configuration conf, final VFile file ) {
59          super( conf, PROPERTIES_CHARSET, file );
60      }
61  
62      /**
63       * @see org.millscript.millscript.render.Renderer#append(char)
64       */
65      public void append( final char ch ) throws IOException {
66          switch ( ch ) {
67              case '\\':
68                  super.outputWriter.write( '\\' );
69                  super.outputWriter.write( '\\' );
70                  break;
71              case '\f':
72                  super.outputWriter.write( '\\' );
73                  super.outputWriter.write( 'f' );
74                  break;
75              case '\n':
76                  super.outputWriter.write( '\\' );
77                  super.outputWriter.write( 'n' );
78                  break;
79              case '\r':
80                  super.outputWriter.write( '\\' );
81                  super.outputWriter.write( 'r' );
82                  break;
83              case '\t':
84                  super.outputWriter.write( '\\' );
85                  super.outputWriter.write( 't' );
86                  break;
87              case '#': case '!': case '=': case ':': case ' ':
88                  super.outputWriter.write( '\\' );
89                  super.outputWriter.write( ch );
90                  break;
91              default:
92                  if ( ch < 0x20 || ch > 0x7E ) {
93                      super.outputWriter.write( '\\' );
94                      super.outputWriter.write( 'u' );
95                      final String hexEncodedChar = Integer.toHexString( ch );
96                      for ( int i = hexEncodedChar.length(); i < 4; i++ ) {
97                          super.outputWriter.write( '0' );
98                      }
99                      super.outputWriter.write( hexEncodedChar );
100                 } else {
101                     // The character is ok, so simply write out the byte sequence
102                     super.outputWriter.write( ch );
103                 }
104                 break;
105         }
106     }
107 
108     /**
109      * @see org.millscript.millscript.render.Renderer#appendEscapeFor(char)
110      */
111     public void appendEscapeFor( final char ch ) throws IOException {
112         switch ( ch ) {
113             case '\\':
114                 super.outputWriter.write( '\\' );
115                 super.outputWriter.write( '\\' );
116                 break;
117             case '\f':
118                 super.outputWriter.write( '\\' );
119                 super.outputWriter.write( 'f' );
120                 break;
121             case '\n':
122                 super.outputWriter.write( '\\' );
123                 super.outputWriter.write( 'n' );
124                 break;
125             case '\r':
126                 super.outputWriter.write( '\\' );
127                 super.outputWriter.write( 'r' );
128                 break;
129             case '\t':
130                 super.outputWriter.write( '\\' );
131                 super.outputWriter.write( 't' );
132                 break;
133             case '#': case '!': case '=': case ':': case ' ':
134                 super.outputWriter.write( '\\' );
135                 super.outputWriter.write( ch );
136                 break;
137             default:
138                 super.outputWriter.write( '\\' );
139                 super.outputWriter.write( 'u' );
140                 super.outputWriter.write( Integer.toHexString( ch ) );
141                 break;
142         }
143     }
144 
145     /**
146      * @see org.millscript.millscript.render.Renderer#appendNoEscape(char)
147      */
148     public void appendNoEscape( final char ch ) throws IOException {
149         if ( this.canEncode( ch ) ) {
150             super.outputWriter.write( ch );
151         } else {
152             throw new Alert(
153                 "Unsupport character for rendering into a properties file",
154                 "Only ISO-8859-1 characters can be written directly"
155             ).culprit( "character", new Character( ch ) ).mishap();
156         }
157     }
158 
159     /**
160      * @see org.millscript.millscript.render.Renderer#render(java.lang.Object)
161      */
162     @Override
163     public void render( final Object o ) throws IOException {
164         if ( o == null ) {
165             return;
166         } else if ( o instanceof Renderable ) {
167             ((Renderable) o).render( this );
168         } else if ( o instanceof Maplet ) {
169             Maplet< ?, ? > maplet = (Maplet) o;
170             this.renderObject( maplet.getKey() );
171             this.appendNoEscape( '=' );
172             this.renderObject( maplet.getValue() );
173             this.appendNoEscape( LINE_SEPARATOR );
174         } else if ( o instanceof IList ) {
175             ListIterator< ? > it = ((IList) o).iterator( true );
176             while ( it.hasNext() ) {
177                 this.render( it.nextValue() );
178             }
179         } else if ( o instanceof IMap ) {
180             MapIterator< ?, ? > it = ((IMap) o).iterator( true );
181             while ( it.hasNext() ) {
182                 this.renderObject( it.nextKey() );
183                 this.appendNoEscape( '=' );
184                 this.renderObject( it.currentValue() );
185                 this.appendNoEscape( LINE_SEPARATOR );
186             }
187         } else if ( o instanceof List ) {
188             Iterator< ? > it = ((List)o).iterator();
189             while ( it.hasNext() ) {
190                 this.render( it.next() );
191             }
192         } else if ( o instanceof Map.Entry ) {
193             Map.Entry< ?, ? > entry = (Map.Entry) o;
194             this.renderObject( entry.getKey() );
195             this.appendNoEscape( '=' );
196             this.renderObject( entry.getValue() );
197             this.appendNoEscape( LINE_SEPARATOR );
198         } else {
199             throw new Alert(
200                 "Unsupport type for rendering into a properties file",
201                 "Only maps and maplets are supported"
202             ).culprit( "object", o ).mishap();
203         }
204     }
205 
206     /**
207      * @see org.millscript.millscript.render.Renderer#renderDocumentFooter()
208      */
209     public void renderDocumentFooter() {
210         // There is no footer for a properties file
211     }
212 
213     /**
214      * @see org.millscript.millscript.render.Renderer#renderDocumentHeader()
215      */
216     public void renderDocumentHeader() {
217         // There is no header for a properties file
218     }
219 
220     /**
221      * @see org.millscript.millscript.render.Renderer#renderObject(java.lang.Object)
222      */
223     public void renderObject( final Object o ) throws IOException {
224         this.append( o.toString() );
225     }
226 
227     /**
228      * @see org.millscript.millscript.render.Renderer#renderXMLElement(org.millscript.millscript.datatypes.XmlElement)
229      */
230     public void renderXMLElement( final XmlElement e ) throws IOException {
231         this.append( e.toString() );
232     }
233 
234 }