View Javadoc

1   /*
2    * Copyright 2004-2008 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.uruma.rcp.configuration.writer;
17  
18  import java.io.IOException;
19  import java.io.Writer;
20  import java.lang.reflect.Field;
21  import java.util.List;
22  
23  import org.seasar.framework.beans.BeanDesc;
24  import org.seasar.framework.beans.PropertyDesc;
25  import org.seasar.framework.beans.factory.BeanDescFactory;
26  import org.seasar.framework.exception.IORuntimeException;
27  import org.seasar.framework.util.FieldUtil;
28  import org.seasar.framework.util.StringUtil;
29  import org.seasar.uruma.annotation.ConfigurationAttribute;
30  import org.seasar.uruma.core.UrumaConstants;
31  import org.seasar.uruma.rcp.configuration.ConfigurationElement;
32  import org.seasar.uruma.rcp.configuration.ConfigurationWriter;
33  import org.seasar.uruma.rcp.configuration.elements.AbstractConfigurationElementContainer;
34  import org.seasar.uruma.util.AnnotationUtil;
35  
36  /**
37   * 汎用的な {@link ConfigurationWriter} です。<br />
38   * 
39   * @author y-komori
40   */
41  public class GenericConfigurationWriter implements ConfigurationWriter,
42          UrumaConstants {
43  
44      private Class<? extends ConfigurationElement> supportType;
45  
46      private String elementName;
47  
48      private boolean startTagOnly;
49  
50      private static final String ELEMENT_NAME = "ELEMENT_NAME";
51  
52      /**
53       * {@link GenericConfigurationWriter} を構築します。<br />
54       * 
55       * @param supportType
56       *            対応する {@link ConfigurationElement} の型
57       */
58      public GenericConfigurationWriter(
59              final Class<? extends ConfigurationElement> supportType) {
60          this.supportType = supportType;
61          this.startTagOnly = AbstractConfigurationElementContainer.class
62                  .isAssignableFrom(supportType) ? false : true;
63          BeanDesc desc = BeanDescFactory.getBeanDesc(supportType);
64          Field field = desc.getField(ELEMENT_NAME);
65          this.elementName = FieldUtil.getString(field);
66      }
67  
68      /**
69       * {@link GenericConfigurationWriter} を構築します。<br />
70       * 
71       * @param supportType
72       *            対応する {@link ConfigurationElement} の型
73       * @param elementName
74       *            要素名
75       * @param startTagOnly
76       *            <code>true</code> の場合、開始タグのみを出力する
77       */
78      public GenericConfigurationWriter(
79              final Class<? extends ConfigurationElement> supportType,
80              final String elementName, final boolean startTagOnly) {
81          this.supportType = supportType;
82          this.elementName = elementName;
83          this.startTagOnly = startTagOnly;
84      }
85  
86      /*
87       * @see org.seasar.uruma.rcp.configuration.ConfigurationWriter#getSupportType()
88       */
89      public Class<? extends ConfigurationElement> getSupportType() {
90          return this.supportType;
91      }
92  
93      /*
94       * @see org.seasar.uruma.rcp.configuration.ConfigurationWriter#writeStartTag(org.seasar.uruma.rcp.configuration.ConfigurationElement,
95       *      java.io.Writer)
96       */
97      public void writeStartTag(final ConfigurationElement element,
98              final Writer writer) {
99          writeStartTag(element, writer, 0);
100     }
101 
102     /*
103      * @see org.seasar.uruma.rcp.configuration.ConfigurationWriter#writeStartTag(org.seasar.uruma.rcp.configuration.ConfigurationElement,
104      *      java.io.Writer, int)
105      */
106     public void writeStartTag(final ConfigurationElement element,
107             final Writer writer, final int level) {
108         try {
109             writer.write(createIndent(level));
110             writer.write("<");
111             writer.write(elementName);
112             writer.write(WHITE_SPACE);
113 
114             List<PropertyDesc> pdLists = AnnotationUtil
115                     .getAnnotatedPropertyDescs(supportType,
116                             ConfigurationAttribute.class);
117             for (PropertyDesc pd : pdLists) {
118                 Field field = pd.getField();
119                 ConfigurationAttribute anno = field
120                         .getAnnotation(ConfigurationAttribute.class);
121                 String name = anno.name();
122                 if (StringUtil.isEmpty(name)) {
123                     name = field.getName();
124                 }
125 
126                 Object value = pd.getValue(element);
127 
128                 if (value != null) {
129                     writer.write(name);
130                     writer.write("=\"");
131                     escapeChars(value.toString(), writer);
132                     writer.write("\" ");
133                 } else if (anno.required()) {
134                     writer.write(name);
135                     writer.write("=\"\" ");
136                 }
137             }
138 
139             if (startTagOnly) {
140                 writer.write("/>\n");
141             } else {
142                 writer.write(">\n");
143             }
144         } catch (IOException ex) {
145             throw new IORuntimeException(ex);
146         }
147     }
148 
149     /*
150      * @see org.seasar.uruma.rcp.configuration.ConfigurationWriter#writeEndTag(org.seasar.uruma.rcp.configuration.ConfigurationElement,
151      *      java.io.Writer)
152      */
153     public void writeEndTag(final ConfigurationElement element,
154             final Writer writer) {
155         writeEndTag(element, writer, 0);
156     }
157 
158     /*
159      * @see org.seasar.uruma.rcp.configuration.ConfigurationWriter#writeEndTag(org.seasar.uruma.rcp.configuration.ConfigurationElement,
160      *      java.io.Writer, int)
161      */
162     public void writeEndTag(final ConfigurationElement element,
163             final Writer writer, final int level) {
164         if (!startTagOnly) {
165             try {
166                 writer.write(createIndent(level));
167                 writer.write("</" + elementName + ">\n");
168             } catch (IOException ex) {
169                 throw new IORuntimeException(ex);
170             }
171         }
172     }
173 
174     protected void escapeChars(final String str, final Writer writer)
175             throws IOException {
176         for (int i = 0; i < str.length(); i++) {
177             int chr = str.charAt(i);
178 
179             switch (chr) {
180             case '&':
181                 writer.write("&amp;");
182                 break;
183 
184             case '<':
185                 writer.write("&lt;");
186                 break;
187 
188             case '>':
189                 writer.write("&gt;");
190                 break;
191 
192             case '"':
193                 writer.write("&quot;");
194                 break;
195 
196             default:
197                 writer.write(chr);
198             }
199         }
200     }
201 
202     protected String createIndent(final int level) {
203         if (level > 0) {
204             StringBuilder builder = new StringBuilder(level);
205             for (int i = 0; i < level; i++) {
206                 builder.append(WHITE_SPACE);
207             }
208             return builder.toString();
209         } else {
210             return NULL_STRING;
211         }
212     }
213 }