Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/objectstyle/cayenne/access/util/BatchQueryUtils.java


1   /* ====================================================================
2    *
3    * The ObjectStyle Group Software License, Version 1.0
4    *
5    * Copyright (c) 2002-2003 The ObjectStyle Group
6    * and individual authors of the software.  All rights reserved.
7    *
8    * Redistribution and use in source and binary forms, with or without
9    * modification, are permitted provided that the following conditions
10   * are met:
11   *
12   * 1. Redistributions of source code must retain the above copyright
13   *    notice, this list of conditions and the following disclaimer.
14   *
15   * 2. Redistributions in binary form must reproduce the above copyright
16   *    notice, this list of conditions and the following disclaimer in
17   *    the documentation and/or other materials provided with the
18   *    distribution.
19   *
20   * 3. The end-user documentation included with the redistribution, if
21   *    any, must include the following acknowlegement:
22   *       "This product includes software developed by the
23   *        ObjectStyle Group (http://objectstyle.org/)."
24   *    Alternately, this acknowlegement may appear in the software itself,
25   *    if and wherever such third-party acknowlegements normally appear.
26   *
27   * 4. The names "ObjectStyle Group" and "Cayenne"
28   *    must not be used to endorse or promote products derived
29   *    from this software without prior written permission. For written
30   *    permission, please contact andrus@objectstyle.org.
31   *
32   * 5. Products derived from this software may not be called "ObjectStyle"
33   *    nor may "ObjectStyle" appear in their names without prior written
34   *    permission of the ObjectStyle Group.
35   *
36   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39   * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
40   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47   * SUCH DAMAGE.
48   * ====================================================================
49   *
50   * This software consists of voluntary contributions made by many
51   * individuals on behalf of the ObjectStyle Group.  For more
52   * information on the ObjectStyle Group, please see
53   * <http://objectstyle.org/>.
54   *
55   */
56  
57  package org.objectstyle.cayenne.access.util;
58  
59  import java.sql.Types;
60  import java.util.Collection;
61  import java.util.Collections;
62  import java.util.HashMap;
63  import java.util.Iterator;
64  import java.util.List;
65  import java.util.Map;
66  
67  import org.apache.commons.lang.builder.HashCodeBuilder;
68  import org.objectstyle.cayenne.DataObject;
69  import org.objectstyle.cayenne.map.DbAttribute;
70  import org.objectstyle.cayenne.map.DbAttributePair;
71  import org.objectstyle.cayenne.map.DbRelationship;
72  import org.objectstyle.cayenne.map.Entity;
73  import org.objectstyle.cayenne.map.ObjAttribute;
74  import org.objectstyle.cayenne.map.ObjEntity;
75  import org.objectstyle.cayenne.map.ObjRelationship;
76  import org.objectstyle.cayenne.query.BatchQuery;
77  import org.objectstyle.cayenne.query.InsertBatchQuery;
78  import org.objectstyle.cayenne.query.UpdateBatchQuery;
79  
80  /**
81   * Collection of utility methods to work with BatchQueries.
82   *
83   * @author Andriy Shapochka
84   */
85  
86  public class BatchQueryUtils {
87  
88    private BatchQueryUtils() {
89    }
90  
91    /**
92     * Utility method that returns <code>true</code> if 
93     * the query will update at least one BLOB or CLOB DbAttribute.
94     */
95    public static boolean updatesLOBColumns(BatchQuery query) {
96      boolean isInsert = query instanceof InsertBatchQuery;
97      boolean isUpdate = query instanceof UpdateBatchQuery;
98  
99      if (!isInsert && !isUpdate) {
100       return false;
101     }
102 
103     List updatedAttributes =
104       (isInsert)
105         ? query.getDbAttributes()
106         : ((UpdateBatchQuery) query).getUpdatedDbAttributes();
107 
108     Iterator it = updatedAttributes.iterator();
109     while (it.hasNext()) {
110       int type = ((DbAttribute) it.next()).getType();
111       if (type == Types.CLOB || type == Types.BLOB) {
112         return true;
113       }
114     }
115     
116     return false;
117   }
118 
119   public static Map buildSnapshotForUpdate(DataObject o) {
120     Map committedSnapshot = o.getCommittedSnapshot();
121     Map currentSnapshot = o.getCurrentSnapshot();
122     Map snapshot = null;
123 
124     if (committedSnapshot == null || committedSnapshot.isEmpty()) {
125       snapshot = Collections.unmodifiableMap(currentSnapshot);
126       return snapshot;
127     } else
128       snapshot = new HashMap(currentSnapshot.size());
129 
130     Iterator it = currentSnapshot.entrySet().iterator();
131     while (it.hasNext()) {
132       Map.Entry entry = (Map.Entry) it.next();
133       String attrName = (String) entry.getKey();
134       Object newValue = entry.getValue();
135       // if snapshot exists, compare old values and new values,
136       // only add attribute to the update clause if the value has changed
137       Object oldValue = committedSnapshot.get(attrName);
138       if (valueChanged(oldValue, newValue))
139         snapshot.put(attrName, newValue);
140     }
141 
142     // original snapshot can have extra keys that are missing in current snapshot
143     // process those
144     Iterator origit = committedSnapshot.entrySet().iterator();
145     while (origit.hasNext()) {
146       Map.Entry entry = (Map.Entry) origit.next();
147       String attrName = (String) entry.getKey();
148       Object oldValue = entry.getValue();
149       if (oldValue == null || currentSnapshot.containsKey(attrName))
150         continue;
151       snapshot.put(attrName, null);
152     }
153 
154     return Collections.unmodifiableMap(snapshot);
155   }
156 
157   public static int hashCode(Collection c) {
158     HashCodeBuilder builder = new HashCodeBuilder();
159     for (Iterator i = c.iterator(); i.hasNext();)
160       builder.append(i.next());
161     return builder.toHashCode();
162   }
163 
164   public static Map buildFlattenedSnapshot(
165     Map sourceId,
166     Map destinationId,
167     DbRelationship firstRelationship,
168     DbRelationship secondRelationship) {
169     Map snapshot = new HashMap(sourceId.size() + destinationId.size());
170     List joins = firstRelationship.getJoins();
171     for (int i = 0, numJoins = joins.size(); i < numJoins; i++) {
172       DbAttributePair thisJoin = (DbAttributePair) joins.get(i);
173       DbAttribute sourceAttribute = thisJoin.getSource();
174       DbAttribute targetAttribute = thisJoin.getTarget();
175       snapshot.put(
176         targetAttribute.getName(),
177         sourceId.get(sourceAttribute.getName()));
178     }
179 
180     joins = secondRelationship.getJoins();
181     for (int i = 0, numJoins = joins.size(); i < numJoins; i++) {
182       DbAttributePair thisJoin = (DbAttributePair) joins.get(i);
183       DbAttribute sourceAttribute = thisJoin.getSource();
184       DbAttribute targetAttribute = thisJoin.getTarget();
185       snapshot.put(
186         sourceAttribute.getName(),
187         destinationId.get(targetAttribute.getName()));
188     }
189 
190     return snapshot;
191   }
192 
193   public static Map buildSnapshotForInsert(
194     ObjEntity ent,
195     DataObject o,
196     DbRelationship masterDependentRel) {
197     boolean isMasterDbEntity = (masterDependentRel == null);
198     Map map = new HashMap();
199 
200     Map attrMap = ent.getAttributeMap();
201     Iterator it = attrMap.keySet().iterator();
202     while (it.hasNext()) {
203       String attrName = (String) it.next();
204       ObjAttribute objAttr = (ObjAttribute) attrMap.get(attrName);
205 
206       if (isMasterDbEntity && !objAttr.isCompound()) {
207         map.put(
208           objAttr.getDbAttributePath(),
209           o.readPropertyDirectly(attrName));
210       } else if (!isMasterDbEntity && objAttr.isCompound()) {
211         DbAttribute dbAttr = objAttr.getDbAttribute();
212         if (dbAttr.getEntity() == masterDependentRel.getTargetEntity())
213           map.put(dbAttr.getName(), o.readPropertyDirectly(attrName));
214       }
215     }
216 
217     if (isMasterDbEntity) {
218       Map relMap = ent.getRelationshipMap();
219       Iterator itr = relMap.keySet().iterator();
220       while (itr.hasNext()) {
221         String relName = (String) itr.next();
222         ObjRelationship rel = (ObjRelationship) relMap.get(relName);
223         // to-many will be handled on the other side
224         if (rel.isToMany())
225           continue;
226         if (rel.isToDependentEntity())
227           continue;
228         DataObject target =
229           (DataObject) o.readPropertyDirectly(relName);
230         if (target == null)
231           continue;
232         DbRelationship dbRel =
233           (DbRelationship) rel.getDbRelationships().get(0);
234         Map idParts = target.getObjectId().getIdSnapshot();
235         // this may happen in uncommitted objects
236         if (idParts == null)
237           continue;
238         Map fk = dbRel.srcFkSnapshotWithTargetSnapshot(idParts);
239         map.putAll(fk);
240       }
241     } else {
242       Map relMap = ent.getRelationshipMap();
243       Iterator itr = relMap.keySet().iterator();
244       while (itr.hasNext()) {
245         String relName = (String) itr.next();
246         ObjRelationship rel = (ObjRelationship) relMap.get(relName);
247         DbRelationship dbRel =
248           (DbRelationship) rel.getDbRelationships().get(1);
249         if (rel.isToMany())
250           continue;
251         if (dbRel.isToDependentPK())
252           continue;
253         DataObject target =
254           (DataObject) o.readPropertyDirectly(relName);
255         if (target == null)
256           continue;
257         if (dbRel.getSourceEntity()
258           != masterDependentRel.getTargetEntity())
259           continue;
260         Map idParts = target.getObjectId().getIdSnapshot();
261         // this may happen in uncommitted objects
262         if (idParts == null)
263           continue;
264         Map fk = dbRel.srcFkSnapshotWithTargetSnapshot(idParts);
265         map.putAll(fk);
266       }
267     }
268 
269     // process object id map
270     // we should ignore any object id values if a corresponding attribute
271     // is a part of relationship "toMasterPK", since those values have been
272     // set above when db relationships where processed.
273     Map thisIdParts = o.getObjectId().getIdSnapshot();
274     if (thisIdParts != null) {
275       if (!isMasterDbEntity) {
276         thisIdParts =
277           masterDependentRel.targetPkSnapshotWithSrcSnapshot(
278             thisIdParts);
279       }
280       // put only thise that do not exist in the map
281       Iterator itm = thisIdParts.keySet().iterator();
282       while (itm.hasNext()) {
283         Object nextKey = itm.next();
284         if (!map.containsKey(nextKey))
285           map.put(nextKey, thisIdParts.get(nextKey));
286       }
287     }
288     return map;
289   }
290 
291   //    public static Map buildSnapshotForUpdate(ObjEntity ent,
292   //            DataObject o,
293   //            DbRelationship masterDependentRel) {
294   //        boolean isMasterDbEntity = (masterDependentRel == null);
295   //        Map committedSnapshot = o.getCommittedSnapshot();
296   //        committedSnapshot = (committedSnapshot == null ||
297   //                             committedSnapshot.isEmpty() ?
298   //                             Collections.EMPTY_MAP :
299   //                             committedSnapshot);
300   //        Map map = new HashMap();
301   //
302   //        Map attrMap = ent.getAttributeMap();
303   //        Iterator it = attrMap.keySet().iterator();
304   //        while (it.hasNext()) {
305   //            String attrName = (String) it.next();
306   //            ObjAttribute objAttr = (ObjAttribute) attrMap.get(attrName);
307   //
308   //            Object oldValue = committedSnapshot.get(objAttr.getDbAttributePath());
309   //            Object newValue = o.readPropertyDirectly(attrName);
310   //
311   //            // if snapshot exists, compare old values and new values,
312   //            // only add attribute to the update clause if the value has changed
313   //            if (!valueChanged(oldValue, newValue)) continue;
314   //
315   //            if (isMasterDbEntity && !objAttr.isCompound()) {
316   //                map.put(objAttr.getDbAttributePath(), newValue);
317   //            } else if (!isMasterDbEntity && objAttr.isCompound()) {
318   //                DbAttribute dbAttr = objAttr.getDbAttribute();
319   //                if (dbAttr.getEntity() == masterDependentRel.getTargetEntity())
320   //                    map.put(dbAttr.getName(), newValue);
321   //            }
322   //        }
323   //
324   //        if (isMasterDbEntity) {
325   //            Map relMap = ent.getRelationshipMap();
326   //            Iterator itr = relMap.keySet().iterator();
327   //            while (itr.hasNext()) {
328   //                String relName = (String) itr.next();
329   //                ObjRelationship rel = (ObjRelationship) relMap.get(relName);
330   //
331   //                // to-many will be handled on the other side
332   //                if (rel.isToMany() || rel.isToDependentEntity()) continue;
333   //
334   //                DbRelationship dbRel =
335   //                        (DbRelationship) rel.getDbRelationshipList().get(0);
336   //
337   //                DataObject target = (DataObject) o.readPropertyDirectly(relName);
338   //
339   //                if (target == null) {
340   //                    for (Iterator i = dbRel.getJoins().iterator(); i.hasNext(); ) {
341   //                        DbAttributePair join = (DbAttributePair)i.next();
342   //                        String dbAttrName = join.getSource().getName();
343   //                        if (committedSnapshot.get(dbAttrName) != null) {
344   //                            map.put(dbAttrName, null);
345   //                        }
346   //                    }
347   //                    continue;
348   //                }
349   //
350   //                Map idParts = target.getObjectId().getIdSnapshot();
351   //
352   //                // this may happen in uncommitted objects
353   //                if (idParts == null) {
354   //                    continue;
355   //                }
356   //
357   //                Map fk = dbRel.srcFkSnapshotWithTargetSnapshot(idParts);
358   //                for (Iterator i = fk.entrySet().iterator(); i.hasNext(); ) {
359   //                    Map.Entry entry = (Map.Entry)i.next();
360   //                    Object key = entry.getKey();
361   //                    Object oldValue = committedSnapshot.get(key);
362   //                    Object newValue = entry.getValue();
363   //
364   //                    // if snapshot exists, compare old values and new values,
365   //                    // only add attribute to the update clause if the value has changed
366   //                    if (!valueChanged(oldValue, newValue)) continue;
367   //
368   //                    map.put(key, newValue);
369   //                }
370   //            }
371   //        }
372   //
373   //        // process object id map
374   //        // we should ignore any object id values if a corresponding attribute
375   //        // is a part of relationship "toMasterPK", since those values have been
376   //        // set above when db relationships where processed.
377   //        Map thisIdParts = o.getObjectId().getIdSnapshot();
378   //        if (thisIdParts != null) {
379   //            Map id = (isMasterDbEntity ?
380   //                      thisIdParts :
381   //                      masterDependentRel.
382   //                      targetPkSnapshotWithSrcSnapshot(thisIdParts));
383   //            // put only thise that do not exist in the map
384   //            Iterator itm = id.keySet().iterator();
385   //            while (itm.hasNext()) {
386   //                Object nextKey = itm.next();
387   //                Object newValue = id.get(nextKey);
388   //                if (!map.containsKey(nextKey)) {
389   //                    Object committedKey = (isMasterDbEntity ?
390   //                            nextKey :
391   //                            getSrcDbAttributeName((String)nextKey, masterDependentRel));
392   //                    Object oldValue = committedSnapshot.get(committedKey);
393   //                    if (!valueChanged(oldValue, newValue)) continue;
394   //                    map.put(nextKey, newValue);
395   //                }
396   //            }
397   //        }
398   //        return map;
399   //  }
400 
401   private static boolean valueChanged(Object oldValue, Object newValue) {
402     return (
403       (newValue == null && oldValue != null)
404         || (newValue != null && !newValue.equals(oldValue)));
405   }
406 
407   /*
408       private static String getSrcDbAttributeName(
409               String targetDbAttributeName,
410               DbRelationship masterDependentRel) {
411           for (Iterator i = masterDependentRel.getJoins().iterator(); i.hasNext(); ) {
412               DbAttributePair join = (DbAttributePair)i.next();
413               if (targetDbAttributeName.equals(join.getTarget().getName()))
414                   return join.getSource().getName();
415           }
416           return null;
417       }
418   */
419 
420   private static String getTargetDbAttributeName(
421     String srcDbAttributeName,
422     DbRelationship masterDependentRel) {
423     for (Iterator i = masterDependentRel.getJoins().iterator();
424       i.hasNext();
425       ) {
426       DbAttributePair join = (DbAttributePair) i.next();
427       if (srcDbAttributeName.equals(join.getSource().getName()))
428         return join.getTarget().getName();
429     }
430     return null;
431   }
432 
433   public static Map buildSnapshotForUpdate(
434     ObjEntity entity,
435     DataObject o,
436     DbRelationship masterDependentRel) {
437     boolean isMasterDbEntity = (masterDependentRel == null);
438     Map committedSnapshot = o.getCommittedSnapshot();
439     Map currentSnapshot = o.getCurrentSnapshot();
440     Map snapshot = new HashMap(currentSnapshot.size());
441 
442     if (committedSnapshot == null || committedSnapshot.isEmpty()) {
443       for (Iterator i = currentSnapshot.entrySet().iterator();
444         i.hasNext();
445         ) {
446         Map.Entry entry = (Map.Entry) i.next();
447         String dbAttrPath = (String) entry.getKey();
448         boolean compoundDbAttr =
449           dbAttrPath.indexOf(Entity.PATH_SEPARATOR) > 0;
450         Object newValue = entry.getValue();
451         if (isMasterDbEntity && !compoundDbAttr) {
452           snapshot.put(dbAttrPath, newValue);
453         } else if (!isMasterDbEntity && compoundDbAttr) {
454           Iterator pathIterator =
455             entity.getDbEntity().resolvePathComponents(dbAttrPath);
456           if (pathIterator.hasNext()
457             && masterDependentRel.equals(pathIterator.next())) {
458             DbAttribute dbAttr = (DbAttribute) pathIterator.next();
459             snapshot.put(dbAttr.getName(), newValue);
460           }
461         } else if (!isMasterDbEntity && !compoundDbAttr) {
462           String pkAttrName =
463             getTargetDbAttributeName(
464               dbAttrPath,
465               masterDependentRel);
466           if (pkAttrName != null)
467             snapshot.put(pkAttrName, newValue);
468         }
469       }
470       return Collections.unmodifiableMap(snapshot);
471     }
472 
473     Iterator it = currentSnapshot.entrySet().iterator();
474     while (it.hasNext()) {
475       Map.Entry entry = (Map.Entry) it.next();
476       String dbAttrPath = (String) entry.getKey();
477       boolean compoundDbAttr =
478         dbAttrPath.indexOf(Entity.PATH_SEPARATOR) > 0;
479       Object newValue = entry.getValue();
480       // if snapshot exists, compare old values and new values,
481       // only add attribute to the update clause if the value has changed
482       Object oldValue = committedSnapshot.get(dbAttrPath);
483       if (valueChanged(oldValue, newValue)) {
484         if (isMasterDbEntity && !compoundDbAttr) {
485           snapshot.put(dbAttrPath, newValue);
486         } else if (!isMasterDbEntity && compoundDbAttr) {
487           Iterator pathIterator =
488             entity.getDbEntity().resolvePathComponents(dbAttrPath);
489           if (pathIterator.hasNext()
490             && masterDependentRel.equals(pathIterator.next())) {
491             DbAttribute dbAttr = (DbAttribute) pathIterator.next();
492             snapshot.put(dbAttr.getName(), newValue);
493           }
494         } else if (!isMasterDbEntity && !compoundDbAttr) {
495           String pkAttrName =
496             getTargetDbAttributeName(
497               dbAttrPath,
498               masterDependentRel);
499           if (pkAttrName != null)
500             snapshot.put(pkAttrName, newValue);
501         }
502       }
503     }
504 
505     // original snapshot can have extra keys that are missing in current snapshot
506     // process those
507     Iterator origit = committedSnapshot.entrySet().iterator();
508     while (origit.hasNext()) {
509       Map.Entry entry = (Map.Entry) origit.next();
510       String dbAttrPath = (String) entry.getKey();
511       boolean compoundDbAttr =
512         dbAttrPath.indexOf(Entity.PATH_SEPARATOR) > 0;
513       Object oldValue = entry.getValue();
514       if (oldValue == null || currentSnapshot.containsKey(dbAttrPath))
515         continue;
516       if (isMasterDbEntity && !compoundDbAttr) {
517         snapshot.put(dbAttrPath, null);
518       } else if (!isMasterDbEntity && compoundDbAttr) {
519         Iterator pathIterator =
520           entity.getDbEntity().resolvePathComponents(dbAttrPath);
521         if (pathIterator.hasNext()
522           && masterDependentRel.equals(pathIterator.next())) {
523           DbAttribute dbAttr = (DbAttribute) pathIterator.next();
524           snapshot.put(dbAttr.getName(), null);
525         }
526       } else if (!isMasterDbEntity && !compoundDbAttr) {
527         String pkAttrName =
528           getTargetDbAttributeName(dbAttrPath, masterDependentRel);
529         if (pkAttrName != null)
530           snapshot.put(pkAttrName, null);
531       }
532     }
533     return Collections.unmodifiableMap(snapshot);
534   }
535 }