001: /**
002: * Copyright 2006 Webmedia Group Ltd.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: **/package org.araneaframework.backend.list.helper.naming;
016:
017: import java.sql.ResultSet;
018: import java.util.Collection;
019: import java.util.HashMap;
020: import java.util.LinkedHashMap;
021: import java.util.Map;
022:
023: import org.apache.commons.lang.StringUtils;
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026: import org.araneaframework.backend.list.helper.ListSqlHelper;
027: import org.araneaframework.backend.list.helper.fields.Fields;
028:
029: /**
030: * Naming conventions and list of fields provider which is based on mappings.
031: * <p>
032: * There are 3 types of fields:
033: * <ul>
034: * <li>Fields presented in <code>SELECT</code> and are read from the {@link ResultSet} - use methods {@link #addMapping(String, String, String)} and {@link #addMapping(String, String)}</li>
035: * <li>Fields presented in <code>SELECT</code> but are not read from the {@link ResultSet} - use method {@link #addDatabaseFieldMapping(String, String, String)} and {@link #addDatabaseFieldMapping(String, String)}</li>
036: * <li>Fields not presented in <code>SELECT</code> but which are read from the {@link ResultSet} - use method {@link #addResultSetMapping(String, String)}</li>
037: * </ul>
038: * The term <code>SELECT</code> refers to the corresponding SQL segment constructed by Aranea Lists.
039: * That may be wrapped inside another SQL clause for example.
040: * </p>
041: * <p>
042: * Each list field must be added together with it's corresponding column name (and alias).
043: * </p>
044: * <p>
045: * This implementation is based on the {@link ListSqlHelper} methods up to Aranea MVC 1.1-M5.
046: * </p>
047: *
048: * @see NamingStrategy
049: * @see ListSqlHelper#getMappingNamingStrategyAndFields()
050: *
051: * @author Rein Raudjärv
052: *
053: * @since 1.1
054: */
055: public class MappingNamingStrategyAndFields implements NamingStrategy,
056: Fields {
057:
058: private static final Log log = LogFactory
059: .getLog(MappingNamingStrategyAndFields.class);
060:
061: /**
062: * Field name --> Database column name
063: * (all these fields are in <code>SELECT</code>)
064: * */
065: private Map fieldToColumnName = new HashMap();
066:
067: /**
068: * Field name --> Database column alias
069: * (all these fields are in <code>SELECT</code>)
070: * */
071: private Map fieldToColumnAlias = new LinkedHashMap();
072:
073: /**
074: * Field name --> Result set column name
075: * (all these fields are in the result set)
076: * */
077: private Map fieldToResultSetColumn = new LinkedHashMap();
078:
079: /**
080: * Adds a <b>field name</b> to database <b>column name</b> and <b>column alias</b> mapping.
081: * <p>
082: * A given field is listed in the <code>SELECT</code> but is not read from the {@link ResultSet}.
083: *
084: * @param fieldName
085: * field name.
086: * @param columnName
087: * database column name.
088: * @param columnAlias
089: * database column alias.
090: *
091: * @see #addMapping(String, String, String)
092: * @see #addMapping(String, String)
093: * @see #addDatabaseFieldMapping(String, String)
094: * @see #addResultSetMapping(String, String)
095: */
096: public void addDatabaseFieldMapping(String fieldName,
097: String columnName, String columnAlias) {
098: this .fieldToColumnName.put(fieldName, columnName);
099: this .fieldToColumnAlias.put(fieldName, columnAlias);
100: }
101:
102: /**
103: * Adds a <b>field name</b> to database <b>column name</b> mapping.
104: * <p>
105: * A given field is listed in the <code>SELECT</code> but is not read from the {@link ResultSet}.
106: * </p>
107: * <p>
108: * The corresponding <b>column alias</b> is generated automatically.
109: *
110: * @param fieldName
111: * field name.
112: * @param columnName
113: * database column name.
114: *
115: * @see #addMapping(String, String, String)
116: * @see #addMapping(String, String)
117: * @see #addDatabaseFieldMapping(String, String, String)
118: * @see #addResultSetMapping(String, String)
119: */
120: public void addDatabaseFieldMapping(String fieldName,
121: String columnName) {
122: addDatabaseFieldMapping(fieldName, columnName,
123: createAlias(columnName));
124: }
125:
126: /**
127: * Adds a <b>field name</b> to database <b>column alias</b> mapping.
128: * <p>
129: * A given field is not listed in the <code>SELECT</code> but is read from the {@link ResultSet}.
130: * </p>
131: *
132: * @param fieldName
133: * field name.
134: * @param columnAlias
135: * database column name in the result set.
136: *
137: * @see #addMapping(String, String, String)
138: * @see #addMapping(String, String)
139: * @see #addDatabaseFieldMapping(String, String, String)
140: * @see #addDatabaseFieldMapping(String, String)
141: */
142: public void addResultSetMapping(String fieldName, String columnAlias) {
143: this .fieldToResultSetColumn.put(fieldName, columnAlias);
144: }
145:
146: /**
147: * Adds a <b>field name</b> to database <b>column name</b> and <b>column alias</b> mapping.
148: * <p>
149: * A given field is listed in the <code>SELECT</code> and is read from the {@link ResultSet}.
150: *
151: * @param fieldName
152: * field name.
153: * @param columnName
154: * database column name.
155: * @param columnAlias
156: * database column alias.
157: *
158: * @see #addMapping(String, String)
159: * @see #addDatabaseFieldMapping(String, String, String)
160: * @see #addDatabaseFieldMapping(String, String)
161: * @see #addResultSetMapping(String, String)
162: */
163: public void addMapping(String fieldName, String columnName,
164: String columnAlias) {
165: addDatabaseFieldMapping(fieldName, columnName, columnAlias);
166: addResultSetMapping(fieldName, columnAlias);
167: }
168:
169: /**
170: * Adds a <b>field name</b> to database <b>column name</b>.
171: * <p>
172: * A given field is listed in the <code>SELECT</code> and is read from the {@link ResultSet}.
173: * </p>
174: * <p>
175: * The corresponding <b>column alias</b> is generated automatically.
176: *
177: * @param fieldName
178: * field name.
179: * @param columnName
180: * database column name.
181: *
182: * @see #addMapping(String, String, String)
183: * @see #addDatabaseFieldMapping(String, String, String)
184: * @see #addDatabaseFieldMapping(String, String)
185: * @see #addResultSetMapping(String, String)
186: */
187: public void addMapping(String fieldName, String columnName) {
188: addMapping(fieldName, columnName, createAlias(columnName));
189: }
190:
191: // Fields
192:
193: public Collection getNames() {
194: return fieldToColumnAlias.keySet();
195: }
196:
197: public Collection getResultSetNames() {
198: return fieldToResultSetColumn.keySet();
199: }
200:
201: // NamingStrategy
202:
203: public String fieldToColumnName(String variableName) {
204: return (String) fieldToColumnName.get(variableName);
205: }
206:
207: public String fieldToColumnAlias(String variableName) {
208: String result = (String) fieldToColumnAlias.get(variableName);
209: if (result == null) {
210: result = (String) fieldToResultSetColumn.get(variableName);
211: }
212: return result;
213: }
214:
215: // Generating Aliases
216:
217: /**
218: * @return a new <b>column alias</b>.
219: */
220: protected String createAlias(String columnName) {
221: // Remove prefix
222: String tmp = columnName
223: .substring(columnName.lastIndexOf('.') + 1);
224: // TODO: replace with 1.3 compatible regexp check
225: if (!StringUtils
226: .containsOnly(tmp,
227: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_")) {
228: tmp = "alias";
229: }
230:
231: // Make unique
232: String alias = tmp;
233: int index = 0;
234: while (this .fieldToColumnAlias.containsValue(alias)) {
235: alias = tmp + index++;
236: }
237:
238: if (log.isDebugEnabled()) {
239: log.debug("Generated '" + alias + "' as alias for field '"
240: + columnName + "'");
241: }
242: return alias;
243: }
244:
245: }
|