1 package org.andromda.core.dbmapping;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.text.MessageFormat;
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.Map;
9 import java.util.HashMap;
10 import java.util.HashSet;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Set;
14
15 import org.andromda.core.common.DbMappingTable;
16 import org.andromda.core.common.RepositoryReadException;
17
18 import org.apache.commons.digester.Digester;
19
20
21 /***
22 * <p>Implements DbMappingTable by using a Jakarta Commons Digester to
23 * read the <code>TypeMappings.xml</code> file.</p>
24 *
25 * @author Stefan Kuehnel
26 * @author Matthias Bohlen
27 * @author <a href="http://www.amowers.com">Anthony Mowers</a>
28 *
29 * @see <a href="http://jakarta.apache.org/commons/digester/">Jakarta Commons Digester</a>
30 */
31 public class DigesterDbMappingTable
32 implements DbMappingTable
33 {
34 private Map map = Collections.EMPTY_MAP;
35 private Digester digester = new Digester();
36
37 public DigesterDbMappingTable()
38 {
39 digester.addObjectCreate("mappings", Mappings.class);
40 digester.addSetProperties("mappings", "database", "database");
41 digester.addObjectCreate("mappings/mapping", Mapping.class);
42 digester.addCallMethod("mappings/mapping/type", "addJavaType", 0);
43 digester.addObjectCreate("mappings/mapping/jdbc-type", JdbcType.class);
44 digester.addSetProperties("mappings/mapping/jdbc-type", "name", "name");
45 digester.addSetNext("mappings/mapping/jdbc-type", "setJdbcType");
46 digester.addObjectCreate("mappings/mapping/sql-type", SqlType.class);
47 digester.addSetProperties("mappings/mapping/sql-type",
48 new String[] { "pattern", "default-length" },
49 new String[] { "pattern", "defaultLength" });
50 digester.addSetNext("mappings/mapping/sql-type", "setSqlType");
51 digester.addSetNext("mappings/mapping", "addMapping");
52 }
53
54 /***
55 * @see org.andromda.core.common.DbMappingTable#read(File)
56 */
57 public void read(File mappingsFile)
58 throws RepositoryReadException, IOException
59 {
60 try {
61
62
63
64 Mappings mappings = (Mappings)digester.parse(mappingsFile);
65 initialize(mappings);
66 } catch (Exception ex) {
67 throw new RepositoryReadException(
68 "Error in TypeMappings file: " + mappingsFile, ex);
69 }
70 }
71
72 /***
73 * @see org.andromda.core.common.DbMappingTable#getJDBCType(String)
74 */
75 public String getJDBCType(String javaType)
76 {
77 Mapping m = (Mapping) map.get(javaType);
78 if (null == m)
79 {
80 return "** MISSING JDBC type mapping for " + javaType;
81 }
82
83 return m.getJdbcType().getName();
84 }
85
86 /***
87 * @see org.andromda.core.common.DbMappingTable#getSQLType(String, String)
88 */
89 public String getSQLType(String javaType, String desiredFieldLength)
90 {
91 Mapping m = (Mapping) map.get(javaType);
92 if (null == m)
93 {
94 return "** MISSING SQL type mapping for " + javaType;
95 }
96 SqlType sqlType = m.getSqlType();
97
98 String pattern = sqlType.getPattern();
99
100 String fieldLength =
101 (null == desiredFieldLength)
102 || ("".equals(desiredFieldLength))
103 ? sqlType.getDefaultLength()
104 : desiredFieldLength;
105 Object[] arguments = { fieldLength };
106
107 return MessageFormat.format(pattern, arguments);
108 }
109
110 private void initialize(Mappings mappings)
111 {
112 map = new HashMap();
113
114 for (Iterator i = mappings.getMappings().iterator(); i.hasNext(); )
115 {
116 Mapping mapping = (Mapping)i.next();
117 for (Iterator j = mapping.getJavaTypes().iterator(); j.hasNext(); )
118 {
119 String type = (String)j.next();
120 if (map.containsKey(type)) {
121 System.out.println("WARNING: Duplicate mappings for Java type '"+type+"'. Using new value.");
122 }
123 map.put(type, mapping);
124 }
125 }
126 }
127
128 public static class Mappings {
129 private List mappings = new ArrayList();
130 private String database;
131
132 /***
133 * Gets the list of mappings.
134 *
135 * @return a List with all mappings
136 */
137 public List getMappings() {
138 return mappings;
139 }
140
141 /***
142 * Adds the given mapping to our list.
143 *
144 * @param m the new mapping to add
145 */
146 public void addMapping(Mapping m) {
147 mappings.add(m);
148 }
149
150 /***
151 * Gets the name of the database this mappings are for.
152 *
153 * @return a String with the name of the database this mappings are for
154 */
155 public String getDatabase() {
156 return database;
157 }
158
159 /***
160 * Sets the name of the database this mappings are for.
161 *
162 * @param database String with the name of the database this mappings are for
163 */
164 public void setDatabase(String database) {
165 this.database = database;
166 }
167 }
168
169 public static class Mapping {
170 private Set javaTypes = new HashSet();
171 private JdbcType jdbcType;
172 private SqlType sqlType;
173
174 /***
175 * Gets the Java types this mapping applies to.
176 *
177 * @return a Set with the Java types this mapping applies to
178 */
179 public Set getJavaTypes() {
180 return javaTypes;
181 }
182
183 /***
184 * Adds a Java type this mapping applies to.
185 *
186 * @param javaType a String with a Java type this mapping applies to
187 */
188 public void addJavaType(String javaType) {
189 javaTypes.add(javaType);
190 }
191
192 /***
193 * Gets the JDBC type the Java types map to.
194 *
195 * @return the JdbcType the Java types map to
196 */
197 public JdbcType getJdbcType() {
198 return jdbcType;
199 }
200
201 /***
202 * Sets the JDBC type the Java types map to.
203 *
204 * @param jdbcType the JdbcType the Java types map to
205 */
206 public void setJdbcType(JdbcType jdbcType) {
207 this.jdbcType = jdbcType;
208 }
209
210 /***
211 * Gets the SQL type the Java types map to.
212 *
213 * @return the SqlType the Java types map to
214 */
215 public SqlType getSqlType() {
216 return sqlType;
217 }
218
219 /***
220 * Sets the SQL type the Java types map to.
221 *
222 * @param sqlType the SqlType the Java types map to
223 */
224 public void setSqlType(SqlType sqlType) {
225 this.sqlType = sqlType;
226 }
227
228 }
229
230 public static class JdbcType {
231 private String name;
232
233 /***
234 * Gets the name of the JDBC type.
235 *
236 * @return a String with the name of the JDBC type
237 */
238 public String getName() {
239 return name;
240 }
241
242 /***
243 * Sets the name of the JDBC type.
244 *
245 * @param name a String with the name of the JDBC type
246 */
247 public void setName(String name) {
248 this.name = name;
249 }
250 }
251
252 public static class SqlType {
253 private String pattern;
254 private String defaultLength;
255
256 /***
257 * Gets the pattern to build the SQL type.
258 *
259 * @return a String with the pattern to build the SQL type
260 */
261 public String getPattern() {
262 return pattern;
263 }
264
265 /***
266 * Sets the pattern to build the SQL type.
267 *
268 * @param pattern a String with the pattern to build the SQL type
269 */
270 public void setPattern(String pattern) {
271 this.pattern = pattern;
272 }
273
274 /***
275 * Gets the default length for the SQL type.
276 *
277 * @return a String with the default length for the SQL type
278 */
279 public String getDefaultLength() {
280 return defaultLength;
281 }
282
283 /***
284 * Sets the default length for the SQL type.
285 *
286 * @param defaultLength a String with the default length for the SQL type
287 */
288 public void setDefaultLength(String defaultLength) {
289 this.defaultLength = defaultLength;
290 }
291 }
292
293 }