View Javadoc

1   package uba.db.table;
2   
3   import java.io.Serializable;
4   import java.util.Collections;
5   import java.util.List;
6   import java.util.Set;
7   
8   import org.apache.commons.collections.CollectionUtils;
9   import org.apache.commons.collections.Predicate;
10  import org.apache.commons.collections.SetUtils;
11  import org.apache.commons.lang.builder.EqualsBuilder;
12  import org.apache.commons.lang.builder.HashCodeBuilder;
13  
14  import uba.db.column.ColumnSpecification;
15  
16  /***
17   * Representa el esquema de una tabla. La diferencias con un
18   * {@link uba.db.relationalmodel.RelationSchema} son:
19   * <ul>
20   * <li>basicamente estan a "niveles" distintos, mientras que un esquema de
21   * relación representa algo lógico, una tabla esta asociada con la información
22   * fisica en disco y por lo tanto brinda la forma de acceder a esa información.</li>
23   * <li>una tabla tiene que tener un nombre (un esquema de relación podria no
24   * tenerlo)</li>
25   * <li>un esquema de tabla contiene además información sobre los constraints
26   * (indices, foreing keys, etc)</i>
27   * <li>los columnas de una tabla tienen que tener un nombre</li>
28   * <li>varios "tipos" de columna podrian mapearse a un mismo dominio de
29   * atributo en un esquema de relacion (por ejemplo CHAR y VARCHAR son Strings)</li>
30   * </ul>
31   * 
32   * @version $Revision: 1.3 $
33   */
34  public class TableSchema implements Serializable {
35      private static final long serialVersionUID = 3617571600447583797L;
36  
37      private List columnSpecifications;
38      private String tableName;
39      private Set primaryKeyColumns;
40  
41      /***
42       * Crea una nueva instancia especificando el nombre que tendrá la tabla, la
43       * definición de cada uno de sus campos y los constraints.
44       * 
45       * @param tableName
46       *            nombre de la tabla.
47       * @param columnSpecifications
48       *            especificación de cada uno de los campos.
49       * @param primaryKeyColumns
50       *            colección con la especificacion de los campos que conforman la
51       *            clave primaria.
52       */
53      public TableSchema(String tableName, List columnSpecifications, Set primaryKeyColumns)
54              throws InvalidTableNameException, InvalidPrimaryKeyColumnsException {
55          validateTableName(tableName);
56  
57          this.tableName = tableName.toLowerCase();
58          this.columnSpecifications = columnSpecifications;
59          this.primaryKeyColumns = primaryKeyColumns;
60  
61          validatePrimaryKeys();
62      }
63  
64      /***
65       * Este constructor es equivalente a:
66       * TableSchema(tableName, columnSpecifications, <i>conjunto vacio</i>).
67       * 
68       * @see #TableSchema(String, List, Set)
69       */
70      public TableSchema(String tableName, List columnSpecifications) {
71          this(tableName, columnSpecifications, SetUtils.EMPTY_SET);
72      }
73  
74      private void validateTableName(String name) {
75          if (name == null || name.length() == 0) {
76              throw new InvalidTableNameException();
77          }
78      }
79  
80  
81      private void validatePrimaryKeys() {
82          if (primaryKeyColumns == null || !allPrimaryKeysContainedInColumnSpecifications()) {
83              throw new InvalidPrimaryKeyColumnsException();
84          }
85      }
86  
87      private boolean allPrimaryKeysContainedInColumnSpecifications() {
88          return CollectionUtils.isProperSubCollection(primaryKeyColumns,
89                                                       columnSpecifications);
90      }
91  
92      /***
93       * @see java.lang.Object#equals(java.lang.Object)
94       */
95      public boolean equals(Object obj) {
96          return EqualsBuilder.reflectionEquals(this, obj);
97      }
98  
99      /***
100      * @see java.lang.Object#hashCode()
101      */
102     public int hashCode() {
103         return HashCodeBuilder.reflectionHashCode(this);
104     }
105 
106     /***
107      * Retorna el nombre de la tabla que representa este esquema.
108      * 
109      * @return un {@link String} no nulo.
110      */
111     public String tableName() {
112         return tableName;
113     }
114 
115     /***
116      * Retorna un conjunto con las especificaciones de columna de esta tabla que
117      * conforman la clave primaria de la tabla.
118      */
119     public Set primaryKeyColumns() {
120         return Collections.unmodifiableSet(primaryKeyColumns);
121     }
122 
123     /***
124      * Retorna una lista con las especificaciones de columna que contiene este esquema.
125      */
126     public List columnSpecifications() {
127         return Collections.unmodifiableList(columnSpecifications);
128     }
129 
130     /***
131      * @see uba.db.table.TableSchema#containsColumnNamed(java.lang.String)
132      */
133     public boolean containsColumnNamed(final String columnName) {
134         return CollectionUtils.exists(columnSpecifications, new Predicate() {
135             public boolean evaluate(Object columnSpecification) {
136                 return ((ColumnSpecification) columnSpecification).name()
137                         .equalsIgnoreCase(columnName);
138             }
139         });
140     }
141 }