1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.tiles.test.db;
23
24 import java.sql.ResultSet;
25 import java.sql.SQLException;
26 import java.util.List;
27 import java.util.Locale;
28 import java.util.Map;
29
30 import org.apache.tiles.Attribute;
31 import org.apache.tiles.Definition;
32 import org.apache.tiles.definition.dao.DefinitionDAO;
33 import org.apache.tiles.util.LocaleUtil;
34 import org.springframework.jdbc.core.RowMapper;
35 import org.springframework.jdbc.core.support.JdbcDaoSupport;
36
37 /***
38 * Stub definition DAO to demonstrate that Tiles definitions can be stored in a
39 * Database.
40 *
41 * @version $Rev: 831448 $ $Date: 2009-10-30 21:39:52 +0100 (ven, 30 ott 2009) $
42 */
43 public class LocaleDbDefinitionDAO extends JdbcDaoSupport implements
44 DefinitionDAO<Locale> {
45
46 /***
47 * Selects a customization by its name.
48 */
49 private static final String SELECT_CUSTOMIZATION_BY_NAME_SQL =
50 "select ID, PARENT_ID, NAME from CUSTOMIZATION "
51 + "where NAME = ? ";
52
53 /***
54 * Selects a customization by its Id.
55 */
56 private static final String SELECT_CUSTOMIZATION_BY_ID_SQL =
57 "select ID, PARENT_ID, NAME from CUSTOMIZATION "
58 + "where ID = ? ";
59
60 /***
61 * Selects a definition by its name and a customization Id.
62 */
63 private static final String SELECT_DEFINITION_SQL =
64 "select ID, PARENT_NAME, NAME, PREPARER, TEMPLATE from DEFINITION "
65 + "where NAME = ? and CUSTOMIZATION_ID = ? ";
66
67 /***
68 * Selects attributes of a definition, given the definition Id.
69 */
70 private static final String SELECT_ATTRIBUTES_SQL =
71 "select ID, NAME, TYPE, VALUE, CASCADE_ATTRIBUTE from ATTRIBUTE "
72 + "where DEFINITION_ID = ? ";
73
74 /***
75 * Maps a row of a {@link ResultSet} to a {@link Definition}.
76 */
77 private final DefinitionRowMapper definitionRowMapper = new DefinitionRowMapper();
78
79 /*** {@inheritDoc} */
80 @SuppressWarnings("unchecked")
81 public Definition getDefinition(String name, Locale locale) {
82 List<Map<String, Object>> customizations = null;
83 Long customizationId = null, parentCustomizationId = null;
84 do {
85 customizations = getJdbcTemplate().queryForList(
86 SELECT_CUSTOMIZATION_BY_NAME_SQL,
87 new Object[] { locale.toString() });
88 if (!customizations.isEmpty()) {
89 Map<String, Object> customization = customizations.get(0);
90 customizationId = ((Number) customization.get("ID")).longValue();
91 parentCustomizationId = numberToLong((Number) customization.get("PARENT_ID"));
92 } else {
93 locale = LocaleUtil.getParentLocale(locale);
94 }
95 } while (customizations.isEmpty());
96
97 return getDefinition(name, customizationId, parentCustomizationId,
98 locale);
99 }
100
101 /*** {@inheritDoc} */
102 public Map<String, Definition> getDefinitions(Locale locale) {
103 throw new UnsupportedOperationException(
104 "Currently the 'getDefinitions' method is not supported");
105 }
106
107 /***
108 * Loads a definition from the DB.
109 *
110 * @param name The name of the definition.
111 * @param baseCustomizationId The id of the customization item.
112 * @param baseParentCustomizationId The id of the parent customization item.
113 * @param locale The locale.
114 * @return The definition.
115 */
116 @SuppressWarnings("unchecked")
117 protected DbDefinition getDefinition(String name, Long baseCustomizationId,
118 Long baseParentCustomizationId, Locale locale) {
119 DbDefinition definition = null;
120 Long customizationId = baseCustomizationId;
121 Long parentCustomizationId = baseParentCustomizationId;
122 List<DbDefinition> definitions = null;
123 boolean finished = false;
124 do {
125 definitions = getJdbcTemplate()
126 .query(SELECT_DEFINITION_SQL,
127 new Object[] { name, customizationId },
128 definitionRowMapper);
129 if (definitions.isEmpty()) {
130 if (parentCustomizationId != null) {
131 Map<String, Object> customization = getJdbcTemplate().queryForMap(
132 SELECT_CUSTOMIZATION_BY_ID_SQL,
133 new Object[] { parentCustomizationId });
134 customizationId = ((Number) customization.get("ID")).longValue();
135 parentCustomizationId = numberToLong((Number) customization.get("PARENT_ID"));
136 } else {
137 finished = true;
138 }
139 } else {
140 definition = definitions.get(0);
141 finished = true;
142 }
143 } while (!finished);
144
145 if (definition != null) {
146 AttributeRowMapper attributeRowMapper = new AttributeRowMapper(definition);
147 getJdbcTemplate().query(SELECT_ATTRIBUTES_SQL,
148 new Object[] { definition.getId() }, attributeRowMapper);
149 }
150 return definition;
151 }
152
153 /***
154 * Returns a {@link Long} object only if the number is not null.
155 *
156 * @param number The number to convert.
157 * @return The number converted into {@link Long} if not null,
158 * <code>null</code> otherwise.
159 */
160 private static Long numberToLong(Number number) {
161 Long retValue = null;
162 if (number != null) {
163 retValue = number.longValue();
164 }
165 return retValue;
166 }
167
168 /***
169 * A definition with the new property "id".
170 */
171 private static class DbDefinition extends Definition {
172
173 /***
174 * The id of the definition.
175 */
176 private Long id;
177
178 /***
179 * The default constructor.
180 */
181 public DbDefinition() {
182 super();
183 }
184
185 /***
186 * Returns the Id of the definition.
187 *
188 * @return The id.
189 */
190 public Long getId() {
191 return id;
192 }
193
194 /***
195 * Sets the id of the definition.
196 *
197 * @param id The id to set
198 */
199 public void setId(Long id) {
200 this.id = id;
201 }
202
203 }
204
205 /***
206 * Maps a row of a {@link ResultSet} to a {@link Definition}.
207 */
208 private static final class DefinitionRowMapper implements RowMapper {
209
210 /*** {@inheritDoc} */
211 public Object mapRow(ResultSet rs, int row) throws SQLException {
212 DbDefinition definition = new DbDefinition();
213 definition.setId(numberToLong((Number) rs.getObject("ID")));
214 definition.setName(rs.getString("NAME"));
215 definition.setTemplateAttribute(Attribute
216 .createTemplateAttribute(rs.getString("TEMPLATE")));
217 definition.setPreparer(rs.getString("PREPARER"));
218 definition.setExtends(rs.getString("PARENT_NAME"));
219 return definition;
220 }
221
222 }
223
224 /***
225 * Maps a row of a {@link ResultSet} to an {@link Attribute}. It stores the
226 * attributes directly in their definition.
227 */
228 private static final class AttributeRowMapper implements RowMapper {
229
230 /***
231 * The definition in which the attributes will be stored.
232 */
233 private Definition definition;
234
235 /***
236 * Constructor.
237 *
238 * @param definition The definition in which the attributes will be
239 * stored.
240 */
241 private AttributeRowMapper(Definition definition) {
242 this.definition = definition;
243 }
244
245 /*** {@inheritDoc} */
246 public Object mapRow(ResultSet rs, int row) throws SQLException {
247 Attribute attribute = new Attribute();
248 attribute.setRenderer(rs.getString("TYPE"));
249 attribute.setValue(rs.getString("VALUE"));
250 definition.putAttribute(rs.getString("NAME"), attribute, rs
251 .getBoolean("CASCADE_ATTRIBUTE"));
252 return attribute;
253 }
254
255 }
256 }