View Javadoc

1   /* (c) Copyright 2003 Caleigo AB, All rights reserved. 
2    * 
3    * This library is free software; you can redistribute it and/or
4    * modify it under the terms of the GNU Lesser General Public
5    * License as published by the Free Software Foundation; either
6    * version 2.1 of the License, or (at your option) any later version.
7    * 
8    * This library is distributed in the hope that it will be useful,
9    * but WITHOUT ANY WARRANTY; without even the implied warranty of
10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   * Lesser General Public License for more details.
12   * 
13   * You should have received a copy of the GNU Lesser General Public
14   * License along with this library; if not, write to the Free Software
15   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16   *  
17   */
18  
19  package org.caleigo.core;
20  
21  
22  import java.util.*;
23  import java.text.*;
24  
25  import org.caleigo.core.exception.*;
26  
27  /*** The EntityCollator class defines how entities of a defined type should
28   * be ordered so that the order information can be relayed. The EntityCollator
29   * also implements the Comparartor class making it possible to sort IEntity
30   * objects of the defined type in an ISelector or a java.util.list object.  
31   *
32   * @author  Dennis Zikovic
33   * @version 1.00
34   *
35   *//* 
36   *
37   * WHEN        WHO               WHY & WHAT
38   * -----------------------------------------------------------------------------
39   * 2001-12-14  Dennis Zikovic    Creation
40   */
41  public class EntityCollator implements Comparator, java.io.Serializable
42  {
43      // Constants ---------------------------------------------------------------
44      
45      // Data members ------------------------------------------------------------
46      private List mFieldCollatorList;
47      private IEntityDescriptor mEntityDescriptor;
48      
49      // Constructors ------------------------------------------------------------
50      
51      /*** Creates new EntityCollator
52       */
53      public EntityCollator(IEntityDescriptor descriptor) 
54      {
55          mFieldCollatorList = new ArrayList();
56          mEntityDescriptor = descriptor;
57      }
58      
59      public EntityCollator(IEntityDescriptor descriptor, EntityCollator collator) 
60      {
61          this(descriptor);
62          for(int j=0; j<collator.getFieldCount(); j++)
63              if(mEntityDescriptor.contains(collator.getFieldCollator(j).getFieldDescriptor()))
64                  this.addCollationField(collator.getFieldCollator(j));
65      }
66          
67      // Comparator implementation -----------------------------------------------
68      public int compare(java.lang.Object obj1, java.lang.Object obj2)
69      {
70          // Fast handling of single field collation as it normally will be the 
71          // most common case. Also break and return zero if no field collators.
72          if(mFieldCollatorList.size()==1)
73              return ((FieldCollator)mFieldCollatorList.get(0)).compare(obj1, obj2);
74          else if(mFieldCollatorList.size()==0)
75              return 0;
76          
77          // Compare multiple fielsd using iteration.
78          int compare = 0;
79          for(int j=0; compare==0 && j<mFieldCollatorList.size(); j++)
80              compare = ((FieldCollator)mFieldCollatorList.get(j)).compare(obj1, obj2);
81          return compare;
82      }
83      
84      public boolean equals(Object data1, Object data2)
85      {
86          return this.compare(data1, data2)==0;
87      }
88      
89      // Action methods ----------------------------------------------------------
90      
91      public void setCollationField(IFieldDescriptor fieldDescriptor)
92      {
93          this.clearCollatorFields();
94          this.addCollationField(new FieldCollator(fieldDescriptor));
95      }
96      
97      public void setCollationField(IFieldDescriptor fieldDescriptor, boolean ascending)
98      {
99          this.clearCollatorFields();
100         this.addCollationField(new FieldCollator(fieldDescriptor, ascending));
101     }
102     
103     public void addCollationField(IFieldDescriptor fieldDescriptor)
104     {
105         this.addCollationField(new FieldCollator(fieldDescriptor));
106     }
107     
108     public void addCollationField(IFieldDescriptor fieldDescriptor, boolean ascending)
109     {
110         this.addCollationField(new FieldCollator(fieldDescriptor, ascending));
111     }
112     
113     public void addCollationField(FieldCollator collator)
114     {
115         if(mEntityDescriptor.contains(collator.getFieldDescriptor()))
116             mFieldCollatorList.add(collator);
117         else
118             throw new InvalidFieldException("Field is not part the collation entity.");
119     }
120     
121     public void clearCollatorFields()
122     {
123         mFieldCollatorList.clear();
124     }
125     
126     // Access methods ----------------------------------------------------------
127     public IEntityDescriptor getEntityDescriptor()
128     {
129         return mEntityDescriptor;
130     }
131     
132     public int getFieldCount()
133     {
134         return mFieldCollatorList.size();
135     }
136     
137     public FieldCollator getFieldCollator(int index)
138     {
139         return (FieldCollator)mFieldCollatorList.get(index);
140     }
141     
142     public Iterator getFieldCollators()
143     {
144         if(mFieldCollatorList!=null)
145             return mFieldCollatorList.iterator();
146         else
147             return null;
148     }
149     
150     // Help methods ------------------------------------------------------------
151     
152     // Nested classes ----------------------------------------------------------
153     
154     public static class FieldCollator implements Comparator, java.io.Serializable
155     {
156         // Data members --------------------------------------------------------
157         private IFieldDescriptor mFieldDescriptor;
158         private boolean mIsAscending;
159         private Collator mStringCollator;
160         
161         // Constructors --------------------------------------------------------
162         public FieldCollator(IFieldDescriptor fieldDescriptor)
163         {
164             this(fieldDescriptor, true, null);
165         }
166 
167         public FieldCollator(IFieldDescriptor fieldDescriptor, boolean ascending)
168         {
169             this(fieldDescriptor, ascending, null);
170         }
171         
172         /*** Note that the string collator will only be accepted if the fields
173          * data class is String.
174          */
175         public FieldCollator(IFieldDescriptor fieldDescriptor, boolean ascending, Collator stringCollator)
176         {
177             mFieldDescriptor = fieldDescriptor;
178             mIsAscending = ascending;
179             if(fieldDescriptor.getDataType().getDataClass().equals(String.class))
180                 mStringCollator = stringCollator;
181             else
182                 mStringCollator = null;
183         }
184         
185         // Comparator implementation -------------------------------------------
186         
187         /*** Note that the compare method in the FieldCollator object is 
188          * required to handle both the data type of the field and entity
189          * objects as parameter values. If the parameters are IEntity objects
190          * then the field collator chould extract the field data it is designed
191          * to collate and use that data in itīs comparison.
192          */
193         public int compare(Object obj1, Object obj2)
194         {
195             // Extract field data if parameters are IEntity objects.
196             if(obj1 instanceof IEntity)
197                 obj1 = ((IEntity)obj1).getData(mFieldDescriptor);
198             if(obj2 instanceof IEntity)
199                 obj2 = ((IEntity)obj2).getData(mFieldDescriptor);
200                 
201             // Compare values and consider ascending/descending order.
202             if(mStringCollator!=null)
203             {
204                 if(mIsAscending)
205                     return mStringCollator.compare(obj1, obj2);
206                 else
207                     return mStringCollator.compare(obj2, obj1);
208             }
209             else
210             {
211                 if(mIsAscending)
212                     return mFieldDescriptor.getDataType().compare(obj1, obj2);
213                 else
214                     return mFieldDescriptor.getDataType().compare(obj2, obj1);
215             }
216         }
217 
218         public boolean equals(Object data1, Object data2)
219         {
220             return this.compare(data1, data2)==0;
221         }
222         
223         // Access methods ------------------------------------------------------
224         public IFieldDescriptor getFieldDescriptor()
225         {
226             return mFieldDescriptor;
227         }
228         
229         public boolean isAscending()
230         {
231             return mIsAscending;
232         }        
233         
234         public Collator getStringCollator()
235         {
236             return mStringCollator;
237         }
238     }
239 }