1/*2 * $Id: LocaleDbDefinitionDAO.java 1297705 2012-03-06 20:44:30Z nlebas $3 *4 * Licensed to the Apache Software Foundation (ASF) under one5 * or more contributor license agreements. See the NOTICE file6 * distributed with this work for additional information7 * regarding copyright ownership. The ASF licenses this file8 * to you under the Apache License, Version 2.0 (the9 * "License"); you may not use this file except in compliance10 * with the License. You may obtain a copy of the License at11 *12 * http://www.apache.org/licenses/LICENSE-2.013 *14 * Unless required by applicable law or agreed to in writing,15 * software distributed under the License is distributed on an16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY17 * KIND, either express or implied. See the License for the18 * specific language governing permissions and limitations19 * under the License.20 */2122package org.apache.tiles.test.db;
2324import java.sql.ResultSet;
25import java.sql.SQLException;
26import java.util.List;
27import java.util.Locale;
28import java.util.Map;
2930import org.apache.tiles.Attribute;
31import org.apache.tiles.Definition;
32import org.apache.tiles.definition.dao.DefinitionDAO;
33import org.apache.tiles.request.locale.LocaleUtil;
34import org.springframework.jdbc.core.RowMapper;
35import org.springframework.jdbc.core.support.JdbcDaoSupport;
3637/**38 * Stub definition DAO to demonstrate that Tiles definitions can be stored in a39 * Database.40 *41 * @version $Rev: 1297705 $ $Date: 2012-03-07 07:44:30 +1100 (Wed, 07 Mar 2012) $42 */43publicclassLocaleDbDefinitionDAOextends JdbcDaoSupport implements44 DefinitionDAO<Locale> {
4546/**47 * Selects a customization by its name.48 */49privatestaticfinal String SELECT_CUSTOMIZATION_BY_NAME_SQL =
50"select ID, PARENT_ID, NAME from CUSTOMIZATION "51 + "where NAME = ? ";
5253/**54 * Selects a customization by its Id.55 */56privatestaticfinal String SELECT_CUSTOMIZATION_BY_ID_SQL =
57"select ID, PARENT_ID, NAME from CUSTOMIZATION "58 + "where ID = ? ";
5960/**61 * Selects a definition by its name and a customization Id.62 */63privatestaticfinal String SELECT_DEFINITION_SQL =
64"select ID, PARENT_NAME, NAME, PREPARER, TEMPLATE from DEFINITION "65 + "where NAME = ? and CUSTOMIZATION_ID = ? ";
6667/**68 * Selects attributes of a definition, given the definition Id.69 */70privatestaticfinal String SELECT_ATTRIBUTES_SQL =
71"select ID, NAME, TYPE, VALUE, CASCADE_ATTRIBUTE from ATTRIBUTE "72 + "where DEFINITION_ID = ? ";
7374/**75 * Maps a row of a {@link ResultSet} to a {@link Definition}.76 */77privatefinalDefinitionRowMapper definitionRowMapper = newDefinitionRowMapper();
7879/** {@inheritDoc} */80 @SuppressWarnings("unchecked")
81publicDefinition getDefinition(String name, Locale locale) {
82 List<Map<String, Object>> customizations = null;
83 Long customizationId = null, parentCustomizationId = null;
84do {
85 customizations = getJdbcTemplate().queryForList(
86 SELECT_CUSTOMIZATION_BY_NAME_SQL,
87new Object[] { locale.toString() });
88if (!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());
9697return getDefinition(name, customizationId, parentCustomizationId,
98 locale);
99 }
100101/** {@inheritDoc} */102public Map<String, Definition> getDefinitions(Locale locale) {
103thrownew UnsupportedOperationException(
104"Currently the 'getDefinitions' method is not supported");
105 }
106107/**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")
117protectedDbDefinition getDefinition(String name, Long baseCustomizationId,
118 Long baseParentCustomizationId, @SuppressWarnings("unused") Locale locale) {
119DbDefinition definition = null;
120 Long customizationId = baseCustomizationId;
121 Long parentCustomizationId = baseParentCustomizationId;
122 List<DbDefinition> definitions = null;
123boolean finished = false;
124do {
125 definitions = getJdbcTemplate()
126 .query(SELECT_DEFINITION_SQL,
127new Object[] { name, customizationId },
128 definitionRowMapper);
129if (definitions.isEmpty()) {
130if (parentCustomizationId != null) {
131 Map<String, Object> customization = getJdbcTemplate().queryForMap(
132 SELECT_CUSTOMIZATION_BY_ID_SQL,
133new 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);
144145if (definition != null) {
146AttributeRowMapper attributeRowMapper = newAttributeRowMapper(definition);
147 getJdbcTemplate().query(SELECT_ATTRIBUTES_SQL,
148new Object[] { definition.getId() }, attributeRowMapper);
149 }
150return definition;
151 }
152153/**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 */160privatestatic Long numberToLong(Number number) {
161 Long retValue = null;
162if (number != null) {
163 retValue = number.longValue();
164 }
165return retValue;
166 }
167168/**169 * A definition with the new property "id".170 */171privatestaticclassDbDefinitionextendsDefinition {
172173/**174 * The id of the definition.175 */176private Long id;
177178/**179 * The default constructor.180 */181publicDbDefinition() {
182super();
183 }
184185/**186 * Returns the Id of the definition.187 *188 * @return The id.189 */190public Long getId() {
191return id;
192 }
193194/**195 * Sets the id of the definition.196 *197 * @param id The id to set198 */199publicvoid setId(Long id) {
200this.id = id;
201 }
202203 }
204205/**206 * Maps a row of a {@link ResultSet} to a {@link Definition}.207 */208privatestaticfinalclassDefinitionRowMapperimplements RowMapper {
209210/** {@inheritDoc} */211public Object mapRow(ResultSet rs, int row) throws SQLException {
212DbDefinition definition = newDbDefinition();
213 definition.setId(numberToLong((Number) rs.getObject("ID")));
214 definition.setName(rs.getString("NAME"));
215 definition.setTemplateAttribute(Attribute216 .createTemplateAttribute(rs.getString("TEMPLATE")));
217 definition.setPreparer(rs.getString("PREPARER"));
218 definition.setExtends(rs.getString("PARENT_NAME"));
219return definition;
220 }
221222 }
223224/**225 * Maps a row of a {@link ResultSet} to an {@link Attribute}. It stores the226 * attributes directly in their definition.227 */228privatestaticfinalclassAttributeRowMapperimplements RowMapper {
229230/**231 * The definition in which the attributes will be stored.232 */233privateDefinition definition;
234235/**236 * Constructor.237 *238 * @param definition The definition in which the attributes will be239 * stored.240 */241privateAttributeRowMapper(Definition definition) {
242this.definition = definition;
243 }
244245/** {@inheritDoc} */246public Object mapRow(ResultSet rs, int row) throws SQLException {
247Attribute attribute = newAttribute();
248 attribute.setRenderer(rs.getString("TYPE"));
249 attribute.setValue(rs.getString("VALUE"));
250 definition.putAttribute(rs.getString("NAME"), attribute, rs
251 .getBoolean("CASCADE_ATTRIBUTE"));
252return attribute;
253 }
254255 }
256 }