svn commit: r788972 - in /ofbiz/trunk/applications/workeffort: data/WorkEffortTypeData.xml script/org/ofbiz/workeffort/workeffort/WorkEffortSimpleServices.xml servicedef/services.xml src/org/ofbiz/workeffort/workeffort/ICalConverter.java

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r788972 - in /ofbiz/trunk/applications/workeffort: data/WorkEffortTypeData.xml script/org/ofbiz/workeffort/workeffort/WorkEffortSimpleServices.xml servicedef/services.xml src/org/ofbiz/workeffort/workeffort/ICalConverter.java

adrianc
Author: adrianc
Date: Sat Jun 27 13:42:43 2009
New Revision: 788972

URL: http://svn.apache.org/viewvc?rev=788972&view=rev
Log:
More work on the iCalendar integration. Still to do: report multi-status back to client, enforce SSL, create publish point screen.

Modified:
    ofbiz/trunk/applications/workeffort/data/WorkEffortTypeData.xml
    ofbiz/trunk/applications/workeffort/script/org/ofbiz/workeffort/workeffort/WorkEffortSimpleServices.xml
    ofbiz/trunk/applications/workeffort/servicedef/services.xml
    ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalConverter.java

Modified: ofbiz/trunk/applications/workeffort/data/WorkEffortTypeData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/workeffort/data/WorkEffortTypeData.xml?rev=788972&r1=788971&r2=788972&view=diff
==============================================================================
--- ofbiz/trunk/applications/workeffort/data/WorkEffortTypeData.xml (original)
+++ ofbiz/trunk/applications/workeffort/data/WorkEffortTypeData.xml Sat Jun 27 13:42:43 2009
@@ -226,4 +226,12 @@
 
     <WebSite webSiteId="WORKEFFORT" siteName="Work Effort Manager" visualThemeSetId="BACKOFFICE"/>
 
+    <!-- iCalendar Data -->
+    <RoleType description="Calendar Member" hasTable="N" parentTypeId="CALENDAR_ROLE" roleTypeId="ICAL_MEMBER"/>
+    <ContactMechType contactMechTypeId="LDAP_ADDRESS" parentTypeId="ELECTRONIC_ADDRESS" hasTable="N" description="LDAP URL"/>
+    <ContactMechPurposeType contactMechPurposeTypeId="ICAL_URL" description="iCalendar URL"/>
+    <ContactMechTypePurpose contactMechPurposeTypeId="ICAL_URL" contactMechTypeId="EMAIL_ADDRESS"/>
+    <ContactMechTypePurpose contactMechPurposeTypeId="ICAL_URL" contactMechTypeId="LDAP_ADDRESS"/>
+    <ContactMechTypePurpose contactMechPurposeTypeId="ICAL_URL" contactMechTypeId="WEB_ADDRESS"/>
+
 </entity-engine-xml>

Modified: ofbiz/trunk/applications/workeffort/script/org/ofbiz/workeffort/workeffort/WorkEffortSimpleServices.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/workeffort/script/org/ofbiz/workeffort/workeffort/WorkEffortSimpleServices.xml?rev=788972&r1=788971&r2=788972&view=diff
==============================================================================
--- ofbiz/trunk/applications/workeffort/script/org/ofbiz/workeffort/workeffort/WorkEffortSimpleServices.xml (original)
+++ ofbiz/trunk/applications/workeffort/script/org/ofbiz/workeffort/workeffort/WorkEffortSimpleServices.xml Sat Jun 27 13:42:43 2009
@@ -1480,11 +1480,7 @@
         <entity-condition list="assignedParties" entity-name="WorkEffortPartyAssignment" filter-by-date="true">
             <condition-list combine="and">
                 <condition-expr field-name="workEffortId" from-field="workEffortId"/>
-                <!-- DELEGATE has special meaning in publish properties - it's
-                    another party in an ORGANIZER role, NOT a party whose work efforts
-                    are included in a calendar. We need another role to define calendar
-                    members. -->
-                <condition-expr field-name="roleTypeId" value="CAL_DELEGATE" operator="not-equals"/>
+                <condition-expr field-name="roleTypeId" value="ICAL_MEMBER"/>
             </condition-list>
         </entity-condition>
         <iterate entry="assignedParty" list="assignedParties">
@@ -1517,20 +1513,22 @@
         <field-to-result field="workEfforts"/>
     </simple-method>
     
-    <simple-method method-name="getPartyICalUri" short-description="Get The Party iCalendar URI" login-required="false">
+    <simple-method method-name="getPartyICalUrl" short-description="Get The Party iCalendar URL" login-required="false">
         <!-- RFC 2445 4.8.4.1 and 4.8.4.3 Value must be a URI (4.3.3) -->
-        <!-- For now we just look for a primary email address. This could be expanded later. -->
         <set field="partyId" from-field="parameters.partyId"/>
-        <entity-condition list="emailAddresses" entity-name="PartyContactWithPurpose">
+        <entity-condition list="contactMechs" entity-name="PartyContactWithPurpose">
             <condition-list combine="and">
+                <condition-list combine="or">
+                    <condition-expr field-name="contactMechPurposeTypeId" value="ICAL_URL"/>
+                    <condition-expr field-name="contactMechPurposeTypeId" value="PRIMARY_EMAIL"/>
+                </condition-list>
                 <condition-expr field-name="partyId" from-field="partyId"/>
-                <condition-expr field-name="contactMechPurposeTypeId" value="PRIMARY_EMAIL"/>
                 <condition-expr field-name="purposeThruDate" from-field="null"/>
             </condition-list>
+            <order-by field-name="contactMechPurposeTypeId"/>
         </entity-condition>
-        <if-compare field="util:size(emailAddresses)" operator="not-equals" value="0" type="Integer">
-            <set field="iCalUri" value="MAILTO:${emailAddresses[0].infoString}"/>
-            <field-to-result field="iCalUri"/>
+        <if-compare field="util:size(contactMechs)" operator="greater" value="0" type="Integer">
+            <field-to-result field="iCalUrl" result-name="contactMechs[0].infoString"/>
         </if-compare>
     </simple-method>
 

Modified: ofbiz/trunk/applications/workeffort/servicedef/services.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/workeffort/servicedef/services.xml?rev=788972&r1=788971&r2=788972&view=diff
==============================================================================
--- ofbiz/trunk/applications/workeffort/servicedef/services.xml (original)
+++ ofbiz/trunk/applications/workeffort/servicedef/services.xml Sat Jun 27 13:42:43 2009
@@ -693,9 +693,9 @@
         <attribute type="String" mode="IN" name="workEffortId" optional="false"/>
         <attribute type="List" mode="OUT" name="workEfforts"/>
     </service>
-    <service name="getPartyICalUri" engine="simple" auth="false"
-             location="component://workeffort/script/org/ofbiz/workeffort/workeffort/WorkEffortSimpleServices.xml" invoke="getPartyICalUri">
-        <description>Get Party iCalendar URI</description>
+    <service name="getPartyICalUrl" engine="simple" auth="false"
+             location="component://workeffort/script/org/ofbiz/workeffort/workeffort/WorkEffortSimpleServices.xml" invoke="getPartyICalUrl">
+        <description>Get Party iCalendar URL</description>
         <!-- No permission checking - the servlet handles that -->
         <attribute type="String" mode="IN" name="partyId" optional="false"/>
         <attribute type="String" mode="OUT" name="iCalUri" optional="true"/>

Modified: ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalConverter.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalConverter.java?rev=788972&r1=788971&r2=788972&view=diff
==============================================================================
--- ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalConverter.java (original)
+++ ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalConverter.java Sat Jun 27 13:42:43 2009
@@ -31,6 +31,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import javolution.util.FastList;
 import javolution.util.FastMap;
 import javolution.util.FastSet;
 
@@ -86,6 +87,8 @@
             "PRTYASGN_OFFERED", PartStat.TENTATIVE, "PRTYASGN_ASSIGNED", PartStat.ACCEPTED);
     protected static final Map<String, String> fromPartStatusMap = UtilMisc.toMap(
             "TENTATIVE", "PRTYASGN_OFFERED", "ACCEPTED", "PRTYASGN_ASSIGNED");
+    protected static final Map<String, String> fromRoleMap = UtilMisc.toMap("ATTENDEE", "CAL_ATTENDEE",
+            "CONTACT", "CONTACT", "ORGANIZER", "CAL_ORGANIZER");
 
     protected static VAlarm createAlarm(GenericValue workEffortEventReminder) {
         VAlarm alarm = null;
@@ -118,20 +121,22 @@
         serviceMap.put("workEffortTypeId", "VTODO".equals(component.getName()) ? "TASK" : "EVENT");
         serviceMap.put("currentStatusId", "VTODO".equals(component.getName()) ? "CAL_NEEDS_ACTION" : "CAL_TENTATIVE");
         serviceMap.put("partyId", ((GenericValue) context.get("userLogin")).get("partyId"));
-        serviceMap.put("roleTypeId", "CAL_ORGANIZER");
+        serviceMap.put("roleTypeId", "CAL_OWNER");
         serviceMap.put("statusId", "PRTYASGN_ASSIGNED");
         Map<String, Object> serviceResult = invokeService("createWorkEffortAndPartyAssign", serviceMap, context);
         String workEffortId = (String) serviceResult.get("workEffortId");
         if (workEffortId != null) {
+            replaceProperty(component.getProperties(), toXProperty(workEffortIdXPropName, workEffortId));
             serviceMap.clear();
             serviceMap.put("workEffortIdFrom", context.get("workEffortId"));
             serviceMap.put("workEffortIdTo", workEffortId);
             serviceMap.put("workEffortAssocTypeId", "WORK_EFF_DEPENDENCY");
             serviceMap.put("fromDate", new Timestamp(System.currentTimeMillis()));
             serviceResult = invokeService("createWorkEffortAssoc", serviceMap, context);
-            if (!ServiceUtil.isError(serviceResult)) {
-                replaceProperty(component.getProperties(), toXProperty(workEffortIdXPropName, workEffortId));
+            if (ServiceUtil.isError(serviceResult)) {
+                return;
             }
+            storePartyAssignments(workEffortId, component, context);
         }
     }
 
@@ -244,6 +249,14 @@
         return iCalObj.getValue();
     }
 
+    protected static String fromUid(PropertyList propertyList) {
+        Uid iCalObj = (Uid) propertyList.getProperty(Uid.UID);
+        if (iCalObj == null) {
+            return null;
+        }
+        return iCalObj.getValue();
+    }
+
     protected static String fromXParameter(ParameterList parameterList, String parameterName) {
         if (parameterName == null) {
             return null;
@@ -364,13 +377,16 @@
         return calendar.toString();
     }
 
-    protected static void getPartyPrimaryEmailAddress(Property property, GenericValue partyAssign, Map<String, Object> context) {
+    protected static void getPartyUrl(Property property, GenericValue partyAssign, Map<String, Object> context) {
         Map<String, ? extends Object> serviceMap = UtilMisc.toMap("partyId", partyAssign.get("partyId"));
-        Map<String, Object> resultMap = invokeService("getPartyICalUri", serviceMap, context);
-        String iCalUri = (String) resultMap.get("iCalUri");
-        if (iCalUri != null) {
+        Map<String, Object> resultMap = invokeService("getPartyICalUrl", serviceMap, context);
+        String iCalUrl = (String) resultMap.get("iCalUrl");
+        if (iCalUrl != null) {
+            if (!iCalUrl.contains(":") && iCalUrl.contains("@")) {
+                iCalUrl = "MAILTO:".concat(iCalUrl);
+            }
             try {
-                property.setValue(iCalUri);
+                property.setValue(iCalUrl);
             } catch (Exception e) {
                 Debug.logError(e, "Error while setting party URI: ", module);
             }
@@ -444,7 +460,7 @@
     }
 
     protected static void loadPartyAssignment(Property property, GenericValue partyAssign, Map<String, Object> context) {
-        getPartyPrimaryEmailAddress(property, partyAssign, context);
+        getPartyUrl(property, partyAssign, context);
         if (UtilValidate.isEmpty(property.getValue())) {
             try {
                 // RFC 2445 4.8.4.1 and 4.8.4.3 Value must be a URL
@@ -501,7 +517,11 @@
         replaceProperty(componentProps, toLocation(workEffort.getString("locationDesc")));
         replaceProperty(componentProps, toStatus(workEffort.getString("currentStatusId")));
         replaceProperty(componentProps, toSummary(workEffort.getString("workEffortName")));
-        replaceProperty(componentProps, toUid(workEffort.getString("workEffortId")));
+        Property uid = componentProps.getProperty(Uid.UID);
+        if (uid == null) {
+            // Don't overwrite UIDs created by calendar clients
+            replaceProperty(componentProps, toUid(workEffort.getString("workEffortId")));
+        }
         replaceProperty(componentProps, toXProperty(workEffortIdXPropName, workEffort.getString("workEffortId")));
     }
 
@@ -580,6 +600,15 @@
         map.put(key, value);
     }
 
+    protected static void setPartyIdFromUrl(Property property, Map<String, Object> context) {
+        Map<String, ? extends Object> serviceMap = UtilMisc.toMap("address", property.getValue(), "caseInsensitive", "Y");
+        Map<String, Object> resultMap = invokeService("findPartyFromEmailAddress", serviceMap, context);
+        String partyId = (String) resultMap.get("partyId");
+        if (partyId != null) {
+            replaceParameter(property.getParameters(), toXParameter(partyIdXParamName, partyId));
+        }
+    }
+
     protected static void setWorkEffortServiceMap(Component component, Map<String, Object> serviceMap) {
         PropertyList propertyList = component.getProperties();
         setMapElement(serviceMap, "scopeEnumId", fromClazz(propertyList));
@@ -591,6 +620,7 @@
         setMapElement(serviceMap, "priority", fromPriority(propertyList));
         setMapElement(serviceMap, "currentStatusId", fromStatus(propertyList));
         setMapElement(serviceMap, "workEffortName", fromSummary(propertyList));
+        setMapElement(serviceMap, "universalId", fromUid(propertyList));
         if ("VTODO".equals(component.getName())) {
             setMapElement(serviceMap, "actualCompletionDate", fromCompleted(propertyList));
             setMapElement(serviceMap, "percentComplete", fromPercentComplete(propertyList));
@@ -626,9 +656,7 @@
         }
         String workEffortId = fromXProperty(calendar.getProperties(), workEffortIdXPropName);
         if (workEffortId == null) {
-            // TODO: Create new publish point
-            Debug.logWarning("Warning: Not an OFBiz calendar: \r\n" + calendar, module);
-            return;
+            workEffortId = (String) context.get("workEffortId");
         }
         if (!workEffortId.equals(context.get("workEffortId"))) {
             Debug.logWarning("Spoof attempt: received calendar workEffortId " + workEffortId +
@@ -658,8 +686,18 @@
         for (Component component : components) {
             if (Component.VEVENT.equals(component.getName()) || Component.VTODO.equals(component.getName())) {
                 workEffortId = fromXProperty(component.getProperties(), workEffortIdXPropName);
+                if (workEffortId == null) {
+                    Property uid = component.getProperty(Uid.UID);
+                    if (uid != null) {
+                        GenericValue workEffort = EntityUtil.getFirst(delegator.findByAnd("WorkEffort", UtilMisc.toMap("universalId", uid.getValue())));
+                        if (workEffort != null) {
+                            workEffortId = workEffort.getString("workEffortId");
+                        }
+                    }
+                }
                 if (workEffortId != null) {
                     if (validWorkEfforts.contains(workEffortId)) {
+                        replaceProperty(component.getProperties(), toXProperty(workEffortIdXPropName, workEffortId));
                         storeWorkEffort(component, context);
                     } else {
                         Debug.logWarning("Spoof attempt: unrelated workEffortId " + workEffortId +
@@ -680,6 +718,47 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
+    protected static void storePartyAssignments(String workEffortId, Component component, Map<String, Object> context) {
+        Map<String, Object> serviceMap = FastMap.newInstance();
+        List<Property> partyList = FastList.newInstance();
+        partyList.addAll(component.getProperties("ATTENDEE"));
+        partyList.addAll(component.getProperties("CONTACT"));
+        partyList.addAll(component.getProperties("ORGANIZER"));
+        for (Property property : partyList) {
+            String partyId = fromXParameter(property.getParameters(), partyIdXParamName);
+            if (partyId == null) {
+                serviceMap.clear();
+                String address = property.getValue();
+                if (address.toUpperCase().startsWith("MAILTO:")) {
+                    address = address.substring(7);
+                }
+                serviceMap.put("address", address);
+                Map<String, Object> result = invokeService("findPartyFromEmailAddress", serviceMap, context);
+                partyId = (String) result.get("partyId");
+                if (partyId == null) {
+                    continue;
+                }
+                replaceParameter(property.getParameters(), toXParameter(partyIdXParamName, partyId));
+            }
+            serviceMap.clear();
+            serviceMap.put("workEffortId", workEffortId);
+            serviceMap.put("partyId", partyId);
+            serviceMap.put("roleTypeId", fromRoleMap.get(property.getName()));
+            GenericDelegator delegator = (GenericDelegator) context.get("delegator");
+            List<GenericValue> assignments = null;
+            try {
+                assignments = EntityUtil.filterByDate(delegator.findByAnd("WorkEffortPartyAssignment", serviceMap));
+                if (assignments.size() == 0) {
+                    serviceMap.put("statusId", "PRTYASGN_OFFERED");
+                    serviceMap.put("fromDate", new Timestamp(System.currentTimeMillis()));
+                    invokeService("assignPartyToWorkEffort", serviceMap, context);
+                }
+            } catch (GenericEntityException e) {
+            }
+        }
+    }
+
     protected static void storeWorkEffort(Component component, Map<String, Object> context) throws GenericEntityException, GenericServiceException {
         PropertyList propertyList = component.getProperties();
         String workEffortId = fromXProperty(propertyList, workEffortIdXPropName);
@@ -695,12 +774,14 @@
         serviceMap.put("workEffortId", workEffortId);
         setWorkEffortServiceMap(component, serviceMap);
         invokeService("updateWorkEffort", serviceMap, context);
+        storePartyAssignments(workEffortId, component, context);
     }
 
     @SuppressWarnings("unchecked")
     protected static void toCalendarComponent(ComponentList components, GenericValue workEffort, Map<String, Object> context) throws GenericEntityException {
         GenericDelegator delegator = workEffort.getDelegator();
         String workEffortId = workEffort.getString("workEffortId");
+        String workEffortUid = workEffort.getString("universalId");
         String workEffortTypeId = workEffort.getString("workEffortTypeId");
         GenericValue typeValue = delegator.findOne("WorkEffortType", UtilMisc.toMap("workEffortTypeId", workEffortTypeId), true);
         boolean isTask = false;
@@ -724,6 +805,11 @@
                 newComponent = false;
                 break;
             }
+            Property uid = result.getProperty(Uid.UID);
+            if (uid != null && uid.getValue().equals(workEffortUid)) {
+                newComponent = false;
+                break;
+            }
         }
         if (isTask) {
             VToDo toDo = null;