1   /*
2    * Copyright 2003 - 2013 The eFaps Team
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Revision:        $Rev$
17   * Last Changed:    $Date$
18   * Last Changed By: $Author$
19   */
20  
21  package org.efaps.db.databases.information;
22  
23  import java.io.Serializable;
24  import java.util.HashMap;
25  import java.util.Map;
26  import java.util.Set;
27  import java.util.UUID;
28  
29  import org.apache.commons.lang3.builder.ToStringBuilder;
30  import org.efaps.db.databases.AbstractDatabase;
31  import org.efaps.util.cache.CacheObjectInterface;
32  
33  /**
34   * Class used to return information about a SQL table.
35   *
36   * @author The eFaps Team
37   * @version $Id$
38   */
39  public class TableInformation
40      implements CacheObjectInterface, Serializable
41  {
42      /**
43       * Needed for serialization.
44       */
45      private static final long serialVersionUID = 1L;
46  
47      /**
48       * Stores the map between a column name and the column information itself.
49       *
50       * @see #getColInfo(String)
51       * @see #addColInfo(String, Set, int, int, boolean)
52       */
53      private final Map<String, ColumnInformation> colMap = new HashMap<String, ColumnInformation>();
54  
55      /**
56       * Stores the map between a unique key name and the unique key information
57       * itself.
58       *
59       * @see #getUKInfo(String)
60       * @see #addUniqueKeyColumn(String, String)
61       */
62      private final Map<String, UniqueKeyInformation> ukMap = new HashMap<String, UniqueKeyInformation>();
63  
64      /**
65       * Stores the map between comma separated string of column names of a unique
66       * key and the unique key itself.
67       *
68       * @see #getUKInfoByColNames(String)
69       * @see #addUniqueKeyColumn(String, String)
70       */
71      private final Map<String, UniqueKeyInformation> ukColMap = new HashMap<String, UniqueKeyInformation>();
72  
73      /**
74       * Stores the map between a name of a foreign key and the information about
75       * the foreign key itself. The name of all foreign keys are in upper case.
76       *
77       * @see #getFKInfo(String)
78       * @see #addForeignKey(String, String, String, String, boolean)
79       */
80      private final Map<String, ForeignKeyInformation> fkMap = new HashMap<String, ForeignKeyInformation>();
81  
82      /**
83       * SQL table name.
84       *
85       * @see #TableInformation(String)
86       * @see #getName()
87       */
88      private final String name;
89  
90      /**
91       * Initialize this table information instance for given
92       * <code>_tableName</code>.
93       *
94       * @param _tableName    name of SQL table for which the information
95       *                      is searched
96       */
97      public TableInformation(final String _tableName)
98      {
99          this.name = _tableName.toUpperCase();
100     }
101 
102     /**
103      * Appends the column information for given values for column
104      * <code>_colName</code>.
105      *
106      * @param _colName      name of the column
107      * @param _colTypes     eFaps types of the column
108      * @param _size         size (for character)
109      * @param _scale        scale (for number)
110      * @param _isNullable   is the column nullable?
111      * @see #colMap
112      */
113     public void addColInfo(final String _colName,
114                               final Set<AbstractDatabase.ColumnType> _colTypes,
115                               final int _size,
116                               final int _scale,
117                               final boolean _isNullable)
118     {
119         this.colMap.put(_colName.toUpperCase(),
120                         new ColumnInformation(_colName, _colTypes, _size, _scale, _isNullable));
121     }
122 
123     /**
124      * Adds an unique key information to this table information.
125      *
126      * @param _ukName   name of unique key
127      * @param _colIndex index of the column for given unique key
128      * @param _colName  name of the column for given unique key
129      * @see #ukMap
130      * @see #ukColMap
131      */
132     public void addUniqueKeyColumn(final String _ukName,
133                                    final int _colIndex,
134                                    final String _colName)
135     {
136         final String ukName = _ukName.toUpperCase();
137         final UniqueKeyInformation uki;
138         if (!this.ukMap.containsKey(ukName))  {
139             uki = new UniqueKeyInformation(_ukName);
140             this.ukMap.put(ukName, uki);
141         } else  {
142             uki = this.ukMap.get(ukName);
143         }
144         uki.appendColumnName(_colIndex, _colName);
145 
146 //        this.ukColMap.put(uki.getColumnNames(), uki);
147     }
148 
149     /**
150      * Fetches all foreign keys for this table.
151      *
152      * @param _fkName       name of foreign key
153      * @param _colName      name of column name
154      * @param _refTableName name of referenced SQL table
155      * @param _refColName   name of column within referenced SQL table
156      * @param _cascade      delete cascade activated
157      * @see #fkMap
158      */
159     public void addForeignKey(final String _fkName,
160                               final String _colName,
161                               final String _refTableName,
162                               final String _refColName,
163                               final boolean _cascade)
164     {
165         this.fkMap.put(_fkName.toUpperCase(),
166                        new ForeignKeyInformation(_fkName, _colName, _refTableName, _refColName, _cascade));
167     }
168 
169     /**
170      * <p>Returns for given column name (of the SQL table) the column
171      * information. If the column does not exists in the table, a
172      * <code>null</code> is returned.</p>
173      * <p>The name of given column is searched independently of upper and / or
174      * lower case.</p>
175      *
176      * @param _columnName   name of column for which the column information is
177      *                      searched
178      * @return column information for given column name; or <code>null</code>
179      *         if column does not exists in the table
180      * @see #colMap
181      */
182     public ColumnInformation getColInfo(final String _columnName)
183     {
184         return (_columnName != null)
185                ? this.colMap.get(_columnName.toUpperCase())
186                : null;
187     }
188 
189     /**
190      * <p>Returns for given name of unique key (of the SQL table) the
191      * information about the unique key, or if the given name of unique key is
192      * not defined, a <code>null</code> is returned.</p>
193      * <p>The name of the given unique key is searched independently of upper
194      * and / or lower case.</p>
195      *
196      * @param _ukName   name of unique key which is searched
197      * @return unique key information
198      * @see #ukMap
199      */
200     public UniqueKeyInformation getUKInfo(final String _ukName)
201     {
202         return (_ukName != null)
203                ? this.ukMap.get(_ukName.toUpperCase())
204                : null;
205     }
206 
207     /**
208      * <p>Returns for given name of unique key <code>_ukColName</code> (of the
209      * SQL table) the information about the unique key, or if the given name of
210      * unique key is not defined, a <code>null</code> is returned.</p>
211      * <p>The name of the given unique key is searched independently of upper
212      * and / or lower case.</p>
213      *
214      * @param _ukColName  name of column names for which the unique key is
215      *                    searched
216      * @return unique key information
217      * @see #ukColMap
218      */
219     public UniqueKeyInformation getUKInfoByColNames(final String _ukColName)
220     {
221         return (_ukColName != null)
222                ? this.ukColMap.get(_ukColName.toUpperCase())
223                : null;
224     }
225 
226     /**
227      * <p>Returns for given name of foreign key <code>_fkName</code> (of the
228      * SQL table) the information about the foreign key, or if the given name
229      * of foreign key is not defined, a <code>null</code> is returned.</p>
230      * <p>The name of the given foreign key is searched independently of upper
231      * and / or lower case.</p>
232      *
233      * @param _fkName   name of foreign key which is searched
234      * @return foreign key information
235      * @see #fkMap
236      */
237     public ForeignKeyInformation getFKInfo(final String _fkName)
238     {
239         return (_fkName != null)
240                ? this.fkMap.get(_fkName.toUpperCase())
241                : null;
242     }
243 
244     /**
245      * Returns the string representation of this class instance. The
246      * information includes {@link #name}, {@link #colMap}, {@link #ukMap} and
247      * {@link #fkMap}.
248      *
249      * @return string representation of this table information
250      */
251     @Override
252     public String toString()
253     {
254         return new ToStringBuilder(this)
255             .append("name", this.name)
256             .append("columns", this.colMap.values())
257             .append("unique keys", this.ukMap.values())
258             .append("foreign keys", this.fkMap.values())
259             .toString();
260     }
261 
262     /**
263      * Returns the {@link #name table name}.
264      *
265      * @return table name
266      * @see #name
267      */
268     @Override
269     public String getName()
270     {
271         return this.name;
272     }
273 
274     /**
275      * An id does not exists for the table information and so an error will
276      * be always thrown if this method is called. The method is only required
277      * to implement interface {@link CacheObjectInterface},
278      * @return nothing because an error will be always thrown
279      */
280     @Override
281     public long getId()
282     {
283         throw new Error("id does not exists for the table information");
284     }
285 
286     /**
287      * An UUID does not exists for the table information and so an error will
288      * be always thrown if this method is called. The method is only required
289      * to implement interface {@link CacheObjectInterface},
290      *
291      * @return nothing because an error will be always thrown
292      */
293     @Override
294     public UUID getUUID()
295     {
296         throw new Error("UUID does not exists for the table information");
297     }
298 }