2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shale.usecases.rolodex;
19  
20  import java.io.IOException;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.SortedSet;
26  import java.util.TreeSet;
27  
28  import javax.faces.model.SelectItem;
29  
30  import org.apache.commons.digester.Digester;
31  import org.xml.sax.InputSource;
32  import org.xml.sax.SAXException;
33  
34  /***
35   * <p>
36   * Data Access Object for the roledex use case.
37   * </p>
38   */
39  public class RolodexDao {
40  
41      /***
42       * <p>
43       * Mock datastore.
44       * </p>
45       */
46      private Collection entityDataStore = null;
47  
48      private Collection stateDataStore = null;
49  
50      private Collection countryDataStore = null;
51  
52      /***
53       * <p>
54       * The constructor loads some default data.
55       * </p>
56       */
57      public RolodexDao() {
58          GenericComparator comparator = new GenericComparator();
59          comparator.setSortBy("sortName, name");
60  
61          entityDataStore = new TreeSet(comparator);
62  
63          comparator = new GenericComparator();
64          comparator.setSortBy("value");
65  
66          stateDataStore = new TreeSet(comparator);
67          countryDataStore = new TreeSet(comparator);
68          loadStates();
69      }
70  
71      /***
72       * <p>
73       * Tab indexes for the rolodex. Each sub array represents the starting and
74       * ending character index.
75       * </p>
76       */
77      public final static char[][] TAB_INDEX = { { 'A', 'B' }, { 'C', 'D' },
78              { 'E', 'F' }, { 'G', 'H' }, { 'I', 'J' }, { 'K', 'L' },
79              { 'M', 'N' }, { 'O', 'P' }, { 'Q', 'Z' } };
80  
81      /***
82       * <p>
83       * Returns a list of <code>SelectItem</code> that will be used to build
84       * the links.
85       * </p>
86       */
87      public List getTabs() {
88          List tabs = new ArrayList();
89          SelectItem tab = null;
90  
91          for (int i = 0; i < TAB_INDEX.length; i++) {
92              tab = new SelectItem();
93              tab.setLabel(TAB_INDEX[i][0] + "-" + TAB_INDEX[i][1]);
94              tab.setValue(new Integer(i));
95              tabs.add(tab);
96          }
97  
98          return tabs;
99      }
100 
101     /***
102      * <p>
103      * Saves a {@link Contact} to the mock data store.
104      * </p>
105      */
106     public int saveContact(Contact entity) {
107         entityDataStore.add(entity);
108         return findTabForContact(entity);
109     }
110 
111     /***
112      * <p>This function will find the tabIndex that the {@link Contact}
113      * will be located on.  It will default to the first page.</p>
114      */
115     public int findTabForContact(Contact contact) {
116         for (int i = 0; i < TAB_INDEX.length; i++) {
117            if ((contact.getTabIndex() >= TAB_INDEX[i][0]) && 
118                (contact.getTabIndex() <= TAB_INDEX[i][1]))  
119               return i;    
120         }
121         
122         return 0;
123     }
124     
125     
126     /***
127      * <p>
128      * Retuns a subset of contacts within the <code>index</code> of a a tab
129      * defined by <code>TAB_INDEX</code> from the mock data store. If this was
130      * a RDBMS data store, the contacts returned might be a "ghost" object
131      * meaning that maybe only the <code>name</code> attribute would be
132      * populated.
133      * </p>
134      */
135     public List findContactsForTab(int index) {
136         List contacts = new ArrayList();
137 
138         Contact low = new Contact();
139         Contact high = new Contact();
140 
141         StringBuffer key = new StringBuffer();
142         
143         key.append(TAB_INDEX[index][0]);
144         low.setName(key.toString());
145 
146         key.setLength(0);
147         key.append(TAB_INDEX[index][1]);
148         for (int i = 0; i < 50; i++)
149            key.append('z');
150 
151         high.setName(key.toString());
152 
153         SortedSet subSet = ((SortedSet) entityDataStore).subSet(low, high);
154         Iterator si = subSet.iterator();
155         while (si.hasNext())
156             contacts.add(si.next());
157 
158         return contacts;
159     }
160 
161     /***
162      * <p>
163      * Removes the contact from the mock data store.
164      * </p>
165      */
166     public void deleteContact(Contact entity) {
167         entityDataStore.remove(entity);
168     }
169 
170     /***
171      * <p>
172      * Loads the {@link State} codes and contacts from an XML data source. The
173      * <code>stateDataStore</code> set will hold the states where the
174      * <code>countryDataStore</code> set will hold the countries. The target type of
175      * these collections will be SelectItem.  The contacts are held in the 
176      * <code>entityDataStore</code> set.
177      * </p>
178      */
179     public void loadStates() {
180 
181         Object config = new Object() {
182             public void addState(State state) {
183                 SelectItem item = null;
184                 // add a blank option
185                 if (stateDataStore.size() == 0) {
186                     item = new SelectItem();
187                     item.setLabel("");
188                     item.setValue("");
189                     stateDataStore.add(item);
190                 }
191                 
192                 item = new SelectItem();
193                 item.setLabel(state.getState());
194                 item.setValue(state.getAbbrState());
195                 stateDataStore.add(item);
196 
197                 item = new SelectItem();
198                 item.setLabel(state.getCountry());
199                 item.setValue(state.getAbbrCountry());
200                 countryDataStore.add(item);
201             }
202 
203             public void addContact(Contact contact) {
204                 saveContact(contact);
205             }
206         };
207 
208         Digester digester = new Digester();
209         digester.setValidating(false);
210         digester.setUseContextClassLoader(true);
211 
212         digester.addObjectCreate("dex/states/state",
213                 org.apache.shale.usecases.rolodex.State.class);
214         digester.addSetProperties("dex/states/state");
215         digester.addSetNext("dex/states/state", "addState",
216                 "org.apache.shale.usecases.rolodex.State");
217 
218         digester.addObjectCreate("dex/contacts/contact/residentialAddress",
219                 org.apache.shale.usecases.rolodex.Address.class);
220         digester.addCallMethod(
221                 "dex/contacts/contact/residentialAddress/street1",
222                 "setStreet1", 0);
223         digester.addCallMethod(
224                 "dex/contacts/contact/residentialAddress/street2",
225                 "setStreet2", 0);
226         digester.addCallMethod("dex/contacts/contact/residentialAddress/city",
227                 "setCity", 0);
228         digester.addCallMethod("dex/contacts/contact/residentialAddress/state",
229                 "setState", 0);
230         digester.addCallMethod("dex/contacts/contact/residentialAddress/zip",
231                 "setZipAsString", 0);
232         digester.addCallMethod(
233                 "dex/contacts/contact/residentialAddress/province",
234                 "setProvince", 0);
235         digester.addCallMethod(
236                 "dex/contacts/contact/residentialAddress/country",
237                 "setCountry", 0);
238         digester.addSetNext("dex/contacts/contact/residentialAddress",
239                 "setResidentialAddress",
240                 "org.apache.shale.usecases.rolodex.Address");
241 
242         digester.addObjectCreate("dex/contacts/contact/businessAddress",
243                 org.apache.shale.usecases.rolodex.Address.class);
244         digester.addCallMethod("dex/contacts/contact/businessAddress/street1",
245                 "setStreet1", 0);
246         digester.addCallMethod("dex/contacts/contact/businessAddress/street2",
247                 "setStreet2", 0);
248         digester.addCallMethod("dex/contacts/contact/businessAddress/city",
249                 "setCity", 0);
250         digester.addCallMethod("dex/contacts/contact/businessAddress/state",
251                 "setState", 0);
252         digester.addCallMethod("dex/contacts/contact/businessAddress/zip",
253                 "setZipAsString", 0);
254         digester.addCallMethod("dex/contacts/contact/businessAddress/province",
255                 "setProvince", 0);
256         digester.addCallMethod("dex/contacts/contact/businessAddress/country",
257                 "setCountry", 0);
258         digester.addSetNext("dex/contacts/contact/businessAddress",
259                 "setBusinessAddress",
260                 "org.apache.shale.usecases.rolodex.Address");
261 
262         digester.addObjectCreate("dex/contacts/contact",
263                 org.apache.shale.usecases.rolodex.Contact.class);
264         digester.addCallMethod("dex/contacts/contact/name", "setName", 0);
265         digester.addCallMethod("dex/contacts/contact/email", "setEmail", 0);
266         digester.addCallMethod("dex/contacts/contact/residentialPhone",
267                 "setResidentialPhone", 0);
268         digester.addCallMethod("dex/contacts/contact/businessPhone",
269                 "setBusinessPhone", 0);
270         digester.addSetNext("dex/contacts/contact", "addContact",
271                 "org.apache.shale.usecases.rolodex.Contact");
272 
273         digester.push(config);
274 
275         ClassLoader classloader = Thread.currentThread()
276                 .getContextClassLoader();
277         if (classloader == null)
278             classloader = config.getClass().getClassLoader();
279 
280         InputSource in = new InputSource(
281                 classloader
282                         .getResourceAsStream("org/apache/shale/usecases/rolodex/dex.xml"));
283 
284         try {
285             digester.parse(in);
286         } catch (IOException e) {
287             e.printStackTrace();
288         } catch (SAXException e) {
289             e.printStackTrace();
290         }
291 
292     }
293 
294     /***
295      * <p>
296      * Returns an array of states used to populate a select list. The target
297      * type is an array of SelectItem.
298      * </p>
299      */
300     public SelectItem[] getStates() {
301         SelectItem[] states = new SelectItem[stateDataStore.size()];
302         stateDataStore.toArray(states);
303         return states;
304     }
305 
306     /***
307      * <p>
308      * Returns an array of countries used to populate a select list. The target
309      * type is an array of SelectItem.
310      * </p>
311      */
312     public SelectItem[] getCountries() {
313         SelectItem[] countries = new SelectItem[countryDataStore.size()];
314         countryDataStore.toArray(countries);
315         return countries;
316     }
317 
318     /***
319      * <p>
320      * Returns the latest copy of the {@link Contact} by primary key.
321      * </p>
322      * 
323      * @param name
324      *            contact name that uniquely identifies a Contact.
325      * @return the target, fully populated {@link Contact}
326      */
327     public Contact findContact(String name) {
328         Contact sarg = new Contact();
329         sarg.setName(name);
330         SortedSet subSet = ((TreeSet) entityDataStore).tailSet(sarg);
331         return (Contact) subSet.first();
332     }
333 
334 }