View Javadoc

1   /*
2    * Created by IntelliJ IDEA.
3    * User: Administrator
4    * Date: 28/02/2002
5    * Time: 15:15:42
6    * To change template for new class use
7    * Code Style | Class Templates options (Tools | IDE Options).
8    */
9   package com.atlassian.core.ofbiz.util;
10  
11  import com.atlassian.core.ofbiz.CoreFactory;
12  import com.atlassian.core.util.DateUtils;
13  import com.atlassian.core.util.ObjectUtils;
14  
15  import org.ofbiz.core.entity.EntityExpr;
16  import org.ofbiz.core.entity.EntityOperator;
17  import org.ofbiz.core.entity.GenericEntityException;
18  import org.ofbiz.core.entity.GenericValue;
19  
20  import java.sql.Timestamp;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.HashMap;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Map;
27  
28  public class EntityUtils
29  {
30      private static final EntityOperator[] entityOperators = { EntityOperator.EQUALS, EntityOperator.NOT_EQUAL, EntityOperator.LESS_THAN, EntityOperator.GREATER_THAN, EntityOperator.LESS_THAN_EQUAL_TO, EntityOperator.GREATER_THAN_EQUAL_TO, EntityOperator.IN, EntityOperator.BETWEEN, EntityOperator.NOT, EntityOperator.AND, EntityOperator.OR };
31  
32      /**
33       * Small utility method to get an entity operator from it's code
34       */
35      public static EntityOperator getOperator(final String code)
36      {
37          for (int i = 0; i < entityOperators.length; i++)
38          {
39              final EntityOperator operator = entityOperators[i];
40              if (operator.toString().trim().equals(code.trim()))
41              {
42                  return operator;
43              }
44          }
45          return null;
46      }
47  
48      /**
49       * Create a new entity.
50       *
51       * If there is no "id" in the parameter list, one is created using the entity sequence
52       */
53      public static GenericValue createValue(final String entity, final Map paramMap) throws GenericEntityException
54      {
55          final Map params = (paramMap == null) ? new HashMap() : new HashMap(paramMap);
56  
57          if (params.get("id") == null)
58          {
59              final Long id = CoreFactory.getGenericDelegator().getNextSeqId(entity);
60              params.put("id", id);
61          }
62  
63          final GenericValue v = CoreFactory.getGenericDelegator().makeValue(entity, params);
64          v.create();
65          return v;
66      }
67  
68      /**
69       * Compare two GenericValues based on their content.
70       *
71       * This method will check the keys and values of both GenericValues.
72       *
73       * There is only a single difference between this method and GenericValue.equals(gv2),
74       * that is that if one GV has no key of a certain type, and the other has a null value
75       * for that key, they are still deemed to be identical (as GenericValue.get(key)
76       * always returns null if the key exists or not).
77       *
78       * @return true if the issues are the same, false if they are different
79       */
80      public static boolean identical(final GenericValue v1, final GenericValue v2)
81      {
82          if ((v1 == null) && (v2 == null))
83          {
84              return true;
85          }
86          if ((v1 == null) || (v2 == null))
87          {
88              return false;
89          }
90  
91          if (!v1.getEntityName().equals(v2.getEntityName()))
92          {
93              return false;
94          }
95  
96          // get the keys of v1, make sure they are equal in v2
97          for (final Iterator iterator = v1.getAllKeys().iterator(); iterator.hasNext();)
98          {
99              final String key = (String) iterator.next();
100 
101             if ((v1.get(key) == null) && (v2.get(key) == null))
102             {
103                 continue;
104             }
105             if ((v1.get(key) == null) && (v2.get(key) != null))
106             {
107                 return false;
108             }
109             else
110             {
111                 // handle timestamps specially due to precision
112                 if ((v1.get(key) instanceof Timestamp) && (v2.get(key) instanceof Timestamp))
113                 {
114                     final Timestamp t1 = (Timestamp) v1.get(key);
115                     final Timestamp t2 = (Timestamp) v2.get(key);
116                     if (!DateUtils.equalTimestamps(t1, t2))
117                     {
118                         return false;
119                     }
120                 }
121                 else if (!v1.get(key).equals(v2.get(key)))
122                 {
123                     return false;
124                 }
125             }
126         }
127 
128         // if they keys aren't the same, loop through v2
129         final Collection uncheckedKeys = new ArrayList(v2.getAllKeys());
130         uncheckedKeys.removeAll(v1.getAllKeys());
131 
132         // for the unchecked keys in v2, if they have values in v2, then the GVs are not identical
133         if (uncheckedKeys.size() > 0)
134         {
135             for (final Iterator iterator = uncheckedKeys.iterator(); iterator.hasNext();)
136             {
137                 final String key = (String) iterator.next();
138                 if (v2.get(key) == null)
139                 {
140                     continue;
141                 }
142                 else
143                 {
144                     return false;
145                 }
146             }
147         }
148         return true;
149     }
150 
151     /**
152      * Checks if a collection of entities contains an identical entity
153      * to the one provided.
154      *
155      * @param entities The list of entities to search
156      * @param entity The entity to search for and compare to
157      * @return The matching entity, or null if no matching entity is found
158      */
159     public static boolean contains(final Collection entities, final GenericValue entity)
160     {
161         for (final Iterator iterator = entities.iterator(); iterator.hasNext();)
162         {
163             final GenericValue gv = (GenericValue) iterator.next();
164 
165             if (identical(gv, entity))
166             {
167                 return true;
168             }
169         }
170         return false;
171     }
172 
173     /**
174      * This method is analagous to the OFBiz EntityUtil.filterByAnd method
175      * except that theirs does not filter on GT, GTE, LT, LTE yet.
176      *
177      * @param values A collection of GenericValues
178      * @param exprs The expressions that must validate to true
179      * @return Collection of GenericValues that match the expression list
180      */
181     public static List filterByAnd(final List values, final List exprs)
182     {
183         if (values == null)
184         {
185             return null;
186         }
187         if ((exprs == null) || (exprs.size() == 0))
188         {
189             return values;
190         }
191 
192         final List result = new ArrayList();
193 
194         for (final Iterator iterator = values.iterator(); iterator.hasNext();)
195         {
196             final GenericValue value = (GenericValue) iterator.next();
197             boolean include = true;
198 
199             for (final Iterator exprIter = exprs.iterator(); exprIter.hasNext();)
200             {
201                 final EntityExpr expr = (EntityExpr) exprIter.next();
202                 final Object lhs = value.get((String) expr.getLhs());
203                 final Object rhs = expr.getRhs();
204 
205                 if (EntityOperator.EQUALS.equals(expr.getOperator()))
206                 {
207                     //if the field named by lhs is not equal to rhs value, constraint fails
208                     include = ObjectUtils.isIdentical(lhs, rhs);
209 
210                     if (!include)
211                     {
212                         break;
213                     }
214                 }
215                 else if (EntityOperator.NOT_EQUAL.equals(expr.getOperator()))
216                 {
217                     include = ObjectUtils.isDifferent(lhs, rhs);
218 
219                     if (!include)
220                     {
221                         break;
222                     }
223                 }
224                 else if (EntityOperator.GREATER_THAN.equals(expr.getOperator()) || EntityOperator.GREATER_THAN_EQUAL_TO.equals(expr.getOperator()) || EntityOperator.LESS_THAN.equals(expr.getOperator()) || EntityOperator.LESS_THAN_EQUAL_TO.equals(expr.getOperator()))
225                 {
226                     if ((rhs != null) && (lhs != null) && (rhs instanceof Comparable))
227                     {
228                         final Comparable rhsComp = (Comparable) rhs;
229                         final Comparable lhsComp = (Comparable) lhs;
230 
231                         final int comparison = lhsComp.compareTo(rhsComp);
232 
233                         if ((comparison <= 0) && EntityOperator.LESS_THAN_EQUAL_TO.equals(expr.getOperator()))
234                         {
235                             include = true;
236                         }
237                         else if ((comparison < 0) && EntityOperator.LESS_THAN.equals(expr.getOperator()))
238                         {
239                             include = true;
240                         }
241                         else if ((comparison >= 0) && EntityOperator.GREATER_THAN_EQUAL_TO.equals(expr.getOperator()))
242                         {
243                             include = true;
244                         }
245                         else if ((comparison > 0) && EntityOperator.GREATER_THAN.equals(expr.getOperator()))
246                         {
247                             include = true;
248                         }
249                         else
250                         {
251                             include = false;
252                             break;
253                         }
254                     }
255                     else
256                     {
257                         throw new IllegalArgumentException(
258                             "Operation " + expr.getOperator().getCode() + " is not yet supported by filterByAnd with objects that do not implement Comparable");
259                     }
260                 }
261                 else
262                 {
263                     throw new IllegalArgumentException("Operation " + expr.getOperator().getCode() + " is not yet supported by filterByAnd");
264                 }
265             }
266 
267             if (include)
268             {
269                 result.add(value);
270             }
271         }
272         return result;
273     }
274 
275     /**
276      * Calculate a new entity ID (by basically taking one more than the max integer that exists).
277      * If there are string IDs here, they will not be affected.
278      */
279     public static synchronized String getNextStringId(final String entityName) throws GenericEntityException
280     {
281         long maxID = 1;
282 
283         for (final Iterator iterator = CoreFactory.getGenericDelegator().findAll(entityName).iterator(); iterator.hasNext();)
284         {
285             final GenericValue entity = (GenericValue) iterator.next();
286             try
287             {
288                 final long entityId = Long.parseLong(entity.getString("id"));
289                 if (entityId >= maxID)
290                 {
291                     maxID = entityId + 1;
292                 }
293             }
294             catch (final NumberFormatException nfe)
295             {
296                 // ignore - we don't care about String constant IDs
297             }
298         }
299         return Long.toString(maxID);
300     }
301 }