KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencrx > kernel > layer > application > Activities


1 /*
2  * ====================================================================
3  * Project: opencrx, http://www.opencrx.org/
4  * Name: $Id: Activities.java,v 1.52 2006/03/31 00:15:17 wfro Exp $
5  * Description: openCRX application plugin
6  * Revision: $Revision: 1.52 $
7  * Owner: CRIXP AG, Switzerland, http://www.crixp.com
8  * Date: $Date: 2006/03/31 00:15:17 $
9  * ====================================================================
10  *
11  * This software is published under the BSD license
12  * as listed below.
13  *
14  * Copyright (c) 2004-2005, CRIXP Corp., Switzerland
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  *
21  * * Redistributions of source code must retain the above copyright
22  * notice, this list of conditions and the following disclaimer.
23  *
24  * * Redistributions in binary form must reproduce the above copyright
25  * notice, this list of conditions and the following disclaimer in
26  * the documentation and/or other materials provided with the
27  * distribution.
28  *
29  * * Neither the name of CRIXP Corp. nor the names of the contributors
30  * to openCRX may be used to endorse or promote products derived
31  * from this software without specific prior written permission
32  *
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
35  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
36  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
37  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
39  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
40  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
41  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
43  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
45  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46  * POSSIBILITY OF SUCH DAMAGE.
47  *
48  * ------------------
49  *
50  * This product includes software developed by the Apache Software
51  * Foundation (http://www.apache.org/).
52  *
53  * This product includes software developed by contributors to
54  * openMDX (http://www.openmdx.org/)
55  */

56
57 package org.opencrx.kernel.layer.application;
58
59 import java.io.ByteArrayOutputStream JavaDoc;
60 import java.io.PrintWriter JavaDoc;
61 import java.math.BigDecimal JavaDoc;
62 import java.text.ParseException JavaDoc;
63 import java.util.ArrayList JavaDoc;
64 import java.util.Collections JavaDoc;
65 import java.util.Date JavaDoc;
66 import java.util.GregorianCalendar JavaDoc;
67 import java.util.HashSet JavaDoc;
68 import java.util.Iterator JavaDoc;
69 import java.util.List JavaDoc;
70 import java.util.Locale JavaDoc;
71 import java.util.Set JavaDoc;
72
73 import org.opencrx.kernel.generic.OpenCrxException;
74 import org.openmdx.base.accessor.jmi.cci.RefPackage_1_0;
75 import org.openmdx.base.exception.ServiceException;
76 import org.openmdx.base.text.format.DateFormat;
77 import org.openmdx.compatibility.base.dataprovider.cci.AttributeSelectors;
78 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderObject;
79 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderObject_1_0;
80 import org.openmdx.compatibility.base.dataprovider.cci.Directions;
81 import org.openmdx.compatibility.base.dataprovider.cci.RequestCollection;
82 import org.openmdx.compatibility.base.dataprovider.cci.ServiceHeader;
83 import org.openmdx.compatibility.base.dataprovider.cci.SystemAttributes;
84 import org.openmdx.compatibility.base.naming.Path;
85 import org.openmdx.compatibility.base.query.FilterOperators;
86 import org.openmdx.compatibility.base.query.FilterProperty;
87 import org.openmdx.compatibility.base.query.Quantors;
88 import org.openmdx.kernel.exception.BasicException;
89 import org.openmdx.kernel.log.SysLog;
90 import org.openmdx.model1.accessor.basic.cci.Model_1_0;
91
92 public class Activities {
93
94     //-----------------------------------------------------------------------
95
public Activities(
96         Model_1_0 model,
97         OpenCrxKernel_1 plugin,
98         RequestCollection delegation,
99         RefPackage_1_0 rootPkg
100     ) {
101         this.model = model;
102         this.plugin = plugin;
103         this.delegation = delegation;
104         this.rootPkg = rootPkg;
105     }
106     
107     //-------------------------------------------------------------------------
108
private int calculateOpenActivityTimeDistribution(
109       ServiceHeader header,
110       Path reference,
111       String JavaDoc objectClass,
112       int[] timeDistribution,
113       String JavaDoc distributionOnAttribute,
114       boolean lookAhead
115     ) {
116       try {
117         List JavaDoc activities = this.delegation.addFindRequest(
118             reference,
119             new FilterProperty[]{
120                 new FilterProperty(
121                     Quantors.THERE_EXISTS,
122                     SystemAttributes.OBJECT_CLASS,
123                     FilterOperators.IS_IN,
124                     new String JavaDoc[]{objectClass}
125                 ),
126                 new FilterProperty(
127                     Quantors.THERE_EXISTS,
128                     "percentComplete",
129                     FilterOperators.IS_LESS,
130                     new Number JavaDoc[]{new Short JavaDoc((short)100)}
131                 )
132             },
133             AttributeSelectors.ALL_ATTRIBUTES,
134             0,
135             Activities.BATCHING_MODE_SIZE,
136             Directions.ASCENDING
137         );
138         
139         int count = 0;
140         for(
141            Iterator JavaDoc i = activities.iterator();
142            i.hasNext();
143         ) {
144           DataproviderObject_1_0 activity = (DataproviderObject_1_0)i.next();
145           Date JavaDoc dt = new Date JavaDoc();
146           try {
147             dt = org.openmdx.base.text.format.DateFormat.getInstance().parse(
148               (String JavaDoc)activity.values(distributionOnAttribute).get(0)
149             );
150           } catch(Exception JavaDoc e) {}
151
152           long delayInDays = (lookAhead ? 1 : -1) * (dt.getTime() - System.currentTimeMillis()) / 86400000;
153           if(delayInDays < 0) timeDistribution[0]++;
154           else if(delayInDays < 1) timeDistribution[1]++;
155           else if(delayInDays < 2) timeDistribution[2]++;
156           else if(delayInDays < 3) timeDistribution[3]++;
157           else if(delayInDays < 4) timeDistribution[4]++;
158           else if(delayInDays < 5) timeDistribution[5]++;
159           else if(delayInDays < 6) timeDistribution[6]++;
160           else if(delayInDays < 7) timeDistribution[7]++;
161           else if(delayInDays < 8) timeDistribution[8]++;
162           else if(delayInDays < 15) timeDistribution[9]++;
163           else if(delayInDays < 31) timeDistribution[10]++;
164           else if(delayInDays < 91) timeDistribution[11]++;
165           else if(delayInDays < 181) timeDistribution[12]++;
166           else if(delayInDays < 361) timeDistribution[13]++;
167           else timeDistribution[14]++;
168           
169           count++;
170         }
171         return count;
172       }
173       catch(ServiceException e) {
174         return 0;
175       }
176     }
177
178     //-------------------------------------------------------------------------
179
DataproviderObject[] calculateUserHomeCharts(
180       ServiceHeader header,
181       Path userHome,
182       Path chartReference
183     ) throws ServiceException {
184
185       java.text.DateFormat JavaDoc dateFormat =
186           java.text.DateFormat.getDateInstance(java.text.DateFormat.SHORT, new Locale JavaDoc("en_US"));
187       java.text.DateFormat JavaDoc timeFormat =
188           java.text.DateFormat.getTimeInstance(java.text.DateFormat.SHORT, new Locale JavaDoc("en_US"));
189       String JavaDoc createdAt = dateFormat.format(new Date JavaDoc()) + " " + timeFormat.format(new Date JavaDoc());
190       // try to get full name of contact
191
String JavaDoc fullName = "";
192       try {
193           fullName = (String JavaDoc)this.plugin.retrieveObjectFromLocal(
194               header,
195               (Path)this.plugin.retrieveObjectFromLocal(header, userHome).values("contact").get(0)
196           ).values("fullName").get(0);
197       } catch(Exception JavaDoc e) {}
198       
199       DataproviderObject[] charts = new DataproviderObject[2];
200       String JavaDoc chartTitle = null;
201       
202       /**
203        * Assigned Activities Overview
204        */

205       chartTitle = (fullName.length() == 0 ? "" : fullName + ": ") + "Assigned Open Activities Overview (" + createdAt + ")";
206       
207       charts[0] = new DataproviderObject(
208         chartReference.getChild("2")
209       );
210       charts[0].values(SystemAttributes.OBJECT_CLASS).add("org:opencrx:kernel:home1:Chart");
211       charts[0].values("description").add(chartTitle);
212       ByteArrayOutputStream JavaDoc os = new ByteArrayOutputStream JavaDoc();
213       PrintWriter JavaDoc pw = new PrintWriter JavaDoc(os);
214
215       pw.println("BEGIN:VND.OPENDMDX-CHART");
216       pw.println("VERSION:1.0");
217       pw.println("COUNT:1");
218
219       pw.println("CHART[0].TYPE:HORIZBAR");
220       pw.println("CHART[0].LABEL:" + chartTitle);
221       pw.println("CHART[0].SCALEXTITLE:#Activities");
222       pw.println("CHART[0].SCALEYTITLE:Activity type");
223       pw.println("CHART[0].COUNT:" + ACTIVITY_TYPES.length);
224       
225       int[] counts = new int[ACTIVITY_TYPES.length];
226       int[] timeDistribution = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
227       Path assignedActivityReference = userHome.getChild("assignedActivity");
228       for(
229           int i = 0;
230           i < ACTIVITY_TYPES.length;
231           i++
232       ) {
233           String JavaDoc activityTypeName = (String JavaDoc)this.plugin.getCodes().getLongText(
234               CODEVALUENAME_ACTIVITY_TYPE,
235               (short)0,
236               true
237           ).get(new Short JavaDoc((short)i));
238           pw.println("CHART[0].LABEL[" + i + "]:" + activityTypeName);
239           counts[i] =
240               this.calculateOpenActivityTimeDistribution(
241                   header,
242                   assignedActivityReference,
243                   ACTIVITY_TYPES[i],
244                   timeDistribution,
245                   "scheduledStart",
246                   true
247               );
248       }
249       int maxValue = 0;
250       for(int i = 0; i < counts.length; i++) {
251         pw.println("CHART[0].VAL[" + i + "]:" + counts[i]);
252         pw.println("CHART[0].BORDER[" + i + "]:#000066");
253         pw.println("CHART[0].FILL[" + i + "]:#F6D66D");
254         maxValue = Math.max(maxValue, counts[i]);
255       }
256       pw.println("CHART[0].MINVALUE:0");
257       pw.println("CHART[0].MAXVALUE:" + maxValue);
258       pw.println("END:VND.OPENDMDX-CHART");
259       try {
260         pw.flush();
261         os.close();
262       } catch(Exception JavaDoc e) {}
263       charts[0].values("chart").add(
264         os.toByteArray()
265       );
266       charts[0].values("chartMimeType").add("application/vnd.openmdx-chart");
267       charts[0].values("chartName").add(
268         this.plugin.toFilename(chartTitle + ".txt")
269       );
270
271       /**
272        * Assigned Activities Age Distribution
273        */

274       chartTitle = (fullName.length() == 0 ? "" : fullName + ": ") + "Assigned Open Activities Age Distribution (" + createdAt + ")";
275       
276       charts[1] = new DataproviderObject(
277         chartReference.getChild("3")
278       );
279       charts[1].values(SystemAttributes.OBJECT_CLASS).add("org:opencrx:kernel:home1:Chart");
280       charts[1].values("description").add(chartTitle);
281       os = new ByteArrayOutputStream JavaDoc();
282       pw = new PrintWriter JavaDoc(os);
283
284       pw.println("BEGIN:VND.OPENDMDX-CHART");
285       pw.println("VERSION:1.0");
286       pw.println("COUNT:1");
287
288       pw.println("CHART[0].TYPE:VERTBAR");
289       pw.println("CHART[0].LABEL:" + chartTitle);
290       pw.println("CHART[0].SCALEXTITLE:#Days");
291       pw.println("CHART[0].SCALEYTITLE:#Activities");
292       pw.println("CHART[0].COUNT:15");
293       
294       pw.println("CHART[0].LABEL[0]:past due");
295       pw.println("CHART[0].LABEL[1]:today");
296       pw.println("CHART[0].LABEL[2]:1");
297       pw.println("CHART[0].LABEL[3]:2");
298       pw.println("CHART[0].LABEL[4]:3");
299       pw.println("CHART[0].LABEL[5]:4");
300       pw.println("CHART[0].LABEL[6]:5");
301       pw.println("CHART[0].LABEL[7]:6");
302       pw.println("CHART[0].LABEL[8]:7");
303       pw.println("CHART[0].LABEL[9]:..14");
304       pw.println("CHART[0].LABEL[10]:..30");
305       pw.println("CHART[0].LABEL[11]:..90");
306       pw.println("CHART[0].LABEL[12]:..180");
307       pw.println("CHART[0].LABEL[13]:..360");
308       pw.println("CHART[0].LABEL[14]:>360 days");
309       
310       maxValue = 0;
311       for(int i = 0; i < 15; i++) {
312         pw.println("CHART[0].VAL[" + i + "]:" + timeDistribution[i]);
313         pw.println("CHART[0].BORDER[" + i + "]:#000066");
314         pw.println("CHART[0].FILL[" + i + "]:#F6D66D");
315         maxValue = Math.max(maxValue, timeDistribution[i]);
316       }
317
318       pw.println("CHART[0].MINVALUE:0");
319       pw.println("CHART[0].MAXVALUE:" + maxValue);
320       
321       pw.println("END:VND.OPENDMDX-CHART");
322       
323       try {
324         pw.flush();
325         os.close();
326       } catch(Exception JavaDoc e) {}
327       charts[1].values("chart").add(
328         os.toByteArray()
329       );
330       charts[1].values("chartMimeType").add("application/vnd.openmdx-chart");
331       charts[1].values("chartName").add(
332         this.plugin.toFilename(chartTitle + ".txt")
333       );
334
335       return charts;
336     }
337     
338     //-------------------------------------------------------------------------
339
public DataproviderObject refreshTracker(
340       ServiceHeader header,
341       DataproviderObject_1_0 activityTracker
342     ) throws ServiceException {
343         DataproviderObject refreshedTracker = this.plugin.retrieveObjectForModification(activityTracker.path());
344         
345         List JavaDoc activites = this.delegation.addFindRequest(
346             activityTracker.path().getChild("filteredActivity"),
347             null,
348             AttributeSelectors.NO_ATTRIBUTES,
349             0,
350             BATCHING_MODE_SIZE,
351             Directions.ASCENDING
352         );
353         int estimateEffortHours = 0;
354         int estimateEffortMinutes = 0;
355         // Iterate all activities and sum up all main effort estimates. Don't care
356
// if isMain=true if there is exactly one estimate for the activity
357
for(
358             Iterator JavaDoc i = activites.iterator();
359             i.hasNext();
360         ) {
361             DataproviderObject_1_0 activity = (DataproviderObject_1_0)i.next();
362             List JavaDoc effortEstimates = this.delegation.addFindRequest(
363                 new Path((String JavaDoc)activity.values(SystemAttributes.OBJECT_IDENTITY).get(0)).getChild("effortEstimate"),
364                 null,
365                 AttributeSelectors.ALL_ATTRIBUTES,
366                 0,
367                 Integer.MAX_VALUE,
368                 Directions.ASCENDING
369             );
370             if(effortEstimates.size() == 1) {
371                 DataproviderObject_1_0 effortEstimate = (DataproviderObject_1_0)effortEstimates.iterator().next();
372                 if(effortEstimate.values("estimateEffortHours").size() > 0) {
373                     estimateEffortHours += ((Number JavaDoc)effortEstimate.values("estimateEffortHours").get(0)).intValue();
374                 }
375                 if(effortEstimate.values("estimateEffortMinutes").size() > 0) {
376                     estimateEffortMinutes += ((Number JavaDoc)effortEstimate.values("estimateEffortMinutes").get(0)).intValue();
377                 }
378             }
379             // Lookup main estimate if there is more than one estimate
380
else {
381                 for(
382                     Iterator JavaDoc j = effortEstimates.iterator();
383                     j.hasNext();
384                 ) {
385                     DataproviderObject_1_0 effortEstimate = (DataproviderObject_1_0)j.next();
386                     if(
387                         (effortEstimate.values("isMain").size() > 0) &&
388                         ((Boolean JavaDoc)effortEstimate.values("isMain").get(0)).booleanValue()
389                     ) {
390                         if(effortEstimate.values("estimateEffortHours").size() > 0) {
391                             estimateEffortHours += ((Number JavaDoc)effortEstimate.values("estimateEffortHours").get(0)).intValue();
392                         }
393                         if(effortEstimate.values("estimateEffortMinutes").size() > 0) {
394                             estimateEffortMinutes += ((Number JavaDoc)effortEstimate.values("estimateEffortMinutes").get(0)).intValue();
395                         }
396                     }
397                 }
398             }
399         }
400         // Update tracker
401
refreshedTracker.clearValues("sumEstimateEffortHours").add(
402             new Integer JavaDoc(estimateEffortHours + estimateEffortMinutes / 60)
403         );
404         refreshedTracker.clearValues("sumEstimateEffortMinutes").add(
405             new Integer JavaDoc(estimateEffortMinutes % 60)
406         );
407         return refreshedTracker;
408     }
409     
410     //-------------------------------------------------------------------------
411
/**
412      * Creates a new activity and links the tracker with this new activity.
413      */

414     public Path newActivity(
415         ServiceHeader header,
416         Path activityCreatorIdentity,
417         String JavaDoc name,
418         String JavaDoc description,
419         String JavaDoc detailedDescription,
420         String JavaDoc suppliedScheduledStart,
421         String JavaDoc suppliedScheduledEnd,
422         String JavaDoc suppliedDueBy,
423         Number JavaDoc suppliedPriority,
424         Path reportingContactIdentity
425     ) throws ServiceException {
426         DataproviderObject_1_0 activityCreator = this.plugin.retrieveObjectFromDelegation(
427             activityCreatorIdentity
428         );
429         if(activityCreator.values("activityType").size() > 0) {
430             DataproviderObject_1_0 activityType = this.plugin.retrieveObjectFromDelegation(
431                 (Path)activityCreator.values("activityType").get(0)
432             );
433             DataproviderObject_1_0 activityProcess = this.plugin.retrieveObjectFromDelegation(
434                 (Path)activityType.values("controlledBy").get(0)
435             );
436             String JavaDoc scheduledStart = null;
437             try {
438                 scheduledStart = suppliedScheduledStart != null
439                     ? suppliedScheduledStart
440                     : (activityCreator.values("baseDate").size() > 0) && (activityCreator.values("scheduledStart").size() > 0)
441                         ? DateFormat.getInstance().format(new Date JavaDoc(System.currentTimeMillis() + (DateFormat.getInstance().parse((String JavaDoc)activityCreator.values("scheduledStart").get(0)).getTime() - DateFormat.getInstance().parse((String JavaDoc)activityCreator.values("baseDate").get(0)).getTime())))
442                         : null;
443             } catch(ParseException JavaDoc e) {}
444             String JavaDoc scheduledEnd = null;
445             try {
446                 scheduledEnd = suppliedScheduledEnd != null
447                     ? suppliedScheduledEnd
448                     : (activityCreator.values("baseDate").size() > 0) && (activityCreator.values("scheduledEnd").size() > 0)
449                         ? DateFormat.getInstance().format(new Date JavaDoc(System.currentTimeMillis() + (DateFormat.getInstance().parse((String JavaDoc)activityCreator.values("scheduledEnd").get(0)).getTime() - DateFormat.getInstance().parse((String JavaDoc)activityCreator.values("baseDate").get(0)).getTime())))
450                         : null;
451             } catch(ParseException JavaDoc e) {}
452             String JavaDoc dueBy = null;
453             try {
454                 dueBy = suppliedDueBy != null
455                     ? suppliedDueBy
456                     : (activityCreator.values("baseDate").size() > 0) && (activityCreator.values("dueBy").size() > 0)
457                         ? DateFormat.getInstance().format(new Date JavaDoc(System.currentTimeMillis() + (DateFormat.getInstance().parse((String JavaDoc)activityCreator.values("dueBy").get(0)).getTime() - DateFormat.getInstance().parse((String JavaDoc)activityCreator.values("baseDate").get(0)).getTime())))
458                         : null;
459             } catch(ParseException JavaDoc e) {}
460             short priority = suppliedPriority != null
461                 ? suppliedPriority.shortValue()
462                 : activityCreator.values("priority").size() > 0
463                     ? ((Number JavaDoc)activityCreator.values("priority").get(0)).shortValue()
464                     : (short)2; // NORMAL
465
Path newActivityIdentity = new Path("xri:@openmdx:org.opencrx.kernel.activity1/provider");
466             newActivityIdentity =
467                 newActivityIdentity.getDescendant(
468                     new String JavaDoc[]{
469                         activityCreator.path().get(2),
470                         "segment",
471                         activityCreator.path().get(4),
472                         "activity",
473                         this.plugin.getUidAsString()
474                     }
475                 );
476             DataproviderObject newActivity = new DataproviderObject(newActivityIdentity);
477             String JavaDoc activityClass = ACTIVITY_TYPES[((Number JavaDoc)activityType.values("activityClass").get(0)).intValue()];
478             newActivity.values(SystemAttributes.OBJECT_CLASS).add(activityClass);
479             if(name != null) {
480                 newActivity.values("name").add(name);
481             }
482             if(description != null) {
483                 newActivity.values("description").add(description);
484             }
485             if(detailedDescription != null) {
486                 newActivity.values("detailedDescription").add(detailedDescription);
487             }
488             if(scheduledStart != null) {
489                 newActivity.values("scheduledStart").add(scheduledStart);
490             }
491             if(scheduledEnd != null) {
492                 newActivity.values("scheduledEnd").add(scheduledEnd);
493             }
494             if(reportingContactIdentity != null) {
495                 newActivity.values("reportingContact").add(reportingContactIdentity);
496             }
497             else {
498                 DataproviderObject_1_0 userHome = this.plugin.getUserHome(header, newActivity.path());
499                 newActivity.values("reportingContact").addAll(
500                     userHome.values("contact")
501                 );
502             }
503             newActivity.values("priority").add(
504                 new Short JavaDoc(priority)
505             );
506             newActivity.values("dueBy").add(
507                 dueBy != null
508                     ? dueBy
509                     : MAX_DATE
510             );
511             newActivity.values("activityState").add(
512                 new Short JavaDoc((short)0)
513             );
514             newActivity.values("percentComplete").add(
515                 new Short JavaDoc((short)0)
516             );
517             newActivity.values("activityType").add(
518                 activityType.path()
519             );
520             newActivity.values("processState").addAll(
521                 activityProcess.values("startState")
522             );
523             // Set code values to 0 (non-optional attributes)
524
if("org:opencrx:kernel:activity1:Incident".equals(activityClass)) {
525                 newActivity.values("caseOrigin").add(new Short JavaDoc((short)0));
526                 newActivity.values("caseType").add(new Short JavaDoc((short)0));
527                 newActivity.values("customerSatisfaction").add(new Short JavaDoc((short)0));
528                 newActivity.values("severity").add(new Short JavaDoc((short)0));
529                 newActivity.values("reproducibility").add(new Short JavaDoc((short)0));
530             }
531             try {
532                 // Create activity
533
this.plugin.createObject(
534                     newActivity
535                 );
536                 this.reapplyActivityCreator(
537                     header,
538                     newActivity.path(),
539                     activityCreator.path()
540                 );
541                 return newActivityIdentity;
542             }
543             catch(ServiceException e) {
544                 SysLog.info("Creation of new activity failed", e.getCause(), 1);
545             }
546         }
547         return null;
548     }
549     
550     //-------------------------------------------------------------------------
551
public Path voteForActivity(
552         ServiceHeader header,
553         DataproviderObject_1_0 activity,
554         DataproviderObject params
555     ) throws ServiceException {
556         DataproviderObject vote = new DataproviderObject(
557             activity.path().getDescendant(new String JavaDoc[]{"vote", this.plugin.getUidAsString()})
558         );
559         vote.values(SystemAttributes.OBJECT_CLASS).add("org:opencrx:kernel:activity1:ActivityVote");
560         String JavaDoc name = (String JavaDoc)params.values("name").get(0);
561         String JavaDoc description = (String JavaDoc)params.values("description").get(0);
562         if(name != null) {
563             vote.values("name").add(name);
564         }
565         if(description != null) {
566             vote.values("description").add(description);
567         }
568         this.plugin.assignToMe(
569             header,
570             vote,
571             null,
572             true,
573             null
574         );
575         this.plugin.createObject(vote);
576         return vote.path();
577     }
578     
579     //-------------------------------------------------------------------------
580
public void doFollowUp(
581         ServiceHeader header,
582         Path activityIdentity,
583         String JavaDoc followUpTitle,
584         String JavaDoc followUpText,
585         Path processTransitionIdentity
586     ) throws ServiceException {
587
588         DataproviderObject_1_0 activity = this.plugin.retrieveObjectForModification(activityIdentity);
589         Path processStateIdentity = (Path)activity.values("processState").get(0);
590         if(processTransitionIdentity != null) {
591             DataproviderObject_1_0 processTransition = this.plugin.retrieveObjectFromDelegation(
592                 processTransitionIdentity
593             );
594             if(processTransition.values("nextState").size() == 0) {
595                 throw new ServiceException(
596                     OpenCrxException.DOMAIN,
597                     OpenCrxException.ACTIVITY_UNDEFINED_NEXT_STATE,
598                     new BasicException.Parameter[]{
599                         new BasicException.Parameter("param0", processTransition.path())
600                     },
601                     "Undefined next state. Transition not possible."
602                 );
603             }
604             // Check that previous state of transition matches the current activity's state
605
if(
606                 ((processTransition.values("prevState").size() == 0) && (processStateIdentity == null)) ||
607                 ((processTransition.values("prevState").size() > 0) && processTransition.values("prevState").get(0).equals(processStateIdentity))
608             ) {
609                 
610             }
611             else {
612                 throw new ServiceException(
613                     OpenCrxException.DOMAIN,
614                     OpenCrxException.ACTIVITY_TRANSITION_NOT_VALID_FOR_STATE,
615                     new BasicException.Parameter[]{
616                         new BasicException.Parameter("param0", processTransitionIdentity),
617                         new BasicException.Parameter("param1", processStateIdentity)
618                     },
619                     "Transition is not valid for current state"
620                 );
621             }
622             // Apply transition to activity
623
activity.clearValues("processState").add(
624                 processTransition.values("nextState").get(0)
625             );
626             activity.clearValues("lastTransition").add(
627                 processTransitionIdentity
628             );
629             activity.clearValues("percentComplete").addAll(
630                 processTransition.values("newPercentComplete")
631             );
632             activity.clearValues("activityState").addAll(
633                 processTransition.values("newActivityState")
634             );
635             
636             // Execute actions
637
List JavaDoc actions = this.delegation.addFindRequest(
638                 processTransitionIdentity.getChild("action"),
639                 null,
640                 AttributeSelectors.ALL_ATTRIBUTES,
641                 0,
642                 Integer.MAX_VALUE,
643                 Directions.ASCENDING
644             );
645             for(Iterator JavaDoc i = actions.iterator(); i.hasNext(); ) {
646                 DataproviderObject_1_0 action = (DataproviderObject_1_0)i.next();
647                 String JavaDoc actionClass = (String JavaDoc)action.values(SystemAttributes.OBJECT_CLASS).get(0);
648                 // SetActualEndAction
649
if(this.model.isSubtypeOf(actionClass, "org:opencrx:kernel:activity1:SetActualEndAction")) {
650                     if((action.values("resetToNull").size() > 0) && ((Boolean JavaDoc)action.values("resetToNull").get(0)).booleanValue()) {
651                         activity.clearValues("actualEnd");
652                     }
653                     else {
654                         activity.clearValues("actualEnd").add(
655                             DateFormat.getInstance().format(new Date JavaDoc())
656                         );
657                     }
658                 }
659                 // SetActualStartAction
660
else if(this.model.isSubtypeOf(actionClass, "org:opencrx:kernel:activity1:SetActualStartAction")) {
661                     if((action.values("resetToNull").size() > 0) && ((Boolean JavaDoc)action.values("resetToNull").get(0)).booleanValue()) {
662                         activity.clearValues("actualStart");
663                     }
664                     else {
665                         activity.clearValues("actualStart").add(
666                             DateFormat.getInstance().format(new Date JavaDoc())
667                         );
668                     }
669                 }
670                 // SetAssignedToAction
671
else if(this.model.isSubtypeOf(actionClass, "org:opencrx:kernel:activity1:SetAssignedToAction")) {
672                     List JavaDoc assignedResources = this.delegation.addFindRequest(
673                         activityIdentity.getChild("assignedResource"),
674                         null,
675                         AttributeSelectors.ALL_ATTRIBUTES,
676                         0,
677                         Integer.MAX_VALUE,
678                         Directions.ASCENDING
679                     );
680                     boolean assigned = false;
681                     // Try to find resource which matches specified contact
682
Path contactIdentity = null;
683                     if(
684                         (action.values("contactFeatureName").size() > 0) &&
685                         (activity.values((String JavaDoc)action.values("contactFeatureName").get(0)).size() > 0)
686                     ) {
687                         contactIdentity = (Path)activity.values((String JavaDoc)action.values("contactFeatureName").get(0)).get(0);
688                     }
689                     else {
690                         DataproviderObject_1_0 userHome = this.plugin.getUserHome(header, action.path());
691                         contactIdentity = (Path)userHome.values("contact").get(0);
692                     }
693                     if(contactIdentity != null) {
694                         for(Iterator JavaDoc j = assignedResources.iterator(); j.hasNext(); ) {
695                             DataproviderObject_1_0 assignedResource = (DataproviderObject_1_0)j.next();
696                             if(assignedResource.values("resource").size() > 0) {
697                                 DataproviderObject_1_0 resource = this.plugin.retrieveObjectFromDelegation(
698                                     (Path)assignedResource.values("resource").get(0)
699                                 );
700                                 if(
701                                     (resource.values("contact").size() > 0) &&
702                                     contactIdentity.equals(resource.values("contact").get(0))
703                                 ) {
704                                     this.assignTo(
705                                         header,
706                                         activityIdentity,
707                                         resource.path()
708                                     );
709                                     assigned = true;
710                                     break;
711                                 }
712                             }
713                         }
714                     }
715                     // Try to find resource with matching resource order
716
if(
717                         !assigned &&
718                         (action.values("resourceOrder").size() > 0)
719                     ) {
720                         for(Iterator JavaDoc j = assignedResources.iterator(); j.hasNext(); ) {
721                             DataproviderObject_1_0 assignedResource = (DataproviderObject_1_0)j.next();
722                             if(assignedResource.values("resourceOrder").size() > 0) {
723                                 short actionResourceOrder = ((Number JavaDoc)action.values("resourceOrder").get(0)).shortValue();
724                                 short assignmentResourceOrder = ((Number JavaDoc)assignedResource.values("resourceOrder").get(0)).shortValue();
725                                 if(
726                                     (actionResourceOrder == assignmentResourceOrder) &&
727                                     (assignedResource.values("resource").size() > 0)
728                                 ) {
729                                     this.assignTo(
730                                         header,
731                                         activityIdentity,
732                                         (Path)assignedResource.values("resource").get(0)
733                                     );
734                                     assigned = true;
735                                     break;
736                                 }
737                             }
738                         }
739                     }
740                     // Try to find resource with matching resource role
741
if(
742                         !assigned &&
743                         (action.values("resourceRole").size() > 0)
744                     ) {
745                         for(Iterator JavaDoc j = assignedResources.iterator(); j.hasNext(); ) {
746                             DataproviderObject_1_0 assignedResource = (DataproviderObject_1_0)j.next();
747                             if(assignedResource.values("resourceRole").size() > 0) {
748                                 short actionResourceRole = ((Number JavaDoc)action.values("resourceRole").get(0)).shortValue();
749                                 short assignmentResourceRole = ((Number JavaDoc)assignedResource.values("resourceRole").get(0)).shortValue();
750                                 if(
751                                     (actionResourceRole == assignmentResourceRole) &&
752                                     (assignedResource.values("resource").size() > 0)
753                                 ) {
754                                     this.assignTo(
755                                         header,
756                                         activityIdentity,
757                                         (Path)assignedResource.values("resource").get(0)
758                                     );
759                                     assigned = true;
760                                     break;
761                                 }
762                             }
763                         }
764                     }
765                 }
766                 // WfAction
767
else if(this.model.isSubtypeOf(actionClass, "org:opencrx:kernel:activity1:WfAction")) {
768                     DataproviderObject_1_0 userHome = this.plugin.getUserHome(header, action.path());
769                     if(action.values("wfProcess").size() > 0) {
770                         this.plugin.workflows.executeWorkflow(
771                             userHome,
772                             (Path)action.values("wfProcess").get(0),
773                             activityIdentity,
774                             null,
775                             null,
776                             null,
777                             null
778                         );
779                     }
780                 }
781                 // ActivityCreationAction
782
else if(this.model.isSubtypeOf(actionClass, "org:opencrx:kernel:activity1:ActivityCreationAction")) {
783                     if(action.values("activityCreator").size() > 0) {
784                         Path newActivityIdentity = this.newActivity(
785                             header,
786                             (Path)action.values("activityCreator").get(0),
787                             (String JavaDoc)action.values("activityName").get(0),
788                             (String JavaDoc)action.values("activityDescription").get(0),
789                             null,
790                             null,
791                             null,
792                             null,
793                             null,
794                             (Path)activity.values("reportingContact").get(0)
795                         );
796                         // Link new activity with original
797
DataproviderObject activityLinkTo = new DataproviderObject(
798                             newActivityIdentity.getDescendant(new String JavaDoc[]{"activityLinkTo", this.plugin.getUidAsString()})
799                         );
800                         activityLinkTo.values(SystemAttributes.OBJECT_CLASS).add("org:opencrx:kernel:activity1:ActivityLinkTo");
801                         activityLinkTo.values("name").addAll(
802                             activity.values("name")
803                         );
804                         activityLinkTo.values("activityLinkType").add(
805                             new Short JavaDoc(ACTIVITY_LINK_TYPE_IS_DERIVED_FROM)
806                         );
807                         activityLinkTo.values("linkTo").add(activityIdentity);
808                         this.plugin.createObject(
809                             activityLinkTo
810                         );
811                         // Postprocess created activity in case of an EMailCreationAction
812
if(this.model.isSubtypeOf(actionClass, "org:opencrx:kernel:activity1:EMailCreationAction")) {
813                             DataproviderObject emailActivity = this.plugin.retrieveObjectForModification(
814                                 newActivityIdentity
815                             );
816                             String JavaDoc emailActivityClass = (String JavaDoc)emailActivity.values(SystemAttributes.OBJECT_CLASS).get(0);
817                             if(this.model.isSubtypeOf(emailActivityClass, "org:opencrx:kernel:activity1:EMail")) {
818                                 // Copy recipients
819
List JavaDoc recipients = this.delegation.addFindRequest(
820                                     activityIdentity.getChild("emailRecipient"),
821                                     null,
822                                     AttributeSelectors.ALL_ATTRIBUTES,
823                                     0,
824                                     Integer.MAX_VALUE,
825                                     Directions.ASCENDING
826                                 );
827                                 for(
828                                     Iterator JavaDoc j = recipients.iterator();
829                                     j.hasNext();
830                                 ) {
831                                     DataproviderObject_1_0 recipient = (DataproviderObject_1_0)j.next();
832                                     this.plugin.cloneable.cloneAndUpdateReferences(
833                                         header,
834                                         recipient,
835                                         newActivityIdentity.getChild("emailRecipient"),
836                                         null,
837                                         "",
838                                         true
839                                     );
840                                 }
841                                 // Update name, description, subject, message
842
String JavaDoc messageSubject =
843                                     "" + emailActivity.values("name").get(0) + " " + activity.values("messageSubject").get(0);
844                                 emailActivity.clearValues("name").add(messageSubject);
845                                 emailActivity.clearValues("messageSubject").add(messageSubject);
846                                 emailActivity.clearValues("messageBody").add(
847                                     "" + emailActivity.values("description").get(0) + "\n" + activity.values("messageBody").get(0)
848                                 );
849                                 emailActivity.clearValues("description");
850                             }
851                         }
852                     }
853                 }
854                 // LinkedActivityFollowUpAction
855
else if(this.model.isSubtypeOf(actionClass, "org:opencrx:kernel:activity1:LinkedActivityFollowUpAction")) {
856                     List JavaDoc activityLinks = this.delegation.addFindRequest(
857                         activityIdentity.getChild("activityLinkTo"),
858                         null,
859                         AttributeSelectors.ALL_ATTRIBUTES,
860                         0,
861                         Integer.MAX_VALUE,
862                         Directions.ASCENDING
863                     );
864                     for(Iterator JavaDoc j = activityLinks.iterator(); j.hasNext(); ) {
865                         DataproviderObject_1_0 activityLink = (DataproviderObject_1_0)i.next();
866                         Number JavaDoc activityLinkType = (Number JavaDoc)activityLink.values("activityLinkType").get(0);
867                         Number JavaDoc actionActivityLinkType = (Number JavaDoc)action.values("activityLinkType").get(0);
868                         if(
869                             (activityLink.values("linkTo").size() > 0) &&
870                             (action.values("transition").size() > 0) &&
871                             (actionActivityLinkType != null) &&
872                             (activityLinkType != null) &&
873                             (actionActivityLinkType.shortValue() == activityLinkType.shortValue())
874                         ) {
875                             this.doFollowUp(
876                                 header,
877                                 (Path)activityLink.values("linkTo").get(0),
878                                 (String JavaDoc)action.values("transitionTitle").get(0),
879                                 (String JavaDoc)action.values("transitionText").get(0),
880                                 (Path)action.values("transition").get(0)
881                             );
882                         }
883                     }
884                 }
885             }
886         }
887         
888         // Create transition
889
DataproviderObject transition = new DataproviderObject(
890             activity.path().getDescendant(new String JavaDoc[]{"followUp", this.plugin.getUidAsString()})
891         );
892         transition.values(SystemAttributes.OBJECT_CLASS).add("org:opencrx:kernel:activity1:ActivityFollowUp");
893         transition.values("transition").add(processTransitionIdentity);
894         transition.values("title").add(followUpTitle);
895         transition.values("text").add(followUpText);
896         this.plugin.assignToMe(
897             header,
898             transition,
899             null,
900             true,
901             null
902         );
903         this.plugin.createObject(transition);
904     }
905         
906     //-------------------------------------------------------------------------
907
public void updateWorkRecord(
908         ServiceHeader header,
909         DataproviderObject workRecord,
910         DataproviderObject_1_0 oldValues
911     ) throws ServiceException {
912         if(this.plugin.isActivityWorkRecord(workRecord)) {
913             DateFormat dateFormat = DateFormat.getInstance();
914             String JavaDoc startedAt = workRecord.getValues("startedAt") != null
915                 ? (String JavaDoc)workRecord.values("startedAt").get(0)
916                 : (oldValues == null ? dateFormat.format(new Date JavaDoc()) : (String JavaDoc)oldValues.values("startedAt").get(0));
917             String JavaDoc endedAt = workRecord.getValues("endedAt") != null
918                 ? (String JavaDoc)workRecord.values("endedAt").get(0)
919                 : (oldValues == null ? dateFormat.format(new Date JavaDoc()) : (String JavaDoc)oldValues.values("endedAt").get(0));
920             Number JavaDoc durationHours = workRecord.getValues("durationHours") != null
921                 ? (Number JavaDoc)workRecord.values("durationHours").get(0)
922                 : (oldValues == null ? new Integer JavaDoc(0) : (Number JavaDoc)oldValues.values("durationHours").get(0));
923             Number JavaDoc durationMinutes = workRecord.getValues("durationMinutes") != null
924                 ? (Number JavaDoc)workRecord.values("durationMinutes").get(0)
925                 : (oldValues == null ? new Integer JavaDoc(0) : (Number JavaDoc)oldValues.values("durationMinutes").get(0));
926             Number JavaDoc pauseDurationHours = workRecord.getValues("pauseDurationHours") != null
927                 ? (Number JavaDoc)workRecord.values("pauseDurationHours").get(0)
928                 : (oldValues == null ? new Integer JavaDoc(0) : (Number JavaDoc)oldValues.values("pauseDurationHours").get(0));
929             Number JavaDoc pauseDurationMinutes = workRecord.getValues("pauseDurationMinutes") != null
930                 ? (Number JavaDoc)workRecord.values("pauseDurationMinutes").get(0)
931                 : (oldValues == null ? new Integer JavaDoc(0) : (Number JavaDoc)oldValues.values("pauseDurationMinutes").get(0));
932             durationHours = durationHours == null ? new Integer JavaDoc(0) : durationHours;
933             durationMinutes = durationMinutes == null ? new Integer JavaDoc(0) : durationMinutes;
934             pauseDurationHours = pauseDurationHours == null ? new Integer JavaDoc(0) : pauseDurationHours;
935             pauseDurationMinutes = pauseDurationMinutes == null ? new Integer JavaDoc(0) : pauseDurationMinutes;
936             
937             int durationCalculationMode = workRecord.getValues("durationCalculationMode") != null
938                 ? ((Number JavaDoc)workRecord.getValues("durationCalculationMode").get(0)).intValue()
939                 : (oldValues == null ? DURATION_CALCULATION_MODE_CALC_DURATION : ((Number JavaDoc)oldValues.values("durationCalculationMode").get(0)).intValue());
940
941             // Calculate duration
942
if(durationCalculationMode == DURATION_CALCULATION_MODE_CALC_DURATION) {
943                 long duration = 0;
944                 try {
945                     duration =
946                         dateFormat.parse(endedAt).getTime() - dateFormat.parse(startedAt).getTime() -
947                         pauseDurationHours.longValue() * 3600000 - pauseDurationMinutes.longValue() * 60000;
948                     durationHours = new Long JavaDoc(duration / 3600000);
949                     durationMinutes = new Long JavaDoc((duration % 3600000) / 60000);
950                     workRecord.clearValues("durationHours").add(durationHours);
951                     workRecord.clearValues("durationMinutes").add(durationMinutes);
952                 } catch(ParseException JavaDoc e) {}
953             }
954             // Calculate pause
955
else {
956                 long pauseDuration = 0;
957                 try {
958                     pauseDuration =
959                         dateFormat.parse(endedAt).getTime() - dateFormat.parse(startedAt).getTime() -
960                         durationHours.longValue() * 3600000 - durationMinutes.longValue() * 60000;
961                     pauseDurationHours = new Long JavaDoc(pauseDuration / 3600000);
962                     pauseDurationMinutes = new Long JavaDoc((pauseDuration % 3600000) / 60000);
963                     workRecord.clearValues("pauseDurationHours").add(pauseDurationHours);
964                     workRecord.clearValues("pauseDurationMinutes").add(pauseDurationMinutes);
965                 } catch(ParseException JavaDoc e) {}
966             }
967             // Billable amount
968
DataproviderObject_1_0 resourceAssignment = this.plugin.retrieveObjectFromDelegation(
969                 workRecord.path().getPrefix(workRecord.path().size() - 2)
970             );
971             // rateType
972
Number JavaDoc rateType = workRecord.getValues("rateType") != null
973                 ? (Number JavaDoc)workRecord.values("rateType").get(0)
974                 : (oldValues == null ? new Short JavaDoc(RATE_TYPE_NA): (Number JavaDoc)oldValues.values("rateType").get(0));
975             workRecord.clearValues("rateType").add(rateType);
976             // rate
977
DataproviderObject_1_0 resource = null;
978             if(resourceAssignment.values("resource").size() > 0) {
979                 resource = this.plugin.retrieveObjectFromDelegation(
980                     (Path)resourceAssignment.values("resource").get(0)
981                 );
982             }
983             BigDecimal JavaDoc rate = null;
984             if((rateType == null) || (rateType.shortValue() == RATE_TYPE_NA)) {
985                 rate = workRecord.getValues("rate") != null
986                     ? (BigDecimal JavaDoc)workRecord.values("rate").get(0)
987                     : (oldValues == null ? new BigDecimal JavaDoc(0) : (BigDecimal JavaDoc)oldValues.values("rate").get(0));
988             }
989             else if(rateType.shortValue() == RATE_TYPE_STANDARD) {
990                 rate = (BigDecimal JavaDoc)resource.values("standardRate").get(0);
991             }
992             else {
993                 rate = (BigDecimal JavaDoc)resource.values("overtimeRate").get(0);
994             }
995             if(rate == null) {
996                 rate = new BigDecimal JavaDoc(0);
997             }
998             boolean updateWorkCompoundBooking =
999                 (oldValues == null) ||
1000                (((Number JavaDoc)workRecord.values("durationHours").get(0)).intValue () != ((Number JavaDoc)oldValues.values("durationHours").get(0)).intValue()) ||
1001                (((Number JavaDoc)workRecord.values("durationMinutes").get(0)).intValue() != ((Number JavaDoc)oldValues.values("durationMinutes").get(0)).intValue());
1002            boolean updateBillableAmount =
1003                updateWorkCompoundBooking ||
1004                (rateType.intValue () != ((Number JavaDoc)oldValues.values("rateType").get(0)).intValue()) ||
1005                (oldValues.values("rate").size() == 0) ||
1006                (rate.doubleValue() != ((Number JavaDoc)oldValues.values("rate").get(0)).doubleValue());
1007            // Update billable amount if rate or rate type has been changed
1008
if(updateBillableAmount) {
1009                workRecord.clearValues("rate").add(rate);
1010                // billableAmount
1011
workRecord.clearValues("billableAmount").add(
1012                    rate.multiply(
1013                        new BigDecimal JavaDoc(durationHours.intValue())
1014                    ).add(
1015                        rate.multiply(new BigDecimal JavaDoc(durationMinutes.intValue()).divide(new BigDecimal JavaDoc(60), 2, BigDecimal.ROUND_DOWN))
1016                    )
1017                );
1018            }
1019            // Update work booking if duration has been changed
1020
if(updateWorkCompoundBooking) {
1021                if(workRecord.values("workCb").size() > 0) {
1022                    this.plugin.depots.removeCompoundBooking(
1023                        header,
1024                        (Path)workRecord.getValues("workCb").get(0)
1025                    );
1026                }
1027                // Depot credit
1028
// Get assigned depot of resource with usage DEPOT_USAGE_WORK_EFFORT
1029
DataproviderObject_1_0 depotCredit = null;
1030                Path resourceIdentity = (Path)resourceAssignment.values("resource").get(0);
1031                List JavaDoc depotReferences = null;
1032                if(resourceIdentity == null) {
1033                    depotReferences = Collections.EMPTY_LIST;
1034                }
1035                else {
1036                    depotReferences = this.delegation.addFindRequest(
1037                        resourceIdentity.getChild("depotReference"),
1038                        null,
1039                        AttributeSelectors.ALL_ATTRIBUTES,
1040                        0,
1041                        Integer.MAX_VALUE,
1042                        Directions.ASCENDING
1043                    );
1044                }
1045                for(
1046                    Iterator JavaDoc j = depotReferences.iterator();
1047                    j.hasNext();
1048                ) {
1049                    DataproviderObject_1_0 depotReference = (DataproviderObject_1_0)j.next();
1050                    Number JavaDoc depotUsage = (Number JavaDoc)depotReference.values("depotUsage").get(0);
1051                    if((depotUsage != null) && (depotUsage.shortValue() == Depots.DEPOT_USAGE_WORK_EFFORT)) {
1052                        depotCredit = this.plugin.retrieveObjectFromLocal(
1053                            header,
1054                            (Path)depotReference.values("depot").get(0)
1055                        );
1056                    }
1057                }
1058                // Depot debit
1059
// Get assigned depot of activity with usage DEPOT_USAGE_WORK_EFFORT
1060
DataproviderObject_1_0 depotDebit = null;
1061                DataproviderObject_1_0 activity = this.plugin.retrieveObjectFromDelegation(
1062                    workRecord.path().getPrefix(workRecord.path().size() - 4)
1063                );
1064                depotReferences = this.delegation.addFindRequest(
1065                    activity.path().getChild("depotReference"),
1066                    null,
1067                    AttributeSelectors.ALL_ATTRIBUTES,
1068                    0,
1069                    Integer.MAX_VALUE,
1070                    Directions.ASCENDING
1071                );
1072                for(
1073                    Iterator JavaDoc j = depotReferences.iterator();
1074                    j.hasNext();
1075                ) {
1076                    DataproviderObject_1_0 depotReference = (DataproviderObject_1_0)j.next();
1077                    Number JavaDoc depotUsage = (Number JavaDoc)depotReference.values("depotUsage").get(0);
1078                    if((depotUsage != null) && (depotUsage.shortValue() == Depots.DEPOT_USAGE_WORK_EFFORT)) {
1079                        depotDebit = this.plugin.retrieveObjectFromLocal(
1080                            header,
1081                            (Path)depotReference.values("depot").get(0)
1082                        );
1083                    }
1084                }
1085                Path activityTypeIdentity = (Path)activity.values("activityType").get(0);
1086                if(
1087                    (depotCredit != null) &&
1088                    (depotDebit != null) &&
1089                    (activityTypeIdentity != null)
1090                ) {
1091                    if(!depotCredit.path().getPrefix(7).equals(depotDebit.path().getPrefix(7))) {
1092                        throw new ServiceException(
1093                            OpenCrxException.DOMAIN,
1094                            OpenCrxException.DEPOT_POSITION_IS_LOCKED,
1095                            new BasicException.Parameter[]{
1096                                new BasicException.Parameter("param0", depotDebit.path()),
1097                                new BasicException.Parameter("param1", depotCredit.path())
1098                            },
1099                            "Depot entity not equal"
1100                        );
1101                    }
1102                    else {
1103                        DataproviderObject_1_0 activityType = this.plugin.retrieveObjectFromDelegation(
1104                            activityTypeIdentity
1105                        );
1106                        String JavaDoc valueDate = (String JavaDoc)workRecord.values("endedAt").get(0);
1107                        Path positionCreditIdentity = this.plugin.depots.openDepotPosition(
1108                            header,
1109                            depotCredit,
1110                            (String JavaDoc)activityType.values("name").get(0),
1111                            (String JavaDoc)activityType.values("description").get(0),
1112                            valueDate, // if position does not exist open latest at value date
1113
null,
1114                            null,
1115                            null,
1116                            Boolean.FALSE
1117                        ).path();
1118                        Path positionDebitIdentity = this.plugin.depots.openDepotPosition(
1119                            header,
1120                            depotDebit,
1121                            (String JavaDoc)activityType.values("name").get(0),
1122                            (String JavaDoc)activityType.values("description").get(0),
1123                            valueDate, // if position does not exist open latest at value date
1124
null,
1125                            null,
1126                            null,
1127                            Boolean.FALSE
1128                        ).path();
1129                        DataproviderObject_1_0 workCb =
1130                            this.plugin.depots.createCreditDebitBooking(
1131                                header,
1132                                depotCredit.path().getPrefix(7),
1133                                (String JavaDoc)workRecord.values("endedAt").get(0),
1134                                Depots.BOOKING_TYPE_STANDARD,
1135                                new BigDecimal JavaDoc(durationHours.intValue()).add(new BigDecimal JavaDoc(durationMinutes.intValue()).divide(new BigDecimal JavaDoc(60), 2, BigDecimal.ROUND_DOWN)),
1136                                BOOKING_TEXT_NAME_WORK_EFFORT,
1137                                (Path)activityType.values("workBt").get(0),
1138                                positionCreditIdentity,
1139                                positionDebitIdentity,
1140                                null,
1141                                workRecord.path(),
1142                                null
1143                            );
1144                        workRecord.clearValues("workCb").add(
1145                            workCb.path()
1146                        );
1147                    }
1148                }
1149            }
1150        }
1151    }
1152    
1153    //-------------------------------------------------------------------------
1154
public DataproviderObject addWorkRecord(
1155        ServiceHeader header,
1156        Path resourceIdentity,
1157        Path activityIdentity,
1158        String JavaDoc name,
1159        String JavaDoc description,
1160        String JavaDoc startedAt,
1161        String JavaDoc endedAt,
1162        Number JavaDoc durationHours,
1163        Number JavaDoc durationMinutes,
1164        Number JavaDoc pauseDurationHours,
1165        Number JavaDoc pauseDurationMinutes,
1166        Number JavaDoc rateType,
1167        short durationCalculationMode
1168    ) throws ServiceException {
1169        DataproviderObject workRecord = null;
1170        if(activityIdentity != null) {
1171            List JavaDoc resourceAssignments = this.delegation.addFindRequest(
1172                activityIdentity.getChild("assignedResource"),
1173                new FilterProperty[]{
1174                    new FilterProperty(
1175                        Quantors.THERE_EXISTS,
1176                        "resource",
1177                        FilterOperators.IS_IN,
1178                        new Object JavaDoc[]{resourceIdentity}
1179                    )
1180                }
1181            );
1182            if(resourceAssignments.size() > 0) {
1183                DataproviderObject_1_0 resource = this.plugin.retrieveObjectFromDelegation(
1184                    resourceIdentity
1185                );
1186                Path resourceAssignmentIdentity =
1187                    ((DataproviderObject_1_0)resourceAssignments.iterator().next()).path();
1188                workRecord = new DataproviderObject(
1189                    resourceAssignmentIdentity.getDescendant(new String JavaDoc[]{"workRecord", this.plugin.getUidAsString()})
1190                );
1191                workRecord.values(SystemAttributes.OBJECT_CLASS).add(
1192                    "org:opencrx:kernel:activity1:ActivityWorkRecord"
1193                );
1194                if(name != null) {
1195                    workRecord.values("name").add(name);
1196                }
1197                if(description != null) {
1198                    workRecord.values("description").add(description);
1199                }
1200                workRecord.values("startedAt").add(
1201                    startedAt == null
1202                        ? DateFormat.getInstance().format(new Date JavaDoc()).substring(0, 8) + "T000000.000Z"
1203                        : startedAt
1204                );
1205                Date JavaDoc startedAtAsDate = null;
1206                try {
1207                    startedAtAsDate = startedAt == null
1208                        ? null
1209                        : DateFormat.getInstance().parse(startedAt);
1210                }
1211                catch(ParseException JavaDoc e) {}
1212                workRecord.values("endedAt").add(
1213                    endedAt == null
1214                        ? startedAt == null
1215                            ? DateFormat.getInstance().format(new Date JavaDoc(System.currentTimeMillis() + 86400000L)).substring(0, 8) + "T000000.000Z"
1216                            : DateFormat.getInstance().format(new Date JavaDoc(startedAtAsDate.getTime() + 86400000L)).substring(0, 8) + "T000000.000Z"
1217                        : endedAt
1218                );
1219                if(durationHours != null) {
1220                    workRecord.values("durationHours").add(durationHours);
1221                }
1222                if(durationMinutes != null) {
1223                    workRecord.values("durationMinutes").add(durationMinutes);
1224                }
1225                if(pauseDurationHours != null) {
1226                    workRecord.values("pauseDurationHours").add(pauseDurationHours);
1227                }
1228                if(pauseDurationMinutes != null) {
1229                    workRecord.values("pauseDurationMinutes").add(pauseDurationMinutes);
1230                }
1231                workRecord.values("durationCalculationMode").add(
1232                    new Short JavaDoc(durationCalculationMode)
1233                );
1234                workRecord.values("isBillable").add(Boolean.TRUE);
1235                workRecord.values("billingCurrency").addAll(
1236                    resource.values("rateCurrency")
1237                );
1238                workRecord.values("rateType").add(
1239                    rateType == null
1240                        ? new Short JavaDoc(RATE_TYPE_NA)
1241                        : rateType
1242                );
1243                this.plugin.createObject(
1244                    workRecord
1245                );
1246                this.updateWorkRecord(
1247                    header,
1248                    this.plugin.retrieveObjectForModification(workRecord.path()),
1249                    null
1250                );
1251            }
1252        }
1253        return workRecord;
1254    }
1255    
1256    //-------------------------------------------------------------------------
1257
public DataproviderObject addWorkRecordByPeriod(
1258        ServiceHeader header,
1259        DataproviderObject_1_0 resource,
1260        DataproviderObject_1_0 params
1261    ) throws ServiceException {
1262        return this.addWorkRecord(
1263            header,
1264            resource.path(),
1265            (Path)params.values("activity").get(0),
1266            (String JavaDoc)params.values("name").get(0),
1267            (String JavaDoc)params.values("description").get(0),
1268            (String JavaDoc)params.values("startAt").get(0),
1269            (String JavaDoc)params.values("endAt").get(0),
1270            null,
1271            null,
1272            (Number JavaDoc)params.values("pauseDurationHours").get(0),
1273            (Number JavaDoc)params.values("pauseDurationMinutes").get(0),
1274            (Number JavaDoc)params.values("rateType").get(0),
1275            Activities.DURATION_CALCULATION_MODE_CALC_DURATION
1276        );
1277    }
1278    
1279    //-------------------------------------------------------------------------
1280
public DataproviderObject addWorkRecordByCalendar(
1281        ServiceHeader header,
1282        DataproviderObject_1_0 resource,
1283        DataproviderObject_1_0 params
1284    ) throws ServiceException {
1285        Path activityIdentity = (Path)params.values("activity").get(0);
1286        if(activityIdentity == null) return null;
1287        // Resource assignment
1288
List JavaDoc resourceAssignments = this.delegation.addFindRequest(
1289            activityIdentity.getChild("assignedResource"),
1290            new FilterProperty[]{
1291                new FilterProperty(
1292                    Quantors.THERE_EXISTS,
1293                    "resource",
1294                    FilterOperators.IS_IN,
1295                    new Object JavaDoc[]{resource.path()}
1296                )
1297            },
1298            AttributeSelectors.ALL_ATTRIBUTES,
1299            0,
1300            Integer.MAX_VALUE,
1301            Directions.ASCENDING
1302        );
1303        if(resourceAssignments.size() == 0) return null;
1304        DataproviderObject_1_0 resourceAssignment =
1305            (DataproviderObject_1_0)resourceAssignments.iterator().next();
1306        // Calendar
1307
Path calendarIdentity = resourceAssignment.values("calendar").size() > 0
1308            ? (Path)resourceAssignment.values("calendar").get(0)
1309            : (Path)resource.values("calendar").get(0);
1310        if(calendarIdentity == null) return null;
1311        String JavaDoc startAt = (String JavaDoc)params.values("startAt").get(0);
1312        GregorianCalendar JavaDoc currentCal = new GregorianCalendar JavaDoc(
1313            Integer.parseInt(startAt.substring(0, 4)),
1314            Integer.parseInt(startAt.substring(4, 6)) - 1,
1315            Integer.parseInt(startAt.substring(6, 8))
1316        );
1317        String JavaDoc endAt = (String JavaDoc)params.values("endAt").get(0);
1318        GregorianCalendar JavaDoc endAtCal = new GregorianCalendar JavaDoc(
1319            Integer.parseInt(endAt.substring(0, 4)),
1320            Integer.parseInt(endAt.substring(4, 6)) - 1,
1321            Integer.parseInt(endAt.substring(6, 8))
1322        );
1323        // workDurationPercentage
1324
int workDurationPercentage = resourceAssignment.values("workDurationPercentage").size() > 0
1325            ? ((Number JavaDoc)resourceAssignment.values("workDurationPercentage").get(0)).intValue()
1326            : 0;
1327        // Create a work record entry for each working calendar day
1328
int count = 0;
1329        DataproviderObject workRecord = null;
1330        while(!currentCal.after(endAtCal)) {
1331            DataproviderObject_1_0 workingDay =
1332                this.findWorkingDay(
1333                    calendarIdentity,
1334                    currentCal
1335                );
1336            if(
1337                (workingDay != null) &&
1338                (workingDay.values("isWorkingDay").size() > 0) &&
1339                ((Boolean JavaDoc)workingDay.values("isWorkingDay").get(0)).booleanValue()
1340            ) {
1341                int workDurationHours =
1342                    (workDurationPercentage * ((Number JavaDoc)workingDay.values("workDurationHours").get(0)).intValue()) / 100;
1343                int workDurationMinutes =
1344                    (workDurationPercentage * ((Number JavaDoc)workingDay.values("workDurationMinutes").get(0)).intValue()) / 100;
1345                workDurationHours += workDurationMinutes / 60;
1346                workDurationMinutes %= 60;
1347                if(
1348                    (workDurationHours > 0) ||
1349                    (workDurationMinutes > 0)
1350                ) {
1351                    int year = currentCal.get(GregorianCalendar.YEAR);
1352                    int month = currentCal.get(GregorianCalendar.MONTH) + 1;
1353                    int day = currentCal.get(GregorianCalendar.DAY_OF_MONTH);
1354                    String JavaDoc currentDate = "" +
1355                        year +
1356                        (month < 10 ? "0" : "") + month +
1357                        (day < 10 ? "0" : "") + day;
1358                    int workHourStartAt = java.lang.Math.max(0, (24 - (workDurationHours + 1)) / 2);
1359                    int workHoursEndAt = java.lang.Math.min(23, workHourStartAt + workDurationHours + 1);
1360                    workRecord =
1361                        this.addWorkRecord(
1362                            header,
1363                            resource.path(),
1364                            activityIdentity,
1365                            (String JavaDoc)params.values("name").get(0) + " #" + count,
1366                            (String JavaDoc)params.values("description").get(0),
1367                            currentDate + "T" + (workHourStartAt < 10 ? "0" : "") + workHourStartAt + "0000.000Z",
1368                            currentDate + "T" + (workHoursEndAt < 10 ? "0" : "") + workHoursEndAt + "0000.000Z",
1369                            new Integer JavaDoc(workDurationHours),
1370                            new Integer JavaDoc(workDurationMinutes),
1371                            null,
1372                            null,
1373                            (Number JavaDoc)params.values("rateType").get(0),
1374                            Activities.DURATION_CALCULATION_MODE_CALC_PAUSE
1375                        );
1376                    count++;
1377                }
1378            }
1379            currentCal.add(
1380                GregorianCalendar.DAY_OF_MONTH,
1381                1
1382            );
1383        }
1384        return workRecord;
1385    }
1386    
1387    //-------------------------------------------------------------------------
1388
public DataproviderObject addWorkRecordByDuration(
1389        ServiceHeader header,
1390        DataproviderObject_1_0 resource,
1391        DataproviderObject_1_0 params
1392    ) throws ServiceException {
1393        return this.addWorkRecord(
1394            header,
1395            resource.path(),
1396            (Path)params.values("activity").get(0),
1397            (String JavaDoc)params.values("name").get(0),
1398            (String JavaDoc)params.values("description").get(0),
1399            // startAt: org::w3c::date
1400
params.values("startAt").size() > 0
1401                ? params.values("startAt").get(0) + "T000000.000Z"
1402                : null,
1403            // endAt: org::w3c::date
1404
params.values("endAt").size() > 0
1405                ? params.values("endAt").get(0) + "T000000.000Z"
1406                : null,
1407            (Number JavaDoc)params.values("durationHours").get(0),
1408            (Number JavaDoc)params.values("durationMinutes").get(0),
1409            null,
1410            null,
1411            (Number JavaDoc)params.values("rateType").get(0),
1412            Activities.DURATION_CALCULATION_MODE_CALC_PAUSE
1413        );
1414    }
1415    
1416    //-------------------------------------------------------------------------
1417
public void removeWorkRecord(
1418        ServiceHeader header,
1419        Path workRecordIdentity
1420    ) throws ServiceException {
1421        DataproviderObject_1_0 workRecord = this.plugin.retrieveObjectFromDelegation(workRecordIdentity);
1422        if(workRecord.values("workCb").size() > 0) {
1423            this.plugin.depots.removeCompoundBooking(
1424                header,
1425                (Path)workRecord.values("workCb").get(0)
1426            );
1427            this.plugin.removeObject(
1428                workRecordIdentity
1429            );
1430        }
1431    }
1432    
1433    //-------------------------------------------------------------------------
1434
public void removeActivityGroup(
1435        ServiceHeader header,
1436        Path activityGroupIdentity
1437    ) throws ServiceException {
1438        List JavaDoc activities = this.delegation.addFindRequest(
1439            activityGroupIdentity.getChild("filteredActivity"),
1440            null
1441        );
1442        // Don't allow removal if activity group has assigned activities
1443
if(activities.size() > 0) {
1444            throw new ServiceException(
1445                OpenCrxException.DOMAIN,
1446                OpenCrxException.ACTIVITY_GROUP_HAS_ASSIGNED_ACTIVITIES,
1447                new BasicException.Parameter[]{
1448                    new BasicException.Parameter("param0", activityGroupIdentity)
1449                },
1450                "Activity group has assigned activities. Can not remove."
1451            );
1452        }
1453        else {
1454            this.plugin.removeObject(
1455                activityGroupIdentity
1456            );
1457        }
1458    }
1459    
1460    //-------------------------------------------------------------------------
1461
public void updateActivity(
1462        DataproviderObject object,
1463        DataproviderObject_1_0 oldValues
1464    ) throws ServiceException {
1465        if(this.plugin.isActivity(object)) {
1466            if(oldValues != null) {
1467                List JavaDoc votes = this.delegation.addFindRequest(
1468                    object.path().getChild("vote"),
1469                    null,
1470                    AttributeSelectors.ALL_ATTRIBUTES,
1471                    0, Integer.MAX_VALUE, Directions.ASCENDING
1472                );
1473                object.clearValues("totalVotes").add(
1474                    new Integer JavaDoc(votes.size())
1475                );
1476            }
1477            if(oldValues == null) {
1478                // init dueBy on creation
1479
if((object.getValues("dueBy") == null) || (object.values("dueBy").size() == 0)) {
1480                    object.clearValues("dueBy").add(MAX_DATE);
1481                }
1482                // init percentComplete on creation
1483
if((object.getValues("percentComplete") == null) || (object.values("percentComplete").size() == 0)) {
1484                    object.clearValues("percentComplete").add(new Short JavaDoc((short)0));
1485                }
1486            }
1487        }
1488    }
1489        
1490    //-------------------------------------------------------------------------
1491
public void reapplyActivityCreator(
1492        ServiceHeader header,
1493        Path activityIdentity,
1494        Path activityCreatorIdentity
1495    ) throws ServiceException {
1496        if(activityCreatorIdentity != null) {
1497            DataproviderObject_1_0 activityCreator = this.plugin.retrieveObjectFromDelegation(
1498                activityCreatorIdentity
1499            );
1500            Path activityTypeIdentity = (Path)activityCreator.values("activityType").get(0);
1501            if(activityTypeIdentity != null) {
1502                DataproviderObject_1_0 activityType = this.plugin.retrieveObjectFromDelegation(
1503                    activityTypeIdentity
1504                );
1505                DataproviderObject activity = this.plugin.retrieveObjectForModification(
1506                    activityIdentity
1507                );
1508                // Type of activity must match defined activity class
1509
if(
1510                    ACTIVITY_TYPES[((Number JavaDoc)activityType.values("activityClass").get(0)).intValue()].equals(
1511                        activity.values(SystemAttributes.OBJECT_CLASS).get(0)
1512                    )
1513                ) {
1514                    // Replace owning groups. The owning groups of the activity is the
1515
// the union of all owning groups of the assigned activity groups.
1516
// This way it is guaranteed that the activity can be viewed in all
1517
// assigned activity groups.
1518
List JavaDoc activityGroupsIdentities = activityCreator.values("activityGroup");
1519                    Set JavaDoc owningGroups = new HashSet JavaDoc();
1520                    for(Iterator JavaDoc i = activityGroupsIdentities.iterator(); i.hasNext(); ) {
1521                        DataproviderObject_1_0 activityGroup = this.plugin.retrieveObjectFromDelegation(
1522                            (Path)i.next()
1523                        );
1524                        owningGroups.addAll(
1525                            activityGroup.values("owningGroup")
1526                        );
1527                    }
1528                    activity.clearValues("owningGroup").addAll(
1529                        owningGroups
1530                    );
1531                    
1532                    // Create GroupAssignments
1533
// Remove already assigned activity groups from list to be added
1534
List JavaDoc existingGroupAssignments = this.delegation.addFindRequest(
1535                        activityIdentity.getChild("assignedGroup"),
1536                        null,
1537                        AttributeSelectors.ALL_ATTRIBUTES,
1538                        0,
1539                        Integer.MAX_VALUE,
1540                        Directions.ASCENDING
1541                    );
1542                    List JavaDoc excludes = new ArrayList JavaDoc();
1543                    for(Iterator JavaDoc i = existingGroupAssignments.iterator(); i.hasNext(); ) {
1544                        DataproviderObject_1_0 existingGroupAssignment = (DataproviderObject_1_0)i.next();
1545                        if(existingGroupAssignment.values("activityGroup").size() > 0) {
1546                            excludes.add(
1547                                existingGroupAssignment.values("activityGroup").get(0)
1548                            );
1549                        }
1550                    }
1551                    // Add new group assignments
1552
for(Iterator JavaDoc i = activityGroupsIdentities.iterator(); i.hasNext(); ) {
1553                        Path activityGroupIdentity = (Path)i.next();
1554                        if(!excludes.contains(activityGroupIdentity)) {
1555                            DataproviderObject activityGroupAssignment = new DataproviderObject(
1556                                activityIdentity.getDescendant(new String JavaDoc[]{"assignedGroup", this.plugin.getUidAsString()})
1557                            );
1558                            activityGroupAssignment.values(SystemAttributes.OBJECT_CLASS).add(
1559                                "org:opencrx:kernel:activity1:ActivityGroupAssignment"
1560                            );
1561                            activityGroupAssignment.values("activityGroup").add(
1562                                activityGroupIdentity
1563                            );
1564                            this.plugin.createObject(
1565                                activityGroupAssignment
1566                            );
1567                        }
1568                    }
1569                    // Create ResourceAssignments
1570
List JavaDoc resources = new ArrayList JavaDoc();
1571                    if(activityCreator.values("resource").size() > 0) {
1572                        resources = activityCreator.values("resource");
1573                    }
1574                    else {
1575                        // Try to find resource matching the current user
1576
List JavaDoc allResources = this.delegation.addFindRequest(
1577                            activityIdentity.getPrefix(5).getChild("resource"),
1578                            new FilterProperty[]{
1579                                new FilterProperty(
1580                                    Quantors.THERE_EXISTS,
1581                                    "contact",
1582                                    FilterOperators.IS_IN,
1583                                    new Object JavaDoc[]{this.plugin.getUserHome(header, activityIdentity).values("contact").get(0)}
1584                                )
1585                            }
1586                        );
1587                        if(allResources.size() > 0) {
1588                            resources.add(
1589                                ((DataproviderObject_1_0)allResources.iterator().next()).path()
1590                            );
1591                        }
1592                    }
1593                    // Remove already assigned resources from list to be added
1594
List JavaDoc existingResourceAssignments = this.delegation.addFindRequest(
1595                        activityIdentity.getChild("assignedResource"),
1596                        null,
1597                        AttributeSelectors.ALL_ATTRIBUTES,
1598                        0,
1599                        Integer.MAX_VALUE,
1600                        Directions.ASCENDING
1601                    );
1602                    excludes = new ArrayList JavaDoc();
1603                    for(Iterator JavaDoc i = existingResourceAssignments.iterator(); i.hasNext(); ) {
1604                        DataproviderObject_1_0 existingResourceAssignment = (DataproviderObject_1_0)i.next();
1605                        if(existingResourceAssignment.values("resource").size() > 0) {
1606                            excludes.add(
1607                                existingResourceAssignment.values("resource").get(0)
1608                            );
1609                        }
1610                    }
1611                    int ii = 0;
1612                    for(Iterator JavaDoc i = resources.iterator(); i.hasNext(); ii++) {
1613                        Path resourceIdentity = (Path)i.next();
1614                        if(!excludes.contains(resourceIdentity)) {
1615                            DataproviderObject_1_0 resource = this.plugin.retrieveObjectFromDelegation(
1616                                resourceIdentity
1617                            );
1618                            DataproviderObject resourceAssignment = new DataproviderObject(
1619                                activityIdentity.getDescendant(new String JavaDoc[]{"assignedResource", this.plugin.getUidAsString()})
1620                            );
1621                            resourceAssignment.values(SystemAttributes.OBJECT_CLASS).add(
1622                                "org:opencrx:kernel:activity1:ResourceAssignment"
1623                            );
1624                            resourceAssignment.values("name").addAll(
1625                                resource.values("name")
1626                            );
1627                            resourceAssignment.values("description").add(
1628                                "#" + activity.values("activityNumber").get(0) + ": " +
1629                                (activity.values("name").size() > 0 ? activity.values("name").get(0) : "")
1630                            );
1631                            resourceAssignment.values("resource").add(
1632                                resourceIdentity
1633                            );
1634                            resourceAssignment.values("resourceRole").add(
1635                                new Short JavaDoc((short)0)
1636                            );
1637                            resourceAssignment.values("resourceOrder").add(
1638                                new Short JavaDoc((short)ii)
1639                            );
1640                            resourceAssignment.values("workDurationPercentage").add(
1641                                new Short JavaDoc((short)100)
1642                            );
1643                            this.plugin.createObject(
1644                                resourceAssignment
1645                            );
1646                        }
1647                    }
1648                    // Create depot references
1649
List JavaDoc existingDepotReferences = this.delegation.addFindRequest(
1650                        activityIdentity.getChild("depotReference"),
1651                        null,
1652                        AttributeSelectors.ALL_ATTRIBUTES,
1653                        0,
1654                        Integer.MAX_VALUE,
1655                        Directions.ASCENDING
1656                    );
1657                    excludes = new ArrayList JavaDoc();
1658                    for(Iterator JavaDoc i = existingDepotReferences.iterator(); i.hasNext(); ) {
1659                        DataproviderObject_1_0 existingDepotReference = (DataproviderObject_1_0)i.next();
1660                        excludes.add(
1661                            new Short JavaDoc(((Number JavaDoc)existingDepotReference.values("depotUsage").get(0)).shortValue())
1662                        );
1663                    }
1664                    List JavaDoc depotReferences = this.delegation.addFindRequest(
1665                        activityCreator.path().getChild("depotReference"),
1666                        null,
1667                        AttributeSelectors.ALL_ATTRIBUTES,
1668                        0,
1669                        Integer.MAX_VALUE,
1670                        Directions.ASCENDING
1671                    );
1672                    for(
1673                        Iterator JavaDoc i = depotReferences.iterator();
1674                        i.hasNext();
1675                    ) {
1676                        DataproviderObject_1_0 depotReference = (DataproviderObject_1_0)i.next();
1677                        if(!excludes.contains(new Short JavaDoc(((Number JavaDoc)depotReference.values("depotUsage").get(0)).shortValue()))) {
1678                            this.plugin.cloneable.cloneAndUpdateReferences(
1679                                header,
1680                                depotReference,
1681                                activityIdentity.getChild("depotReference"),
1682                                null,
1683                                "",
1684                                true
1685                            );
1686                        }
1687                    }
1688                    // Set processState, lastTransition
1689
activity.clearValues("activityType").add(
1690                        activityTypeIdentity
1691                    );
1692                    activity.clearValues("processState");
1693                    activity.clearValues("lastTransition");
1694                    if(activityType.values("controlledBy").size() > 0) {
1695                        DataproviderObject_1_0 activityProcess = this.plugin.retrieveObjectFromDelegation(
1696                            (Path)activityType.values("controlledBy").get(0)
1697                        );
1698                        // Try to find transition which most closely matches the current activity
1699
// completeness and state. If no transition can be found set to start transition.
1700
DataproviderObject_1_0 lastTransition = null;
1701                        Path processStateIdentity = null;
1702                        if(activity.values("percentComplete").size() > 0) {
1703                            List JavaDoc transitions =
1704                                this.delegation.addFindRequest(
1705                                    activityProcess.path().getChild("transition"),
1706                                    new FilterProperty[]{
1707                                        new FilterProperty(
1708                                            Quantors.THERE_EXISTS,
1709                                            "newPercentComplete",
1710                                            FilterOperators.IS_IN,
1711                                            new Object JavaDoc[]{activity.values("percentComplete").get(0)}
1712                                        )
1713                                    },
1714                                    AttributeSelectors.ALL_ATTRIBUTES,
1715                                    0,
1716                                    Integer.MAX_VALUE,
1717                                    Directions.ASCENDING
1718                                );
1719                            if(transitions.size() > 0) {
1720                                lastTransition = (DataproviderObject_1_0)transitions.iterator().next();
1721                                processStateIdentity = (Path)lastTransition.values("nextState").get(0);
1722                            }
1723                        }
1724                        if(
1725                            (lastTransition == null) &&
1726                            (activity.values("activityState").size() > 0)
1727                        ) {
1728                            List JavaDoc transitions =
1729                                this.delegation.addFindRequest(
1730                                    activityProcess.path().getChild("transition"),
1731                                    new FilterProperty[]{
1732                                        new FilterProperty(
1733                                            Quantors.THERE_EXISTS,
1734                                            "newActivityState",
1735                                            FilterOperators.IS_IN,
1736                                            new Object JavaDoc[]{activity.values("activityState").get(0)}
1737                                        )
1738                                    },
1739                                    AttributeSelectors.ALL_ATTRIBUTES,
1740                                    0,
1741                                    Integer.MAX_VALUE,
1742                                    Directions.ASCENDING
1743                                );
1744                            if(transitions.size() > 0) {
1745                                lastTransition = (DataproviderObject_1_0)transitions.iterator().next();
1746                                processStateIdentity = (Path)lastTransition.values("nextState").get(0);
1747                            }
1748                        }
1749                        if(lastTransition == null) {
1750                            lastTransition = null;
1751                            processStateIdentity = (Path)activityProcess.values("startState").get(0);
1752                        }
1753                        if(processStateIdentity != null) {
1754                            activity.values("processState").add(processStateIdentity);
1755                        }
1756                        if(lastTransition != null) {
1757                            activity.values("lastTransition").add(lastTransition.path());
1758                            activity.clearValues("percentComplete").addAll(lastTransition.values("newPercentComplete"));
1759                            activity.clearValues("activityState").addAll(lastTransition.values("newActivityState"));
1760                        }
1761                    }
1762                }
1763            }
1764        }
1765    }
1766    
1767    //-------------------------------------------------------------------------
1768
public FilterProperty[] getActivityFilterProperties(
1769        Path activityFilterIdentity
1770    ) throws ServiceException {
1771        List JavaDoc filterProperties = this.delegation.addFindRequest(
1772            activityFilterIdentity.getChild("filterProperty"),
1773            null,
1774            AttributeSelectors.ALL_ATTRIBUTES,
1775            null,
1776            0,
1777            Integer.MAX_VALUE,
1778            Directions.ASCENDING
1779        );
1780        List JavaDoc filter = new ArrayList JavaDoc();
1781        for(
1782            Iterator JavaDoc i = filterProperties.iterator();
1783            i.hasNext();
1784        ) {
1785            DataproviderObject_1_0 filterProperty = (DataproviderObject_1_0)i.next();
1786            String JavaDoc filterPropertyClass = (String JavaDoc)filterProperty.values(SystemAttributes.OBJECT_CLASS).get(0);
1787
1788            Boolean JavaDoc isActive = (Boolean JavaDoc)filterProperty.values("isActive").get(0);
1789            
1790            if((isActive != null) && isActive.booleanValue()) {
1791                // Get filterOperator, filterQuantor
1792
short filterOperator = filterProperty.values("filterOperator").size() == 0
1793                    ? FilterOperators.IS_IN
1794                    : ((Number JavaDoc)filterProperty.values("filterOperator").get(0)).shortValue();
1795                filterOperator = filterOperator == 0
1796                    ? FilterOperators.IS_IN
1797                    : filterOperator;
1798                short filterQuantor = filterProperty.values("filterQuantor").size() == 0
1799                    ? Quantors.THERE_EXISTS
1800                    : ((Number JavaDoc)filterProperty.values("filterQuantor").get(0)).shortValue();
1801                filterQuantor = filterQuantor == 0
1802                    ? Quantors.THERE_EXISTS
1803                    : filterQuantor;
1804                
1805                if("org:opencrx:kernel:activity1:ActivityStateFilterProperty".equals(filterPropertyClass)) {
1806                    filter.add(
1807                        new FilterProperty(
1808                            filterQuantor,
1809                            "activityState",
1810                            filterOperator,
1811                            filterProperty.values("activityState").toArray()
1812                        )
1813                    );
1814                }
1815                else if("org:opencrx:kernel:activity1:ResourceNameFilterProperty".equals(filterPropertyClass)) {
1816                    filter.add(
1817                        new FilterProperty(
1818                            filterQuantor,
1819                            "p$$resourceName",
1820                            filterOperator,
1821                            filterProperty.values("resourceName").toArray()
1822                        )
1823                    );
1824                }
1825                else if("org:opencrx:kernel:activity1:ResourceRoleFilterProperty".equals(filterPropertyClass)) {
1826                    filter.add(
1827                        new FilterProperty(
1828                            filterQuantor,
1829                            "p$$resourceRole",
1830                            filterOperator,
1831                            filterProperty.values("resourceRole").toArray()
1832                        )
1833                    );
1834                }
1835                else if("org:opencrx:kernel:activity1:ScheduledStartFilterProperty".equals(filterPropertyClass)) {
1836                    filter.add(
1837                        new FilterProperty(
1838                            filterQuantor,
1839                            "scheduledStart",
1840                            filterOperator,
1841                            filterProperty.values("scheduledStart").toArray()
1842                        )
1843                    );
1844                }
1845                else if("org:opencrx:kernel:activity1:ScheduledEndFilterProperty".equals(filterPropertyClass)) {
1846                    filter.add(
1847                        new FilterProperty(
1848                            filterQuantor,
1849                            "scheduledEnd",
1850                            filterOperator,
1851                            filterProperty.values("scheduledEnd").toArray()
1852                        )
1853                    );
1854                }
1855                else if("org:opencrx:kernel:activity1:ActivityProcessStateFilterProperty".equals(filterPropertyClass)) {
1856                    filter.add(
1857                        new FilterProperty(
1858                            filterQuantor,
1859                            "processState",
1860                            filterOperator,
1861                            filterProperty.values("processState").toArray()
1862                        )
1863                    );
1864                }
1865                else if("org:opencrx:kernel:activity1:ActivityTypeFilterProperty".equals(filterPropertyClass)) {
1866                    filter.add(
1867                        new FilterProperty(
1868                            filterQuantor,
1869                            "activityType",
1870                            filterOperator,
1871                            filterProperty.values("activityType").toArray()
1872                        )
1873                    );
1874                }
1875                else if("org:opencrx:kernel:activity1:ResourceFilterProperty".equals(filterPropertyClass)) {
1876                    filter.add(
1877                        new FilterProperty(
1878                            filterQuantor,
1879                            "p$$resource",
1880                            filterOperator,
1881                            filterProperty.values("resource").toArray()
1882                        )
1883                    );
1884                }
1885                else if("org:opencrx:kernel:activity1:ActivityGroupFilterProperty".equals(filterPropertyClass)) {
1886                    filter.add(
1887                        new FilterProperty(
1888                            filterQuantor,
1889                            "p$$activityGroup",
1890                            filterOperator,
1891                            filterProperty.values("activityGroup").toArray()
1892                        )
1893                    );
1894                }
1895                else if("org:opencrx:kernel:activity1:ActivityNumberFilterProperty".equals(filterPropertyClass)) {
1896                    filter.add(
1897                        new FilterProperty(
1898                            filterQuantor,
1899                            "activityNumber",
1900                            filterOperator,
1901                            filterProperty.values("activityNumber").toArray()
1902                        )
1903                    );
1904                }
1905            }
1906        }
1907        return (FilterProperty[])filter.toArray(new FilterProperty[filter.size()]);
1908    }
1909    
1910    //-------------------------------------------------------------------------
1911
public DataproviderObject_1_0 findWorkingDay(
1912        Path calendarIdentity,
1913        GregorianCalendar JavaDoc dateOfDayAsCal
1914    ) throws ServiceException {
1915        int year = dateOfDayAsCal.get(GregorianCalendar.YEAR);
1916        int month = dateOfDayAsCal.get(GregorianCalendar.MONTH) + 1;
1917        int day = dateOfDayAsCal.get(GregorianCalendar.DAY_OF_MONTH);
1918        String JavaDoc dateOfDay = "" +
1919            year +
1920            (month < 10 ? "0" : "") + month +
1921            (day < 10 ? "0" : "") + day;
1922        // Test for CalendarDay
1923
List JavaDoc days =
1924            this.delegation.addFindRequest(
1925                calendarIdentity.getChild("calendarDay"),
1926                new FilterProperty[]{
1927                    new FilterProperty(
1928                        Quantors.THERE_EXISTS,
1929                        "dateOfDay",
1930                        FilterOperators.IS_IN,
1931                        new String JavaDoc[]{dateOfDay}
1932                    )
1933                },
1934                AttributeSelectors.ALL_ATTRIBUTES,
1935                0,
1936                Integer.MAX_VALUE,
1937                Directions.ASCENDING
1938            );
1939        if(days.size() > 0) {
1940            return (DataproviderObject_1_0)days.iterator().next();
1941        }
1942        // Test for WeekDay. Sunday = 1
1943
int dayOfWeek =
1944            dateOfDayAsCal.get(GregorianCalendar.DAY_OF_WEEK) - dateOfDayAsCal.getFirstDayOfWeek() + 1;
1945        days =
1946            this.delegation.addFindRequest(
1947                calendarIdentity.getChild("weekDay"),
1948                new FilterProperty[]{
1949                    new FilterProperty(
1950                        Quantors.THERE_EXISTS,
1951                        "dayOfWeek",
1952                        FilterOperators.IS_IN,
1953                        new Number JavaDoc[]{new Short JavaDoc((short)dayOfWeek)}
1954                    )
1955                },
1956                AttributeSelectors.ALL_ATTRIBUTES,
1957                0,
1958                Integer.MAX_VALUE,
1959                Directions.ASCENDING
1960            );
1961        if(days.size() > 0) {
1962            return (DataproviderObject_1_0)days.iterator().next();
1963        }
1964        // Not found. Lookup in base calendar
1965
DataproviderObject_1_0 calendar = this.plugin.retrieveObjectFromDelegation(
1966            calendarIdentity
1967        );
1968        if(calendar.values("baseCalendar").size() > 0) {
1969            return this.findWorkingDay(
1970                (Path)calendar.values("baseCalendar").get(0),
1971                dateOfDayAsCal
1972            );
1973        }
1974        return null;
1975    }
1976    
1977    //-------------------------------------------------------------------------
1978
public void assignTo(
1979        ServiceHeader header,
1980        Path activityIdentity,
1981        Path resourceIdentity
1982    ) throws ServiceException {
1983        if(resourceIdentity != null) {
1984            DataproviderObject activity = this.plugin.retrieveObjectForModification(
1985                activityIdentity
1986            );
1987            DataproviderObject_1_0 resource = this.plugin.retrieveObjectFromDelegation(
1988                resourceIdentity
1989            );
1990            Path contactIdentity = (Path)resource.values("contact").get(0);
1991            activity.clearValues("assignedTo").add(
1992                contactIdentity
1993            );
1994        }
1995    }
1996
1997    //-------------------------------------------------------------------------
1998
public void completeActualEffort(
1999        ServiceHeader header,
2000        DataproviderObject_1_0 target,
2001        String JavaDoc filterAttribute,
2002        Set JavaDoc fetchSet
2003    ) throws ServiceException {
2004        
2005        // Actual effort
2006
if(
2007            (fetchSet == null) || fetchSet.contains("actualEffortHours") || fetchSet.contains("actualEffortMinutes")
2008        ) {
2009            List JavaDoc workReportEntries = this.delegation.addFindRequest(
2010                target.path().getPrefix(5).getChild("workReportEntry"),
2011                new FilterProperty[]{
2012                    new FilterProperty(
2013                        Quantors.THERE_EXISTS,
2014                        filterAttribute,
2015                        FilterOperators.IS_IN,
2016                        new Object JavaDoc[]{target.path().getPrefix(7)}
2017                    )
2018                },
2019                AttributeSelectors.ALL_ATTRIBUTES,
2020                0,
2021                Integer.MAX_VALUE,
2022                Directions.ASCENDING
2023                
2024            );
2025            BigDecimal JavaDoc actualEffortHours = new BigDecimal JavaDoc(0);
2026            BigDecimal JavaDoc actualEffortMinutes = new BigDecimal JavaDoc(0);
2027            for(
2028                Iterator JavaDoc i = workReportEntries.iterator();
2029                i.hasNext();
2030            ) {
2031                DataproviderObject workReportEntry = (DataproviderObject)i.next();
2032                actualEffortHours = actualEffortHours.add(
2033                    (BigDecimal JavaDoc)workReportEntry.values("durationHours").get(0)
2034                );
2035                actualEffortMinutes = actualEffortMinutes.add(
2036                    (BigDecimal JavaDoc)workReportEntry.values("durationMinutes").get(0)
2037                );
2038            }
2039            target.clearValues("actualEffortHours").add(
2040                new Integer JavaDoc(actualEffortHours.intValue() + (actualEffortMinutes.intValue() / 60))
2041            );
2042            target.clearValues("actualEffortMinutes").add(
2043                new Integer JavaDoc(actualEffortMinutes.intValue() % 60)
2044            );
2045        }
2046    }
2047    
2048    //-------------------------------------------------------------------------
2049
public List JavaDoc completeActivity(
2050        ServiceHeader header,
2051        DataproviderObject_1_0 activity,
2052        Set JavaDoc fetchSet
2053    ) throws ServiceException {
2054        this.completeActualEffort(
2055            header,
2056            activity,
2057            "activity",
2058            fetchSet
2059        );
2060        return Collections.EMPTY_LIST;
2061    }
2062    
2063    //-------------------------------------------------------------------------
2064
public List JavaDoc completeActivityGroup(
2065        ServiceHeader header,
2066        DataproviderObject_1_0 activityGroup,
2067        Set JavaDoc fetchSet
2068    ) throws ServiceException {
2069        this.completeActualEffort(
2070            header,
2071            activityGroup,
2072            "p$$activityGroup",
2073            fetchSet
2074        );
2075        return Collections.EMPTY_LIST;
2076    }
2077    
2078    //-------------------------------------------------------------------------
2079
// Members
2080
//-------------------------------------------------------------------------
2081
public static final String JavaDoc MAX_DATE = "99991231T000000.000Z";
2082    
2083    private final static int BATCHING_MODE_SIZE = 1000;
2084
2085    private static final String JavaDoc CODEVALUENAME_ACTIVITY_TYPE = "org:opencrx:kernel:activity1:ActivityType:activityClass";
2086  
2087    private static final String JavaDoc[] ACTIVITY_TYPES =
2088        new String JavaDoc[]{
2089            "org:opencrx:kernel:activity1:EMail",
2090            "org:opencrx:kernel:activity1:Fax",
2091            "org:opencrx:kernel:activity1:Incident",
2092            "org:opencrx:kernel:activity1:Mailing",
2093            "org:opencrx:kernel:activity1:Meeting",
2094            "org:opencrx:kernel:activity1:Mms",
2095            "org:opencrx:kernel:activity1:PhoneCall",
2096            "org:opencrx:kernel:activity1:Sms",
2097            "org:opencrx:kernel:activity1:Task",
2098            "org:opencrx:kernel:activity1:Absence",
2099            "org:opencrx:kernel:activity1:ExternalActivity",
2100            "org:opencrx:kernel:activity1:SalesVisit"
2101        };
2102    
2103    // LINK_TYPE
2104
public static final short ACTIVITY_LINK_TYPE_IS_DERIVED_FROM = 97;
2105    
2106    // DURATION_CALCULATION_MODE
2107
public static final short DURATION_CALCULATION_MODE_CALC_DURATION = 1;
2108    public static final short DURATION_CALCULATION_MODE_CALC_PAUSE = 2;
2109    
2110    // RATE_TYPE
2111
public static final short RATE_TYPE_NA = 0;
2112    public static final short RATE_TYPE_STANDARD = 1;
2113    public static final short RATE_TYPE_OVERTIME = 2;
2114    
2115    // Booking texts
2116
private static final String JavaDoc BOOKING_TEXT_NAME_WORK_EFFORT = "work efforts";
2117    
2118    private final Model_1_0 model;
2119    private final OpenCrxKernel_1 plugin;
2120    private final RequestCollection delegation;
2121    private final RefPackage_1_0 rootPkg;
2122        
2123}
2124
2125//--- End of File -----------------------------------------------------------
2126
Popular Tags