001/*
002 * Copyright (c) 2003-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.ecoinformatics.seek.querybuilder;
031
032import java.util.Enumeration;
033import java.util.Vector;
034
035import javax.swing.AbstractListModel;
036
037/**
038 * This class represents the model for the JList class. The complexity here is
039 * that the model want to view everything as a a vector, but the items are
040 * actually an object tree. So the options where to:<br>
041 * 1) Use a vecotr as the model and add the complexity to the add and remove
042 * methods (this is what was done) 2) Use the "real" data model and then when an
043 * item was asked for by index we traverse the tree to figure out the index each
044 * time.<br>
045 * <br>
046 * Assuming painting occurs more often than model updates I went with approach
047 * number one
048 */
049public class DBWhereModel extends AbstractListModel {
050        protected Vector mItems = new Vector();
051        protected DBWhereIFace mRootObj = null;
052
053        /**
054         * Default Constructor
055         */
056        public DBWhereModel() {
057        }
058
059        /**
060         * Initialize it by clearing everything and building it from the root where
061         * object
062         * 
063         * @param aWhereObj
064         */
065        public void initialize(DBWhereIFace aWhereObj) {
066                mItems.clear();
067                mRootObj = aWhereObj;
068                buildFromWhereObj(mRootObj);
069                fireContentsChanged();
070        }
071
072        /**
073         * Build it from the where object
074         * 
075         * @param aWhereObj
076         *            the new object
077         */
078        protected void buildFromWhereObj(DBWhereIFace aWhereObj) {
079                if (aWhereObj != null) {
080                        mItems.add(aWhereObj);
081                        if (aWhereObj.isOperator() && aWhereObj instanceof DBWhereOperator) {
082                                DBWhereOperator whereObj = (DBWhereOperator) aWhereObj;
083                                for (Enumeration et = whereObj.getEnumeration(); et
084                                                .hasMoreElements();) {
085                                        buildFromWhereObj((DBWhereIFace) et.nextElement());
086                                }
087                                mItems.add(whereObj.getClosure());
088                        }
089                }
090        }
091
092        /**
093         * Returns the size of the model
094         */
095        public int getSize() {
096                return mItems.size();
097        }
098
099        /**
100         * Gets an element in the model at a specified index
101         */
102        public Object getElementAt(int index) {
103                return mItems.elementAt(index);
104        }
105
106        /**
107         * Returns the current insertion index depending on the current drag over
108         * item
109         * 
110         * @return the index
111         */
112        protected int getInsertionIndexFromDrag() {
113                int inx = 0;
114
115                for (Enumeration e = mItems.elements(); e.hasMoreElements();) {
116                        DBWhereIFace item = (DBWhereIFace) e.nextElement();
117                        if (item.isDragOver()) {
118                                return inx + 1;
119                        }
120                        inx++;
121                }
122                return -1;
123        }
124
125        /**
126         * Adds an item to the model, the parent attr MUST be set before adding item
127         * 
128         * @param aItem
129         *            item to be added, it finds the insert point via the lasted
130         *            dragged object if that can't be found then it adds it as the
131         *            last child of the parent.
132         * @return the index it was added at
133         */
134        public int add(DBWhereIFace aItem) {
135                int inx;
136                if (mItems.size() == 0) {
137                        inx = 0;
138                } else {
139                        // check to make the parent is set
140                        DBWhereOperator parent = aItem.getParent();
141                        if (parent == null)
142                                return -1;
143
144                        inx = getInsertionIndexFromDrag();
145                        if (inx == -1) {
146                                inx = mItems.indexOf(parent.getClosure());
147                                if (inx == -1)
148                                        return -1;
149                                inx--; // back up one slot from the closure
150                        }
151                }
152                add(aItem, inx);
153                return inx;
154        }
155
156        /**
157         * Adds an item to the model at a specified index, the parent attr MUST be
158         * set before adding item
159         * 
160         * @param aItem
161         *            item to be added, it finds the insert point via the lasted
162         *            dragged object if that can't be found then it adds it as the
163         *            last child of the parent.
164         * @param aInx
165         *            index as to where it will be added
166         */
167        public void add(DBWhereIFace aItem, int aInx) {
168                mItems.add(aInx, aItem);
169                if (aItem instanceof DBWhereOperator) {
170                        mItems.add(aInx + 1, ((DBWhereOperator) aItem).getClosure());
171                }
172                if (mRootObj == null && aItem.getParent() == null) {
173                        mRootObj = aItem;
174                }
175                fireContentsChanged(this, 0, mItems.size() - 1);
176        }
177
178        /**
179         * Remove item from list, if operator, remove its closure and all the
180         * children too
181         * 
182         * @param aObj
183         *            item to be removed
184         */
185        public void remove(DBWhereIFace aObj) {
186                int startInx = mItems.indexOf(aObj);
187                if (aObj instanceof DBWhereOperator) {
188                        DBWhereIFace closureItem = ((DBWhereOperator) aObj).getClosure();
189                        DBWhereIFace delItem = null;
190                        while (delItem != closureItem) {
191                                delItem = (DBWhereIFace) mItems.elementAt(startInx);
192                                mItems.remove(delItem);
193                        }
194                } else {
195                        mItems.remove(aObj);
196                }
197
198                if (mItems.size() == 0) {
199                        mRootObj = null;
200                }
201
202                fireContentsChanged();
203        }
204
205        /**
206         * Expose the ability to send the UI a notification the model has been
207         * updated
208         * 
209         */
210        public void fireContentsChanged() {
211                fireContentsChanged(this, 0, mItems.size() - 1);
212        }
213
214        /**
215         * Fills QueryDef from Model
216         */
217        public void fillQueryDef(DBQueryDef aQueryDef) {
218                DBWhereIFace whereObj = null;
219                if (mRootObj != null) {
220                        if (mRootObj instanceof DBWhereOperator) {
221                                if (((DBWhereOperator) mRootObj).getNumChildern() > 0) {
222                                        whereObj = mRootObj;
223                                }
224                        } else {
225                                whereObj = mRootObj;
226                        }
227                }
228                aQueryDef.setWhere(whereObj);
229        }
230
231}