View Javadoc

1   package com.atlassian.core.ofbiz.association;
2   
3   import com.atlassian.core.ofbiz.CoreFactory;
4   import com.atlassian.core.user.UserUtils;
5   import com.opensymphony.user.EntityNotFoundException;
6   import com.opensymphony.user.User;
7   import org.apache.commons.collections.CollectionUtils;
8   import org.apache.commons.collections.Transformer;
9   import org.apache.log4j.Logger;
10  import org.ofbiz.core.entity.*;
11  import org.ofbiz.core.util.UtilMisc;
12  
13  import java.util.*;
14  
15  public class DefaultAssociationManager implements AssociationManager
16  {
17      private static final Logger log = Logger.getLogger(DefaultAssociationManager.class);
18      private final GenericDelegator delegator = CoreFactory.getGenericDelegator();
19  
20      /**
21       * Create an association between two entities, given a particular association type.
22       * <p/>
23       * If the association already exists - it will not be created.
24       *
25       * @return The new association, or the existing association if it already existed.
26       */
27      public GenericValue createAssociation(GenericValue source, GenericValue sink, String associationType)
28              throws GenericEntityException
29      {
30          final GenericValue existingAssocation = getAssociation(source, sink, associationType);
31          if (existingAssocation == null)
32          {
33              GenericValue v = delegator.makeValue("NodeAssociation", UtilMisc.toMap(
34                      "associationType", associationType,
35                      "sourceNodeId", source.getLong("id"),
36                      "sourceNodeEntity", source.getEntityName(),
37                      "sinkNodeId", sink.getLong("id"),
38                      "sinkNodeEntity", sink.getEntityName()));
39              v.create();
40              return v;
41          }
42          return existingAssocation;
43      }
44  
45      public GenericValue createAssociation(Long sourceNodeId, String sourceNodeEntity, Long sinkNodeId, String sinkNodeEntity, String associationType)
46              throws GenericEntityException
47      {
48          final GenericValue existingAssocation = getAssociation(sourceNodeId, sourceNodeEntity, sinkNodeId, sinkNodeEntity, associationType);
49          if (existingAssocation == null)
50          {
51              GenericValue v = delegator.makeValue("NodeAssociation", UtilMisc.toMap(
52                      "associationType", associationType,
53                      "sourceNodeId", sourceNodeId,
54                      "sourceNodeEntity", sourceNodeEntity,
55                      "sinkNodeId", sinkNodeId,
56                      "sinkNodeEntity", sinkNodeEntity));
57              v.create();
58              return v;
59          }
60          return existingAssocation;
61      }
62  
63      public GenericValue createAssociation(String userName, Long sinkNodeId, String sinkNodeEntity, String associationType)
64              throws GenericEntityException
65      {
66          final GenericValue existingAssociation = getAssociation(userName, sinkNodeId, sinkNodeEntity, associationType);
67          if (existingAssociation == null)
68          {
69              GenericValue v = delegator.makeValue("UserAssociation", UtilMisc.toMap(
70                      "associationType", associationType,
71                      "sourceName", userName,
72                      "sinkNodeId", sinkNodeId,
73                      "sinkNodeEntity", sinkNodeEntity));
74              v.create();
75              v.refresh();
76              return v;
77          }
78          return existingAssociation;
79      }
80  
81      public GenericValue createAssociation(User user, GenericValue sink, String associationType)
82              throws GenericEntityException
83      {
84          final GenericValue v = delegator.makeValue("UserAssociation", UtilMisc.toMap(
85                  "associationType", associationType,
86                  "sourceName", user.getName(),
87                  "sinkNodeId", sink.getLong("id"),
88                  "sinkNodeEntity", sink.getEntityName()));
89          v.create();
90          v.refresh();
91          return v;
92      }
93  
94  
95      public void removeAssociation(User user, GenericValue sink, String associationType) throws GenericEntityException
96      {
97          removeAssociation(user.getName(), sink, associationType);
98      }
99  
100     public void removeAssociation(String username, GenericValue sink, String associationType) throws GenericEntityException
101     {
102         final Map fields = new HashMap();
103         fields.put("sinkNodeId", sink.getLong("id"));
104         fields.put("sinkNodeEntity", sink.getEntityName());
105         fields.put("sourceName", username);
106         fields.put("associationType", associationType);
107         delegator.removeByPrimaryKey(delegator.makePK("UserAssociation", fields));
108     }
109 
110     public void removeAssociation(GenericValue source, GenericValue sink, String associationType)
111             throws GenericEntityException
112     {
113         final Map fields = new HashMap();
114         fields.put("sinkNodeId", sink.getLong("id"));
115         fields.put("sinkNodeEntity", sink.getEntityName());
116         fields.put("sourceNodeId", source.getLong("id"));
117         fields.put("sourceNodeEntity", source.getEntityName());
118         fields.put("associationType", associationType);
119         delegator.removeByPrimaryKey(delegator.makePK("NodeAssociation", fields));
120     }
121 
122     /**
123      * Remove all entity<->entity associations, given the source
124      */
125     public void removeAssociationsFromSource(GenericValue source) throws GenericEntityException
126     {
127         final Map fields = new HashMap();
128         fields.put("sourceNodeId", source.getLong("id"));
129         fields.put("sourceNodeEntity", source.getEntityName());
130         delegator.removeByAnd("NodeAssociation", fields);
131     }
132 
133     public void removeAssociationsFromSink(GenericValue sink) throws GenericEntityException
134     {
135         final Map fields = new HashMap();
136         fields.put("sinkNodeId", sink.getLong("id"));
137         fields.put("sinkNodeEntity", sink.getEntityName());
138         delegator.removeByAnd("NodeAssociation", fields);
139     }
140 
141     /**
142      * Remove all user<->entity associations, given the entity
143      */
144     public void removeUserAssociationsFromSink(GenericValue sink) throws GenericEntityException
145     {
146         final Map fields = new HashMap();
147         fields.put("sinkNodeId", sink.getLong("id"));
148         fields.put("sinkNodeEntity", sink.getEntityName());
149         delegator.removeByAnd("UserAssociation", fields);
150     }
151 
152     /**
153      * Remove all user<->entity associations, given the entity and association type
154      */
155     public void removeUserAssociationsFromSink(GenericValue sink, String associationType) throws GenericEntityException
156     {
157         final Map fields = new HashMap();
158         fields.put("sinkNodeId", sink.getLong("id"));
159         fields.put("sinkNodeEntity", sink.getEntityName());
160         fields.put("associationType", associationType);
161         delegator.removeByAnd("UserAssociation", fields);
162     }
163 
164 
165     /**
166      * Remove all user<->entity associations, given the user
167      */
168     public void removeUserAssociationsFromUser(User user) throws GenericEntityException
169     {
170         final Map fields = new HashMap();
171         fields.put("sourceName", user.getName());
172         delegator.removeByAnd("UserAssociation", fields);
173     }
174 
175     public void removeUserAssociationsFromUser(final User user, final String associationType)
176             throws GenericEntityException
177     {
178         final Map fields = new HashMap();
179         fields.put("sourceName", user.getName());
180         fields.put("associationType", associationType);
181         delegator.removeByAnd("UserAssociation", fields);
182     }
183 
184     public void removeUserAssociationsFromUser(final User user, final String associationType, final String entityName)
185             throws GenericEntityException
186     {
187         final Map fields = new HashMap();
188         fields.put("sourceName", user.getName());
189         fields.put("associationType", associationType);
190         fields.put("sinkNodeEntity", entityName);
191         delegator.removeByAnd("UserAssociation", fields);
192     }
193 
194 
195     /**
196      * Swap all assocaitions of a particular type from one sink to another.
197      * <p/>
198      * Used in ComponentDelete and VersionDelete.
199      */
200     public void swapAssociation(String sourceEntityName, String associationType, GenericValue fromSink, GenericValue toSink)
201             throws GenericEntityException
202     {
203         final List sources = getSourceFromSink(fromSink, sourceEntityName, associationType, false);
204         swapAssociation(sources, associationType, fromSink, toSink);
205     }
206 
207     /**
208      * Swaps all associations for a given list of entities (say move a list of unresolved issue entities to a new fix for version)
209      */
210     public void swapAssociation(List entities, String associationType, GenericValue fromSink, GenericValue toSink)
211             throws GenericEntityException
212     {
213         for (Iterator iterator = entities.iterator(); iterator.hasNext();)
214         {
215             GenericValue entity = (GenericValue) iterator.next();
216             CoreFactory.getAssociationManager().createAssociation(entity, toSink, associationType);
217             removeAssociation(entity, fromSink, associationType);
218         }
219     }
220 
221     List getAssociations(String associationName, Map fields, boolean useCache, boolean useSequence)
222             throws GenericEntityException
223     {
224         List result;
225         if (useCache)
226         {
227             result = delegator.findByAndCache(associationName, fields);
228         }
229         else
230         {
231             result = delegator.findByAnd(associationName, fields);
232         }
233 
234         if (useSequence)
235         {
236             result = EntityUtil.orderBy(result, UtilMisc.toList("sequence"));
237         }
238         return result;
239     }
240 
241     public GenericValue getAssociation(GenericValue source, GenericValue sink, String associationType)
242             throws GenericEntityException
243     {
244         return getAssociation(source.getLong("id"), source.getEntityName(), sink.getLong("id"), sink.getEntityName(), associationType);
245     }
246 
247     public GenericValue getAssociation(User user, GenericValue sink, String associationType)
248             throws GenericEntityException
249     {
250         if (user == null)
251         {
252             return null;
253         }
254 
255         return EntityUtil.getOnly(delegator.findByAnd("UserAssociation", UtilMisc.toMap(
256                 "associationType", associationType,
257                 "sourceName", user.getName(),
258                 "sinkNodeId", sink.getLong("id"),
259                 "sinkNodeEntity", sink.getEntityName())));
260     }
261 
262     /**
263      * Operates on NodeAssociations - gets MANY sinks from ONE source
264      */
265     public List getSinkFromSource(GenericValue source, String sinkName, String associationType, boolean useCache)
266             throws GenericEntityException
267     {
268         return getSinkFromSource(source, sinkName, associationType, useCache, false);
269     }
270 
271     public List getSinkFromSource(GenericValue source, String sinkName, String associationType, boolean useCache, boolean useSequence)
272             throws GenericEntityException
273     {
274         if (source == null)
275         {
276             throw new IllegalArgumentException("Source GenericValue can not be null.");
277         }
278 
279         final List result = getSinkIdsFromSource(source, sinkName, associationType, useCache, useSequence);
280 
281         final List outList = new ArrayList(result.size());
282         for (Iterator iterator = result.iterator(); iterator.hasNext();)
283         {
284             GenericValue value = (GenericValue) iterator.next();
285             GenericValue byPrimaryKey;
286             if (useCache)
287             {
288                 byPrimaryKey = delegator.findByPrimaryKeyCache(sinkName, UtilMisc.toMap("id", value.getLong("sinkNodeId")));
289             }
290             else
291             {
292                 byPrimaryKey = delegator.findByPrimaryKey(sinkName, UtilMisc.toMap("id", value.getLong("sinkNodeId")));
293             }
294 
295             if (byPrimaryKey != null)
296             {
297                 outList.add(byPrimaryKey);
298             }
299         }
300         return result.isEmpty() ? Collections.EMPTY_LIST : outList;
301     }
302 
303     private List getSinkIdsFromSource(GenericValue source, String sinkName, String associationType, boolean useCache, boolean useSequence)
304             throws GenericEntityException
305     {
306         final Map fields = new HashMap();
307         fields.put("sourceNodeId", source.getLong("id"));
308         fields.put("sourceNodeEntity", source.getEntityName());
309         fields.put("associationType", associationType);
310         fields.put("sinkNodeEntity", sinkName);
311         return getAssociations("NodeAssociation", fields, useCache, useSequence);
312     }
313 
314     /**
315      * Operates on NodeAssociations - gets MANY sources from ONE sink
316      */
317     public List getSourceFromSink(GenericValue sink, String sourceName, String associationType, boolean useCache)
318             throws GenericEntityException
319     {
320         return getSourceFromSink(sink, sourceName, associationType, useCache, false);
321     }
322 
323     /**
324      * Operates on NodeAssociations - gets MANY sources from ONE sink
325      */
326     public List getSourceFromSink(GenericValue sink, String sourceName, String associationType, boolean useCache, boolean useSequence)
327             throws GenericEntityException
328     {
329         if (sink == null)
330         {
331             throw new IllegalArgumentException("Sink GenericValue can not be null.");
332         }
333         final List result = getSourceIdsFromSink(sink, associationType, sourceName, useCache, useSequence);
334         final List outList = new ArrayList(result.size());
335         for (Iterator iterator = result.iterator(); iterator.hasNext();)
336         {
337             GenericValue value = (GenericValue) iterator.next();
338             GenericPK pk = delegator.makePK(sourceName, UtilMisc.toMap("id", value.getLong("sourceNodeId")));
339             GenericValue byPrimaryKey;
340             if (useCache)
341             {
342                 byPrimaryKey = delegator.findByPrimaryKeyCache(pk);
343             }
344             else
345             {
346                 byPrimaryKey = delegator.findByPrimaryKey(pk);
347             }
348 
349             if (byPrimaryKey != null)
350             {
351                 outList.add(byPrimaryKey);
352             }
353         }
354         return result.isEmpty() ? Collections.EMPTY_LIST : outList;
355     }
356 
357     private List getSourceIdsFromSink(GenericValue sink, String associationType, String sourceName, boolean useCache, boolean useSequence)
358             throws GenericEntityException
359     {
360         final Map fields = new HashMap();
361         fields.put("sinkNodeId", sink.getLong("id"));
362         fields.put("sinkNodeEntity", sink.getEntityName());
363         fields.put("associationType", associationType);
364         fields.put("sourceNodeEntity", sourceName);
365         return getAssociations("NodeAssociation", fields, useCache, useSequence);
366     }
367 
368     /**
369      * Operates on UserAssociations - gets MANY sinks from ONE user
370      */
371     public List getSinkFromUser(User source, String sinkName, String associationType, boolean useCache)
372             throws GenericEntityException
373     {
374         return getSinkFromUser(source, sinkName, associationType, useCache, false);
375     }
376 
377     public List /*<Long>*/ getSinkIdsFromUser(final User source, final String sinkName, final String associationType, final boolean useCache)
378             throws GenericEntityException
379     {
380         final List result = getAssociationsForUser(source, sinkName, associationType, useCache, false);
381         CollectionUtils.transform(result, new Transformer()
382         {
383             public Object transform(Object input)
384             {
385                 return ((GenericValue) input).getLong("sinkNodeId");
386             }
387         });
388         return result;
389     }
390 
391     /**
392      * Operates on UserAssociations - gets MANY sinks from ONE user
393      */
394     public List getSinkFromUser(User source, String sinkName, String associationType, boolean useCache, boolean useSequence)
395             throws GenericEntityException
396     {
397         final List result = getAssociationsForUser(source, sinkName, associationType, useCache, useSequence);
398 
399         final List outList = new ArrayList(result.size());
400         for (Iterator iterator = result.iterator(); iterator.hasNext();)
401         {
402             GenericValue value = (GenericValue) iterator.next();
403             GenericPK pk = delegator.makePK(sinkName, UtilMisc.toMap("id", value.getLong("sinkNodeId")));
404             GenericValue byPrimaryKey;
405             if (useCache)
406             {
407                 byPrimaryKey = delegator.findByPrimaryKeyCache(pk);
408             }
409             else
410             {
411                 byPrimaryKey = delegator.findByPrimaryKey(pk);
412             }
413 
414             if (byPrimaryKey != null)
415             {
416                 outList.add(byPrimaryKey);
417             }
418         }
419         return result.isEmpty() ? Collections.EMPTY_LIST : outList;
420     }
421 
422     private List getAssociationsForUser(final User source, final String sinkName, final String associationType, final boolean useCache, final boolean useSequence)
423             throws GenericEntityException
424     {
425         if (source == null)
426         {
427             throw new IllegalArgumentException("User can not be null.");
428         }
429         final Map fields = new HashMap();
430         fields.put("sourceName", source.getName());
431         fields.put("associationType", associationType);
432         fields.put("sinkNodeEntity", sinkName);
433         return getAssociations("UserAssociation", fields, useCache, useSequence);
434     }
435 
436     /**
437      * Operates on UserAssociations - gets MANY users from ONE sink
438      */
439     public List getUserFromSink(GenericValue sink, String associationType, boolean useCache)
440             throws GenericEntityException, EntityNotFoundException
441     {
442         return getUserFromSink(sink, associationType, useCache, false);
443     }
444 
445     /**
446      * Operates on UserAssociations - gets MANY users from ONE sink
447      */
448     public List/*<User>*/ getUserFromSink(GenericValue sink, String associationType, boolean useCache, boolean useSequence)
449             throws GenericEntityException, EntityNotFoundException
450     {
451         final List/*<String>*/ usernames = getUsernamesFromSink(sink, associationType, useCache, useSequence);
452         final List/*<User>*/ users = new ArrayList(usernames.size());
453         for (Iterator it = usernames.iterator(); it.hasNext();)
454         {
455             String username = (String) it.next();
456             try
457             {
458                 final User user = UserUtils.getUser(username);
459                 if (user != null)
460                 {
461                     users.add(user);
462                 }
463             }
464             catch (EntityNotFoundException e)
465             {
466                 log.error("Cannot find user with username '" + username + "'.", e);
467             }
468         }
469         return users;
470     }
471 
472     public List/*<String>*/ getUsernamesFromSink(GenericValue sink, String associationType, boolean useCache, boolean useSequence)
473             throws GenericEntityException
474     {
475         if (sink == null)
476         {
477             throw new IllegalArgumentException("Sink GenericValue can not be null.");
478         }
479 
480         final Map fields = new HashMap();
481         fields.put("sinkNodeId", sink.getLong("id"));
482         fields.put("sinkNodeEntity", sink.getEntityName());
483         fields.put("associationType", associationType);
484 
485         final List results = getAssociations("UserAssociation", fields, useCache, useSequence);
486         if (results.isEmpty())
487         {
488             return Collections.EMPTY_LIST;
489         }
490 
491         final List outList = new ArrayList(results.size());
492         for (Iterator it = results.iterator(); it.hasNext();)
493         {
494             outList.add(((GenericValue) it.next()).getString("sourceName"));
495         }
496         return outList;
497     }
498 
499     public List getSinkIdsFromSource(GenericValue source, String sinkEntity, String associationType)
500             throws GenericEntityException
501     {
502         List sinks = getSinkIdsFromSource(source, sinkEntity, associationType, false, false);
503 
504         if (sinks != null && !sinks.isEmpty())
505         {
506             List sinkIds = new ArrayList();
507             for (Iterator iterator = sinks.iterator(); iterator.hasNext();)
508             {
509                 GenericValue sink = (GenericValue) iterator.next();
510                 sinkIds.add(sink.getLong("sinkNodeId"));
511             }
512             return sinkIds;
513         }
514 
515         return Collections.EMPTY_LIST;
516     }
517 
518     public List getSourceIdsFromSink(GenericValue sink, String sourceEntity, String associationType)
519             throws GenericEntityException
520     {
521         List sources = getSourceIdsFromSink(sink, associationType, sourceEntity, false, false);
522 
523         if (sources != null && !sources.isEmpty())
524         {
525             List sourceIds = new ArrayList();
526             for (Iterator iterator = sources.iterator(); iterator.hasNext();)
527             {
528                 GenericValue source = (GenericValue) iterator.next();
529                 sourceIds.add(source.getLong("sourceNodeId"));
530             }
531             return sourceIds;
532         }
533 
534         return Collections.EMPTY_LIST;
535     }
536 
537     private GenericValue getAssociation(Long sourceNodeId, String sourceNodeEntity, Long sinkNodeId, String sinkNodeEntity, String associationType)
538             throws GenericEntityException
539     {
540         return EntityUtil.getOnly(delegator.findByAnd("NodeAssociation", UtilMisc.toMap("associationType", associationType, "sourceNodeId", sourceNodeId, "sourceNodeEntity", sourceNodeEntity, "sinkNodeId", sinkNodeId, "sinkNodeEntity", sinkNodeEntity)));
541     }
542 
543     private GenericValue getAssociation(String sourceName, Long sinkNodeId, String sinkNodeEntity, String associationType)
544             throws GenericEntityException
545     {
546         return EntityUtil.getOnly(delegator.findByAnd("UserAssociation", UtilMisc.toMap("associationType", associationType, "sourceName", sourceName, "sinkNodeId", sinkNodeId, "sinkNodeEntity", sinkNodeEntity)));
547     }
548 }