001    package org.apache.torque.engine.database.model;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.ArrayList;
023    import java.util.Collections;
024    import java.util.Iterator;
025    import java.util.List;
026    import java.util.Map;
027    
028    import org.apache.commons.collections.map.ListOrderedMap;
029    import org.apache.commons.logging.Log;
030    import org.apache.commons.logging.LogFactory;
031    
032    import org.apache.torque.engine.EngineException;
033    
034    import org.xml.sax.Attributes;
035    
036    /**
037     * Information about indices of a table.
038     *
039     * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
040     * @author <a href="mailto:dlr@finemaltcoding.com>Daniel Rall</a>
041     * @author <a href="mailto:monroe@dukece.com>Greg Monroe</a>
042     * @version $Id: Index.java,v 1.1 2007-10-21 07:57:27 abyrne Exp $
043     */
044    public class Index
045    {
046        /** Logging class from commons.logging */
047        private static Log log = LogFactory.getLog(Index.class);
048        /** name of the index */
049        private String indexName;
050        /** table */
051        private Table parentTable;
052        /** columns */
053        private List indexColumns;
054        /** The XML Options specified for this index */
055        private Map options;
056    
057    
058        /**
059         * Creates a new instance with default characteristics (no name or
060         * parent table, small column list size allocation, non-unique).
061         */
062        public Index()
063        {
064            indexColumns = new ArrayList(3);
065            options = Collections.synchronizedMap(new ListOrderedMap());
066        }
067    
068        /**
069         * Creates a new instance for the list of columns composing an
070         * index.  Otherwise performs as {@link #Index()}.
071         *
072         * @param table The table this index is associated with.
073         * @param indexColumns The list of {@link
074         * org.apache.torque.engine.database.model.Column} objects which
075         * make up this index.  Cannot be empty.
076         * @exception EngineException Error generating name.
077         * @see #Index()
078         */
079        protected Index(Table table, List indexColumns)
080            throws EngineException
081        {
082            this();
083            setTable(table);
084            if (!indexColumns.isEmpty())
085            {
086                this.indexColumns = indexColumns;
087    
088                if (log.isDebugEnabled())
089                {
090                    log.debug("Created Index named " + getName()
091                            + " with " + indexColumns.size() + " columns");
092                }
093            }
094            else
095            {
096                throw new EngineException("Cannot create a new Index using an "
097                        + "empty list Column object");
098            }
099        }
100    
101        /**
102         * Imports index from an XML specification
103         *
104         * @param attrib the xml attributes
105         */
106        public void loadFromXML(Attributes attrib)
107        {
108            indexName = attrib.getValue("name");
109        }
110    
111        /**
112         * Returns the uniqueness of this index.
113         *
114         * @return the uniqueness of this index
115         */
116        public boolean isUnique()
117        {
118            return false;
119        }
120    
121        /**
122         * Gets the name of this index.
123         *
124         * @return the name of this index
125         */
126        public String getName()
127        {
128            return indexName;
129        }
130    
131        /**
132         * Set the name of this index.
133         *
134         * @param name the name of this index
135         */
136        public void setName(String name)
137        {
138            this.indexName = name;
139        }
140    
141        /**
142         * Set the parent Table of the index
143         *
144         * @param parent the table
145         */
146        public void setTable(Table parent)
147        {
148            parentTable = parent;
149        }
150    
151        /**
152         * Get the parent Table of the index
153         *
154         * @return the table
155         */
156        public Table getTable()
157        {
158            return parentTable;
159        }
160    
161        /**
162         * Returns the Name of the table the index is in
163         *
164         * @return the name of the table
165         */
166        public String getTableName()
167        {
168            return parentTable.getName();
169        }
170    
171        /**
172         * Adds a new column to an index.
173         *
174         * @param attrib xml attributes for the column
175         */
176        public void addColumn(Attributes attrib)
177        {
178            indexColumns.add(attrib.getValue("name"));
179        }
180    
181        /**
182         * Return a comma delimited string of the columns which compose this index.
183         *
184         * @return a list of column names
185         */
186        public String getColumnList()
187        {
188            return Column.makeList(getColumns());
189        }
190    
191        /**
192         * Return the list of local columns. You should not edit this list.
193         *
194         * @return a list of columns
195         */
196        public List getColumns()
197        {
198            return indexColumns;
199        }
200    
201        /**
202         * Returns the list of names of the columns referenced by this
203         * index.  Slightly over-allocates the list's buffer (just in case
204         * more elements are going to be added, such as when a name is
205         * being generated).  Feel free to modify this list.
206         *
207         * @return a list of column names
208         */
209        protected List getColumnNames()
210        {
211            List names = new ArrayList(indexColumns.size() + 2);
212            Iterator i = getColumns().iterator();
213            while (i.hasNext())
214            {
215                Column c = (Column) i.next();
216                names.add(c.getName());
217            }
218            return names;
219        }
220    
221        /**
222         * String representation of the index. This is an xml representation.
223         *
224         * @return a xml representation
225         */
226        public String toString()
227        {
228            StringBuffer result = new StringBuffer();
229            result.append(" <index name=\"")
230                  .append(getName())
231                  .append("\"");
232    
233            result.append(">\n");
234    
235            for (int i = 0; i < indexColumns.size(); i++)
236            {
237                result.append("  <index-column name=\"")
238                    .append(indexColumns.get(i))
239                    .append("\"/>\n");
240            }
241            result.append(" </index>\n");
242            return result.toString();
243        }
244    
245        /**
246         * Add an XML Specified option key/value pair to this element's option set.
247         *
248         * @param key the key of the option.
249         * @param value the value of the option.
250         */
251        public void addOption(String key, String value)
252        {
253            options.put(key, value);
254        }
255    
256        /**
257         * Get the value that was associated with this key in an XML option
258         * element.
259         *
260         * @param key the key of the option.
261         * @return The value for the key or a null.
262         */
263        public String getOption(String key)
264        {
265            return (String) options.get(key);
266        }
267    
268        /**
269         * Gets the full ordered hashtable array of items specified by XML option
270         * statements under this element.<p>
271         *
272         * Note, this is not thread save but since it's only used for
273         * generation which is single threaded, there should be minimum
274         * danger using this in Velocity.
275         *
276         * @return An Map of all options. Will not be null but may be empty.
277         */
278        public Map getOptions()
279        {
280            return options;
281        }
282    }