1 /*
2 *
3 * The DbUnit Database Testing Framework
4 * Copyright (C)2004-2008, DbUnit.org
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21 package org.dbunit.util;
22
23 import org.dbunit.DatabaseUnitRuntimeException;
24 import org.dbunit.database.DatabaseConfig;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29 * Utility to parse a fully qualified table name into its components <i>schema</i> and <i>table</i>.
30 * @author gommma
31 * @author Last changed by: $Author$
32 * @version $Revision$ $Date$
33 * @since 2.3.0
34 */
35 public class QualifiedTableName
36 {
37 /**
38 * Logger for this class
39 */
40 private static final Logger logger = LoggerFactory.getLogger(QualifiedTableName.class);
41
42 private String schema;
43 private String table;
44 private String escapePattern;
45
46 /**
47 * Creates an object parsing the given tableName.
48 * @param tableName The table name, either qualified or unqualified. If it is qualified (like "MYSCHEMA.MYTABLE")
49 * this schema name has precedence before the given <code>defaultSchema</code> parameter.
50 * @param defaultSchema The schema that is used when the given tableName is not fully qualified
51 * (i.e. it is not like "MYSCHEMA.MYTABLE"). Can be null
52 */
53 public QualifiedTableName(String tableName, String defaultSchema)
54 {
55 this(tableName, defaultSchema, null);
56 }
57
58 /**
59 * Creates an object parsing the given tableName.
60 * @param tableName The table name, either qualified or unqualified. If it is qualified (like "MYSCHEMA.MYTABLE")
61 * this schema name has precedence before the given <code>defaultSchema</code> parameter.
62 * @param defaultSchema The schema that is used when the given tableName is not fully qualified
63 * (i.e. it is not like "MYSCHEMA.MYTABLE"). Can be null
64 * @param escapePattern The escape pattern to be applied on the prefix and the name. Can be null.
65 */
66 public QualifiedTableName(String tableName, String defaultSchema, String escapePattern)
67 {
68 if(tableName==null){
69 throw new NullPointerException("The parameter 'tableName' must not be null");
70 }
71 parseFullTableName(tableName, defaultSchema);
72 this.escapePattern = escapePattern;
73 }
74
75 /**
76 * Parses the given full table name into a schema name and a table name if available. If
77 * no schema is set the value of the {@link #getSchema()} is null.
78 * Sets the corresponding members of this class if found.
79 * @param fullTableName potentially fully qualified table name
80 * @param defaultSchema The schema that is used when the given tableName is not fully qualified
81 * (i.e. it is not like "MYSCHEMA.MYTABLE"). Can be null
82 */
83 private void parseFullTableName(String fullTableName, String defaultSchema)
84 {
85 if(fullTableName==null){
86 throw new NullPointerException("The parameter 'fullTableName' must not be null");
87 }
88 // check if a schema is in front
89 int firstDotIndex = fullTableName.indexOf(".");
90 if (firstDotIndex != -1) {
91 // set schema
92 this.schema = fullTableName.substring(0, firstDotIndex);
93 // set table name without schema
94 this.table = fullTableName.substring(firstDotIndex + 1);
95 }
96 else
97 {
98 // No schema name found in table
99 this.table = fullTableName;
100 // If the schema has not been found in the given table name
101 // (that means there is no "MYSCHEMA.MYTABLE" but only a "MYTABLE")
102 // then set the schema to the given default schema
103 this.schema = defaultSchema;
104 }
105 }
106
107 /**
108 * @return The schema name which can be null if no schema has been given in the constructor
109 */
110 public String getSchema() {
111 return schema;
112 }
113
114 /**
115 * @return The name of the plain, unqualified table
116 */
117 public String getTable() {
118 return table;
119 }
120
121 /**
122 * @return The qualified table name with the prepended schema if a schema is available
123 */
124 public String getQualifiedName()
125 {
126 logger.debug("getQualifiedName() - start");
127
128 return getQualifiedName(this.schema, this.table, this.escapePattern);
129 }
130
131 /**
132 * Returns the qualified name using the values given in the constructor.
133 * The qualified table name is <b>only</b> returned if the feature
134 * {@link DatabaseConfig#FEATURE_QUALIFIED_TABLE_NAMES} is set. Otherwise the given
135 * name is returned unqualified (i.e. without prepending the prefix/schema).
136 * @return The qualified table name with the prepended schema if a schema is available.
137 * The qualified table name is <b>only</b> returned if the feature
138 * {@link DatabaseConfig#FEATURE_QUALIFIED_TABLE_NAMES} is set in the given <code>config</code>.
139 */
140 public String getQualifiedNameIfEnabled(DatabaseConfig config)
141 {
142 logger.debug("getQualifiedNameIfEnabled(config={}) - start", config);
143
144 boolean feature = config.getFeature(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES);
145 if (feature)
146 {
147 logger.debug("Qualified table names feature is enabled. Returning qualified table name");
148 return getQualifiedName(this.schema, this.table, this.escapePattern);
149 }
150 else
151 {
152 logger.debug("Qualified table names feature is disabled. Returning plain table name");
153 // return this.table;
154 return getQualifiedName(null, this.table, this.escapePattern);
155 }
156 }
157
158 public String toString() {
159 final StringBuilder sb = new StringBuilder();
160 sb.append(getClass().getName()).append("[");
161 sb.append("schema=").append(schema);
162 sb.append(", table=").append(table);
163 sb.append("]");
164 return sb.toString();
165 }
166
167
168
169 /**
170 * Returns the specified name qualified with the specified prefix. The name
171 * is not modified if the prefix is <code>null</code> or if the name is
172 * already qualified.
173 * <p>
174 * Example: <br>
175 * <code>getQualifiedName(null, "NAME")</code> returns
176 * <code>"NAME"</code>. <code>getQualifiedName("PREFIX", "NAME")</code>
177 * returns <code>"PREFIX.NAME"</code> and
178 * <code>getQualifiedName("PREFIX2", "PREFIX1.NAME")</code>
179 * returns <code>"PREFIX1.NAME"</code>.
180 *
181 * @param prefix the prefix that qualifies the name and is prepended if the name is not qualified yet
182 * @param name the name The name to be qualified if it is not qualified already
183 * @param escapePattern The escape pattern to be applied on the prefix and the name. Can be null.
184 * @return The qualified name
185 */
186 private String getQualifiedName(String prefix, String name,
187 String escapePattern)
188 {
189 if(logger.isDebugEnabled())
190 logger.debug("getQualifiedName(prefix={}, name={}, escapePattern={}) - start",
191 new String[] {prefix, name, escapePattern});
192
193 if (escapePattern != null)
194 {
195 prefix = getEscapedName(prefix, escapePattern);
196 name = getEscapedName(name, escapePattern);
197 }
198
199 if (prefix == null || prefix.equals("") || name.indexOf(".") >= 0)
200 {
201 return name;
202 }
203
204 return prefix + "." + name;
205 }
206
207
208 /**
209 * @param name
210 * @param escapePattern
211 * @return
212 */
213 private String getEscapedName(String name, String escapePattern)
214 {
215 logger.debug("getEscapedName(name={}, escapePattern={}) - start", name, escapePattern);
216
217 if (name == null)
218 {
219 return name;
220 }
221
222 if (escapePattern == null)
223 {
224 throw new NullPointerException(
225 "The parameter 'escapePattern' must not be null");
226 }
227 if(escapePattern.trim().equals(""))
228 {
229 throw new DatabaseUnitRuntimeException("Empty string is an invalid escape pattern!");
230 }
231
232 int split = name.indexOf(".");
233 if (split > 1)
234 {
235 return getEscapedName(name.substring(0, split), escapePattern) + "." + getEscapedName(name.substring(split + 1), escapePattern);
236 }
237
238 int index = escapePattern.indexOf("?");
239 if (index >=0 )
240 {
241 String prefix = escapePattern.substring(0, index);
242 String suffix = escapePattern.substring(index + 1);
243
244 return prefix + name + suffix;
245 }
246 else if(escapePattern.length() == 1)
247 {
248 // No "?" in the escape pattern and only one character.
249 // use the given escapePattern to surround the given name
250 return escapePattern + name + escapePattern;
251 }
252 else
253 {
254 logger.warn("Invalid escape pattern '" + escapePattern + "'. Will not escape name '" + name + "'.");
255 return name;
256 }
257 }
258
259 }