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.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
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
211 }
212
213 /**
214 * @see org.millscript.millscript.render.Renderer#renderDocumentHeader()
215 */
216 public void renderDocumentHeader() {
217
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 }