Source Code Cross Referenced for UspsServices.java in  » ERP-CRM-Financial » ofbiz » org » ofbiz » shipment » thirdparty » usps » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » ofbiz » org.ofbiz.shipment.thirdparty.usps 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Licensed to the Apache Software Foundation (ASF) under one
0003:         * or more contributor license agreements.  See the NOTICE file
0004:         * distributed with this work for additional information
0005:         * regarding copyright ownership.  The ASF licenses this file
0006:         * to you under the Apache License, Version 2.0 (the
0007:         * "License"); you may not use this file except in compliance
0008:         * with the License.  You may obtain a copy of the License at
0009:         * 
0010:         * http://www.apache.org/licenses/LICENSE-2.0
0011:         * 
0012:         * Unless required by applicable law or agreed to in writing,
0013:         * software distributed under the License is distributed on an
0014:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015:         * KIND, either express or implied.  See the License for the
0016:         * specific language governing permissions and limitations
0017:         * under the License.
0018:         *******************************************************************************/package org.ofbiz.shipment.thirdparty.usps;
0019:
0020:        import java.io.ByteArrayOutputStream;
0021:        import java.io.FileOutputStream;
0022:        import java.io.IOException;
0023:        import java.io.OutputStream;
0024:        import java.text.DecimalFormat;
0025:        import java.util.ArrayList;
0026:        import java.util.HashMap;
0027:        import java.util.Iterator;
0028:        import java.util.LinkedList;
0029:        import java.util.List;
0030:        import java.util.ListIterator;
0031:        import java.util.Map;
0032:
0033:        import javax.xml.parsers.ParserConfigurationException;
0034:
0035:        import org.ofbiz.base.util.*;
0036:        import org.ofbiz.entity.GenericDelegator;
0037:        import org.ofbiz.entity.GenericEntityException;
0038:        import org.ofbiz.entity.GenericValue;
0039:        import org.ofbiz.entity.util.EntityUtil;
0040:        import org.ofbiz.product.store.ProductStoreWorker;
0041:        import org.ofbiz.service.DispatchContext;
0042:        import org.ofbiz.service.GenericServiceException;
0043:        import org.ofbiz.service.LocalDispatcher;
0044:        import org.ofbiz.service.ModelService;
0045:        import org.ofbiz.service.ServiceUtil;
0046:
0047:        import org.apache.xml.serialize.OutputFormat;
0048:        import org.apache.xml.serialize.XMLSerializer;
0049:        import org.w3c.dom.Document;
0050:        import org.w3c.dom.Element;
0051:        import org.xml.sax.SAXException;
0052:
0053:        /**
0054:         * USPS Webtools API Services
0055:         */
0056:        public class UspsServices {
0057:
0058:            public final static String module = UspsServices.class.getName();
0059:
0060:            public static Map uspsRateInquire(DispatchContext dctx, Map context) {
0061:
0062:                GenericDelegator delegator = dctx.getDelegator();
0063:
0064:                // check for 0 weight
0065:                Double shippableWeight = (Double) context
0066:                        .get("shippableWeight");
0067:                if (shippableWeight.doubleValue() == 0) {
0068:                    // TODO: should we return an error, or $0.00 ?
0069:                    return ServiceUtil
0070:                            .returnError("shippableWeight must be greater than 0");
0071:                }
0072:
0073:                // get the origination ZIP
0074:                String originationZip = null;
0075:                GenericValue productStore = ProductStoreWorker.getProductStore(
0076:                        ((String) context.get("productStoreId")), delegator);
0077:                if (productStore != null
0078:                        && productStore.get("inventoryFacilityId") != null) {
0079:                    try {
0080:                        List shipLocs = delegator.findByAnd(
0081:                                "FacilityContactMechPurpose",
0082:                                UtilMisc.toMap("facilityId", productStore
0083:                                        .getString("inventoryFacilityId"),
0084:                                        "contactMechPurposeTypeId",
0085:                                        "SHIP_ORIG_LOCATION"), UtilMisc
0086:                                        .toList("-fromDate"));
0087:                        if (UtilValidate.isNotEmpty(shipLocs)) {
0088:                            shipLocs = EntityUtil.filterByDate(shipLocs);
0089:                            GenericValue purp = EntityUtil.getFirst(shipLocs);
0090:                            if (purp != null) {
0091:                                GenericValue shipFromAddress = delegator
0092:                                        .findByPrimaryKey(
0093:                                                "PostalAddress",
0094:                                                UtilMisc
0095:                                                        .toMap(
0096:                                                                "contactMechId",
0097:                                                                purp
0098:                                                                        .getString("contactMechId")));
0099:                                if (shipFromAddress != null) {
0100:                                    originationZip = shipFromAddress
0101:                                            .getString("postalCode");
0102:                                }
0103:                            }
0104:                        }
0105:                    } catch (GenericEntityException e) {
0106:                        Debug.logError(e, module);
0107:                    }
0108:                }
0109:                if (UtilValidate.isEmpty(originationZip)) {
0110:                    return ServiceUtil
0111:                            .returnError("Unable to determine the origination ZIP");
0112:                }
0113:
0114:                // get the destination ZIP
0115:                String destinationZip = null;
0116:                String shippingContactMechId = (String) context
0117:                        .get("shippingContactMechId");
0118:                if (UtilValidate.isNotEmpty(shippingContactMechId)) {
0119:                    try {
0120:                        GenericValue shipToAddress = delegator
0121:                                .findByPrimaryKey("PostalAddress", UtilMisc
0122:                                        .toMap("contactMechId",
0123:                                                shippingContactMechId));
0124:                        if (shipToAddress != null) {
0125:                            destinationZip = shipToAddress
0126:                                    .getString("postalCode");
0127:                        }
0128:                    } catch (GenericEntityException e) {
0129:                        Debug.logError(e, module);
0130:                    }
0131:                }
0132:                if (UtilValidate.isEmpty(destinationZip)) {
0133:                    return ServiceUtil
0134:                            .returnError("Unable to determine the destination ZIP");
0135:                }
0136:
0137:                // get the service code
0138:                String serviceCode = null;
0139:                try {
0140:                    GenericValue carrierShipmentMethod = delegator
0141:                            .findByPrimaryKey(
0142:                                    "CarrierShipmentMethod",
0143:                                    UtilMisc
0144:                                            .toMap(
0145:                                                    "shipmentMethodTypeId",
0146:                                                    (String) context
0147:                                                            .get("shipmentMethodTypeId"),
0148:                                                    "partyId",
0149:                                                    (String) context
0150:                                                            .get("carrierPartyId"),
0151:                                                    "roleTypeId",
0152:                                                    (String) context
0153:                                                            .get("carrierRoleTypeId")));
0154:                    if (carrierShipmentMethod != null) {
0155:                        serviceCode = carrierShipmentMethod
0156:                                .getString("carrierServiceCode");
0157:                    }
0158:                } catch (GenericEntityException e) {
0159:                    Debug.logError(e, module);
0160:                }
0161:                if (UtilValidate.isEmpty(serviceCode)) {
0162:                    return ServiceUtil
0163:                            .returnError("Unable to determine the service code");
0164:                }
0165:
0166:                // create the request document
0167:                Document requestDocument = createUspsRequestDocument("RateV2Request");
0168:
0169:                // TODO: 70 lb max is valid for Express, Priority and Parcel only - handle other methods
0170:                double maxWeight = 70;
0171:                String maxWeightStr = UtilProperties.getPropertyValue(
0172:                        (String) context.get("serviceConfigProps"),
0173:                        "shipment.usps.max.estimate.weight", "70");
0174:                try {
0175:                    maxWeight = Double.parseDouble(maxWeightStr);
0176:                } catch (NumberFormatException e) {
0177:                    Debug
0178:                            .logWarning(
0179:                                    "Error parsing max estimate weight string ["
0180:                                            + maxWeightStr
0181:                                            + "], using default instead",
0182:                                    module);
0183:                    maxWeight = 70;
0184:                }
0185:
0186:                List shippableItemInfo = (List) context
0187:                        .get("shippableItemInfo");
0188:                List packages = getPackageSplit(dctx, shippableItemInfo,
0189:                        maxWeight);
0190:                // TODO: Up to 25 packages can be included per request - handle more than 25
0191:                for (ListIterator li = packages.listIterator(); li.hasNext();) {
0192:                    Map packageMap = (Map) li.next();
0193:
0194:                    double packageWeight = calcPackageWeight(dctx, packageMap,
0195:                            shippableItemInfo, 0);
0196:                    if (packageWeight == 0) {
0197:                        continue;
0198:                    }
0199:
0200:                    Element packageElement = UtilXml.addChildElement(
0201:                            requestDocument.getDocumentElement(), "Package",
0202:                            requestDocument);
0203:                    packageElement.setAttribute("ID", String.valueOf(li
0204:                            .nextIndex() - 1)); // use zero-based index (see examples)
0205:
0206:                    UtilXml.addChildElementValue(packageElement, "Service",
0207:                            serviceCode, requestDocument);
0208:                    UtilXml.addChildElementValue(packageElement,
0209:                            "ZipOrigination", originationZip.substring(0, 5),
0210:                            requestDocument);
0211:                    UtilXml.addChildElementValue(packageElement,
0212:                            "ZipDestination", destinationZip.substring(0, 5),
0213:                            requestDocument);
0214:
0215:                    double weightPounds = Math.floor(packageWeight);
0216:                    // for Parcel post, the weight must be at least 1 lb
0217:                    if ("PARCEL".equals(serviceCode.toUpperCase())
0218:                            && (weightPounds < 1.0)) {
0219:                        weightPounds = 1.0;
0220:                        packageWeight = 0.0;
0221:                    }
0222:                    double weightOunces = Math.ceil(packageWeight * 16 % 16);
0223:                    DecimalFormat df = new DecimalFormat("#"); // USPS only accepts whole numbers like 1 and not 1.0
0224:                    UtilXml.addChildElementValue(packageElement, "Pounds", df
0225:                            .format(weightPounds), requestDocument);
0226:                    UtilXml.addChildElementValue(packageElement, "Ounces", df
0227:                            .format(weightOunces), requestDocument);
0228:
0229:                    // TODO: handle other container types, package sizes, and machinable packages
0230:                    // IMPORTANT: Express or Priority Mail will fail if you supply a Container tag: you will get a message like
0231:                    // Invalid container type. Valid container types for Priority Mail are Flat Rate Envelope and Flat Rate Box.
0232:                    if ("Parcel".equalsIgnoreCase(serviceCode)) {
0233:                        UtilXml.addChildElementValue(packageElement,
0234:                                "Container", "None", requestDocument);
0235:                    }
0236:                    UtilXml.addChildElementValue(packageElement, "Size",
0237:                            "Regular", requestDocument);
0238:                    UtilXml.addChildElementValue(packageElement, "Machinable",
0239:                            "False", requestDocument);
0240:                }
0241:
0242:                // send the request
0243:                Document responseDocument = null;
0244:                try {
0245:                    responseDocument = sendUspsRequest("RateV2",
0246:                            requestDocument);
0247:                } catch (UspsRequestException e) {
0248:                    Debug.log(e, module);
0249:                    return ServiceUtil
0250:                            .returnError("Error sending request for USPS Domestic Rate Calculation service: "
0251:                                    + e.getMessage());
0252:                }
0253:
0254:                List rates = UtilXml.childElementList(responseDocument
0255:                        .getDocumentElement(), "Package");
0256:                if (UtilValidate.isEmpty(rates)) {
0257:                    return ServiceUtil
0258:                            .returnError("No rate available at this time");
0259:                }
0260:
0261:                double estimateAmount = 0.00;
0262:                for (Iterator i = rates.iterator(); i.hasNext();) {
0263:                    Element packageElement = (Element) i.next();
0264:                    try {
0265:                        Element postageElement = UtilXml.firstChildElement(
0266:                                packageElement, "Postage");
0267:                        double packageAmount = Double.parseDouble(UtilXml
0268:                                .childElementValue(postageElement, "Rate"));
0269:                        estimateAmount += packageAmount;
0270:                    } catch (NumberFormatException e) {
0271:                        Debug.log(e, module);
0272:                    }
0273:                }
0274:
0275:                Map result = ServiceUtil.returnSuccess();
0276:                result
0277:                        .put("shippingEstimateAmount", new Double(
0278:                                estimateAmount));
0279:                return result;
0280:            }
0281:
0282:            private static List getPackageSplit(DispatchContext dctx,
0283:                    List shippableItemInfo, double maxWeight) {
0284:                // create the package list w/ the first pacakge
0285:                List packages = new LinkedList();
0286:
0287:                if (shippableItemInfo != null) {
0288:                    Iterator sii = shippableItemInfo.iterator();
0289:                    while (sii.hasNext()) {
0290:                        Map itemInfo = (Map) sii.next();
0291:                        long pieces = ((Long) itemInfo.get("piecesIncluded"))
0292:                                .longValue();
0293:                        double totalQuantity = ((Double) itemInfo
0294:                                .get("quantity")).doubleValue();
0295:                        double totalWeight = ((Double) itemInfo.get("weight"))
0296:                                .doubleValue();
0297:                        String productId = (String) itemInfo.get("productId");
0298:
0299:                        // sanity check
0300:                        if (pieces < 1) {
0301:                            pieces = 1; // can NEVER be less than one
0302:                        }
0303:                        double weight = totalWeight / pieces;
0304:
0305:                        for (int z = 1; z <= totalQuantity; z++) {
0306:                            double partialQty = pieces > 1 ? 1.000 / pieces : 1;
0307:                            for (long x = 0; x < pieces; x++) {
0308:                                if (weight >= maxWeight) {
0309:                                    Map newPackage = new HashMap();
0310:                                    newPackage.put(productId, new Double(
0311:                                            partialQty));
0312:                                    packages.add(newPackage);
0313:                                } else if (totalWeight > 0) {
0314:                                    // create the first package
0315:                                    if (packages.size() == 0) {
0316:                                        packages.add(new HashMap());
0317:                                    }
0318:
0319:                                    // package loop
0320:                                    int packageSize = packages.size();
0321:                                    boolean addedToPackage = false;
0322:                                    for (int pi = 0; pi < packageSize; pi++) {
0323:                                        if (!addedToPackage) {
0324:                                            Map packageMap = (Map) packages
0325:                                                    .get(pi);
0326:                                            double packageWeight = calcPackageWeight(
0327:                                                    dctx, packageMap,
0328:                                                    shippableItemInfo, weight);
0329:                                            if (packageWeight <= maxWeight) {
0330:                                                Double qtyD = (Double) packageMap
0331:                                                        .get(productId);
0332:                                                double qty = qtyD == null ? 0
0333:                                                        : qtyD.doubleValue();
0334:                                                packageMap.put(productId,
0335:                                                        new Double(qty
0336:                                                                + partialQty));
0337:                                                addedToPackage = true;
0338:                                            }
0339:                                        }
0340:                                    }
0341:                                    if (!addedToPackage) {
0342:                                        Map packageMap = new HashMap();
0343:                                        packageMap.put(productId, new Double(
0344:                                                partialQty));
0345:                                        packages.add(packageMap);
0346:                                    }
0347:                                }
0348:                            }
0349:                        }
0350:                    }
0351:                }
0352:                return packages;
0353:            }
0354:
0355:            private static double calcPackageWeight(DispatchContext dctx,
0356:                    Map packageMap, List shippableItemInfo,
0357:                    double additionalWeight) {
0358:
0359:                LocalDispatcher dispatcher = dctx.getDispatcher();
0360:                double totalWeight = 0.00;
0361:                String defaultWeightUomId = UtilProperties.getPropertyValue(
0362:                        "shipment.properties", "shipment.default.weight.uom");
0363:                if (UtilValidate.isEmpty(defaultWeightUomId)) {
0364:                    Debug
0365:                            .logWarning(
0366:                                    "No shipment.default.weight.uom set in shipment.properties, setting it to WT_oz for USPS",
0367:                                    module);
0368:                    defaultWeightUomId = "WT_oz";
0369:                }
0370:
0371:                Iterator i = packageMap.keySet().iterator();
0372:                while (i.hasNext()) {
0373:                    String productId = (String) i.next();
0374:                    Map productInfo = getProductItemInfo(shippableItemInfo,
0375:                            productId);
0376:                    double productWeight = ((Double) productInfo.get("weight"))
0377:                            .doubleValue();
0378:                    double quantity = ((Double) packageMap.get(productId))
0379:                            .doubleValue();
0380:
0381:                    // DLK - I'm not sure if this line is working. shipment_package seems to leave this value null so???
0382:                    String weightUomId = (String) productInfo
0383:                            .get("weight_uom_id");
0384:
0385:                    Debug.logInfo("Product Id : " + productId.toString()
0386:                            + " Product Weight : "
0387:                            + String.valueOf(productWeight)
0388:                            + " Product UomId : " + weightUomId + " assuming "
0389:                            + defaultWeightUomId + " if null. Quantity : "
0390:                            + String.valueOf(quantity), module);
0391:
0392:                    if (UtilValidate.isEmpty(weightUomId)) {
0393:                        weightUomId = defaultWeightUomId;
0394:                        //  Most shipping modules assume pounds while ProductEvents.java assumes WT_oz. - Line 720 for example.
0395:                    }
0396:                    if (!"WT_lb".equals(weightUomId)) {
0397:                        // attempt a conversion to pounds
0398:                        Map result = new HashMap();
0399:                        try {
0400:                            result = dispatcher.runSync("convertUom", UtilMisc
0401:                                    .toMap("uomId", weightUomId, "uomIdTo",
0402:                                            "WT_lb", "originalValue",
0403:                                            new Double(productWeight)));
0404:                        } catch (GenericServiceException ex) {
0405:                            Debug.logError(ex, module);
0406:                        }
0407:
0408:                        if (result.get(ModelService.RESPONSE_MESSAGE).equals(
0409:                                ModelService.RESPOND_SUCCESS)) {
0410:                            productWeight = ((Double) result
0411:                                    .get("convertedValue")).doubleValue();
0412:                        } else {
0413:                            Debug
0414:                                    .logError(
0415:                                            "Unsupported weightUom ["
0416:                                                    + weightUomId
0417:                                                    + "] for calcPackageWeight running productId "
0418:                                                    + productId
0419:                                                    + ", could not find a conversion factor to WT_lb",
0420:                                            module);
0421:                        }
0422:
0423:                    }
0424:
0425:                    totalWeight += (productWeight * quantity);
0426:                }
0427:                Debug.logInfo("Package Weight : " + String.valueOf(totalWeight)
0428:                        + " lbs.", module);
0429:                return totalWeight + additionalWeight;
0430:            }
0431:
0432:            // lifted from UpsServices with no changes - 2004.09.06 JFE
0433:            private static Map getProductItemInfo(List shippableItemInfo,
0434:                    String productId) {
0435:                if (shippableItemInfo != null) {
0436:                    Iterator i = shippableItemInfo.iterator();
0437:                    while (i.hasNext()) {
0438:                        Map testMap = (Map) i.next();
0439:                        String id = (String) testMap.get("productId");
0440:                        if (productId.equals(id)) {
0441:                            return testMap;
0442:                        }
0443:                    }
0444:                }
0445:                return null;
0446:            }
0447:
0448:            /*
0449:
0450:            Track/Confirm Samples: (API=TrackV2)
0451:
0452:            Request:
0453:            <TrackRequest USERID="xxxxxxxx" PASSWORD="xxxxxxxx">
0454:                <TrackID ID="EJ958083578US"></TrackID>
0455:            </TrackRequest>
0456:
0457:            Response:
0458:            <TrackResponse>
0459:                <TrackInfo ID="EJ958083578US">
0460:                    <TrackSummary>Your item was delivered at 8:10 am on June 1 in Wilmington DE 19801.</TrackSummary>
0461:                    <TrackDetail>May 30 11:07 am NOTICE LEFT WILMINGTON DE 19801.</TrackDetail>
0462:                    <TrackDetail>May 30 10:08 am ARRIVAL AT UNIT WILMINGTON DE 19850.</TrackDetail>
0463:                    <TrackDetail>May 29 9:55 am ACCEPT OR PICKUP EDGEWATER NJ 07020.</TrackDetail>
0464:                </TrackInfo>
0465:            </TrackResponse>
0466:
0467:             */
0468:
0469:            public static Map uspsTrackConfirm(DispatchContext dctx, Map context) {
0470:
0471:                Document requestDocument = createUspsRequestDocument("TrackRequest");
0472:
0473:                Element trackingElement = UtilXml.addChildElement(
0474:                        requestDocument.getDocumentElement(), "TrackID",
0475:                        requestDocument);
0476:                trackingElement.setAttribute("ID", (String) context
0477:                        .get("trackingId"));
0478:
0479:                Document responseDocument = null;
0480:                try {
0481:                    responseDocument = sendUspsRequest("TrackV2",
0482:                            requestDocument);
0483:                } catch (UspsRequestException e) {
0484:                    Debug.log(e, module);
0485:                    return ServiceUtil
0486:                            .returnError("Error sending request for USPS Tracking service: "
0487:                                    + e.getMessage());
0488:                }
0489:
0490:                Element trackInfoElement = UtilXml.firstChildElement(
0491:                        responseDocument.getDocumentElement(), "TrackInfo");
0492:                if (trackInfoElement == null) {
0493:                    return ServiceUtil
0494:                            .returnError("Incomplete response from USPS Tracking service: no TrackInfo element found");
0495:                }
0496:
0497:                Map result = ServiceUtil.returnSuccess();
0498:
0499:                result.put("trackingSummary", UtilXml.childElementValue(
0500:                        trackInfoElement, "TrackSummary"));
0501:
0502:                List detailElementList = UtilXml.childElementList(
0503:                        trackInfoElement, "TrackDetail");
0504:                if (UtilValidate.isNotEmpty(detailElementList)) {
0505:                    List trackingDetailList = new ArrayList();
0506:                    for (Iterator iter = detailElementList.iterator(); iter
0507:                            .hasNext();) {
0508:                        trackingDetailList.add(UtilXml
0509:                                .elementValue((Element) iter.next()));
0510:                    }
0511:                    result.put("trackingDetailList", trackingDetailList);
0512:                }
0513:
0514:                return result;
0515:            }
0516:
0517:            /*
0518:
0519:            Address Standardization Samples: (API=Verify)
0520:
0521:            Request:
0522:            <AddressValidateRequest USERID="xxxxxxx" PASSWORD="xxxxxxx">
0523:                <Address ID="0">
0524:                    <Address1></Address1>
0525:                    <Address2>6406 Ivy Lane</Address2>
0526:                    <City>Greenbelt</City>
0527:                    <State>MD</State>
0528:                    <Zip5></Zip5>
0529:                    <Zip4></Zip4>
0530:                </Address>
0531:            </AddressValidateRequest>
0532:
0533:            Response:
0534:            <AddressValidateResponse>
0535:                <Address ID="0">
0536:                    <Address2>6406 IVY LN</Address2>
0537:                    <City>GREENBELT</City>
0538:                    <State>MD</State>
0539:                    <Zip5>20770</Zip5>
0540:                    <Zip4>1440</Zip4>
0541:                </Address>
0542:            </AddressValidateResponse>
0543:
0544:            Note:
0545:                The service parameters address1 and addess2 follow the OFBiz naming convention,
0546:                and are converted to USPS conventions internally
0547:                (OFBiz address1 = USPS address2, OFBiz address2 = USPS address1)
0548:
0549:             */
0550:
0551:            public static Map uspsAddressValidation(DispatchContext dctx,
0552:                    Map context) {
0553:
0554:                Document requestDocument = createUspsRequestDocument("AddressValidateRequest");
0555:
0556:                Element addressElement = UtilXml.addChildElement(
0557:                        requestDocument.getDocumentElement(), "Address",
0558:                        requestDocument);
0559:                addressElement.setAttribute("ID", "0");
0560:
0561:                // 38 chars max
0562:                UtilXml.addChildElementValue(addressElement, "FirmName",
0563:                        (String) context.get("firmName"), requestDocument);
0564:                // 38 chars max
0565:                UtilXml.addChildElementValue(addressElement, "Address1",
0566:                        (String) context.get("address2"), requestDocument);
0567:                // 38 chars max
0568:                UtilXml.addChildElementValue(addressElement, "Address2",
0569:                        (String) context.get("address1"), requestDocument);
0570:                // 15 chars max
0571:                UtilXml.addChildElementValue(addressElement, "City",
0572:                        (String) context.get("city"), requestDocument);
0573:
0574:                UtilXml.addChildElementValue(addressElement, "State",
0575:                        (String) context.get("state"), requestDocument);
0576:                UtilXml.addChildElementValue(addressElement, "Zip5",
0577:                        (String) context.get("zip5"), requestDocument);
0578:                UtilXml.addChildElementValue(addressElement, "Zip4",
0579:                        (String) context.get("zip4"), requestDocument);
0580:
0581:                Document responseDocument = null;
0582:                try {
0583:                    responseDocument = sendUspsRequest("Verify",
0584:                            requestDocument);
0585:                } catch (UspsRequestException e) {
0586:                    Debug.log(e, module);
0587:                    return ServiceUtil
0588:                            .returnError("Error sending request for USPS Address Validation service: "
0589:                                    + e.getMessage());
0590:                }
0591:
0592:                Element respAddressElement = UtilXml.firstChildElement(
0593:                        responseDocument.getDocumentElement(), "Address");
0594:                if (respAddressElement == null) {
0595:                    return ServiceUtil
0596:                            .returnError("Incomplete response from USPS Address Validation service: no Address element found");
0597:                }
0598:
0599:                Element respErrorElement = UtilXml.firstChildElement(
0600:                        respAddressElement, "Error");
0601:                if (respErrorElement != null) {
0602:                    return ServiceUtil
0603:                            .returnError("The following error was returned by the USPS Address Validation service: "
0604:                                    + UtilXml.childElementValue(
0605:                                            respErrorElement, "Description"));
0606:                }
0607:
0608:                Map result = ServiceUtil.returnSuccess();
0609:
0610:                // Note: a FirmName element is not returned if empty
0611:                String firmName = UtilXml.childElementValue(respAddressElement,
0612:                        "FirmName");
0613:                if (UtilValidate.isNotEmpty(firmName)) {
0614:                    result.put("firmName", firmName);
0615:                }
0616:
0617:                // Note: an Address1 element is not returned if empty
0618:                String address1 = UtilXml.childElementValue(respAddressElement,
0619:                        "Address1");
0620:                if (UtilValidate.isNotEmpty(address1)) {
0621:                    result.put("address2", address1);
0622:                }
0623:
0624:                result.put("address1", UtilXml.childElementValue(
0625:                        respAddressElement, "Address2"));
0626:                result.put("city", UtilXml.childElementValue(
0627:                        respAddressElement, "City"));
0628:                result.put("state", UtilXml.childElementValue(
0629:                        respAddressElement, "State"));
0630:                result.put("zip5", UtilXml.childElementValue(
0631:                        respAddressElement, "Zip5"));
0632:                result.put("zip4", UtilXml.childElementValue(
0633:                        respAddressElement, "Zip4"));
0634:
0635:                return result;
0636:            }
0637:
0638:            /*
0639:
0640:            City/State Lookup Samples: (API=CityStateLookup)
0641:
0642:            Request:
0643:            <CityStateLookupRequest USERID="xxxxxxx" PASSWORD="xxxxxxx">
0644:                <ZipCode ID="0">
0645:                    <Zip5>90210</Zip5>
0646:                </ZipCode>
0647:            </CityStateLookupRequest>
0648:
0649:            Response:
0650:            <CityStateLookupResponse>
0651:                <ZipCode ID="0">
0652:                    <Zip5>90210</Zip5>
0653:                    <City>BEVERLY HILLS</City>
0654:                    <State>CA</State>
0655:                </ZipCode>
0656:            </CityStateLookupResponse>
0657:
0658:             */
0659:
0660:            public static Map uspsCityStateLookup(DispatchContext dctx,
0661:                    Map context) {
0662:
0663:                Document requestDocument = createUspsRequestDocument("CityStateLookupRequest");
0664:
0665:                Element zipCodeElement = UtilXml.addChildElement(
0666:                        requestDocument.getDocumentElement(), "ZipCode",
0667:                        requestDocument);
0668:                zipCodeElement.setAttribute("ID", "0");
0669:
0670:                String zipCode = ((String) context.get("zip5")).trim(); // trim leading/trailing spaces
0671:
0672:                // only the first 5 digits are used, the rest are ignored
0673:                UtilXml.addChildElementValue(zipCodeElement, "Zip5", zipCode,
0674:                        requestDocument);
0675:
0676:                Document responseDocument = null;
0677:                try {
0678:                    responseDocument = sendUspsRequest("CityStateLookup",
0679:                            requestDocument);
0680:                } catch (UspsRequestException e) {
0681:                    Debug.log(e, module);
0682:                    return ServiceUtil
0683:                            .returnError("Error sending request for USPS City/State Lookup service: "
0684:                                    + e.getMessage());
0685:                }
0686:
0687:                Element respAddressElement = UtilXml.firstChildElement(
0688:                        responseDocument.getDocumentElement(), "ZipCode");
0689:                if (respAddressElement == null) {
0690:                    return ServiceUtil
0691:                            .returnError("Incomplete response from USPS City/State Lookup service: no ZipCode element found");
0692:                }
0693:
0694:                Element respErrorElement = UtilXml.firstChildElement(
0695:                        respAddressElement, "Error");
0696:                if (respErrorElement != null) {
0697:                    return ServiceUtil
0698:                            .returnError("The following error was returned by the USPS City/State Lookup service: "
0699:                                    + UtilXml.childElementValue(
0700:                                            respErrorElement, "Description"));
0701:                }
0702:
0703:                Map result = ServiceUtil.returnSuccess();
0704:
0705:                String city = UtilXml.childElementValue(respAddressElement,
0706:                        "City");
0707:                if (UtilValidate.isEmpty(city)) {
0708:                    return ServiceUtil
0709:                            .returnError("Incomplete response from USPS City/State Lookup service: no City element found");
0710:                }
0711:                result.put("city", city);
0712:
0713:                String state = UtilXml.childElementValue(respAddressElement,
0714:                        "State");
0715:                if (UtilValidate.isEmpty(state)) {
0716:                    return ServiceUtil
0717:                            .returnError("Incomplete response from USPS City/State Lookup service: no State element found");
0718:                }
0719:                result.put("state", state);
0720:
0721:                return result;
0722:            }
0723:
0724:            /*
0725:
0726:            Service Standards Samples:
0727:
0728:            Priority Mail: (API=PriorityMail)
0729:
0730:                Request:
0731:                <PriorityMailRequest USERID="xxxxxxx" PASSWORD="xxxxxxx">
0732:                    <OriginZip>4</OriginZip>
0733:                    <DestinationZip>4</DestinationZip>
0734:                </PriorityMailRequest>
0735:
0736:                Response:
0737:                <PriorityMailResponse>
0738:                    <OriginZip>4</OriginZip>
0739:                    <DestinationZip>4</DestinationZip>
0740:                    <Days>1</Days>
0741:                </PriorityMailResponse>
0742:
0743:            Package Services: (API=StandardB)
0744:
0745:                Request:
0746:                <StandardBRequest USERID="xxxxxxx" PASSWORD="xxxxxxx">
0747:                    <OriginZip>4</OriginZip>
0748:                    <DestinationZip>4</DestinationZip>
0749:                </StandardBRequest>
0750:
0751:                Response:
0752:                <StandardBResponse>
0753:                    <OriginZip>4</OriginZip>
0754:                    <DestinationZip>4</DestinationZip>
0755:                    <Days>2</Days>
0756:                </StandardBResponse>
0757:
0758:            Note:
0759:                When submitting ZIP codes, only the first 3 digits are used.
0760:                If a 1- or 2-digit ZIP code is entered, leading zeros are implied.
0761:                If a 4- or 5-digit ZIP code is entered, the last digits  will be ignored.
0762:
0763:             */
0764:
0765:            public static Map uspsPriorityMailStandard(DispatchContext dctx,
0766:                    Map context) {
0767:                context.put("serviceType", "PriorityMail");
0768:                return uspsServiceStandards(dctx, context);
0769:            }
0770:
0771:            public static Map uspsPackageServicesStandard(DispatchContext dctx,
0772:                    Map context) {
0773:                context.put("serviceType", "StandardB");
0774:                return uspsServiceStandards(dctx, context);
0775:            }
0776:
0777:            private static Map uspsServiceStandards(DispatchContext dctx,
0778:                    Map context) {
0779:
0780:                String type = (String) context.get("serviceType");
0781:                if (!type.matches("PriorityMail|StandardB")) {
0782:                    return ServiceUtil.returnError("Unsupported service type: "
0783:                            + type);
0784:                }
0785:
0786:                Document requestDocument = createUspsRequestDocument(type
0787:                        + "Request");
0788:
0789:                UtilXml.addChildElementValue(requestDocument
0790:                        .getDocumentElement(), "OriginZip", (String) context
0791:                        .get("originZip"), requestDocument);
0792:                UtilXml
0793:                        .addChildElementValue(requestDocument
0794:                                .getDocumentElement(), "DestinationZip",
0795:                                (String) context.get("destinationZip"),
0796:                                requestDocument);
0797:
0798:                Document responseDocument = null;
0799:                try {
0800:                    responseDocument = sendUspsRequest(type, requestDocument);
0801:                } catch (UspsRequestException e) {
0802:                    Debug.log(e, module);
0803:                    return ServiceUtil
0804:                            .returnError("Error sending request for USPS "
0805:                                    + type + " Service Standards service: "
0806:                                    + e.getMessage());
0807:                }
0808:
0809:                Map result = ServiceUtil.returnSuccess();
0810:
0811:                String days = UtilXml.childElementValue(responseDocument
0812:                        .getDocumentElement(), "Days");
0813:                if (UtilValidate.isEmpty(days)) {
0814:                    return ServiceUtil
0815:                            .returnError("Incomplete response from USPS "
0816:                                    + type + " Service Standards service: "
0817:                                    + "no Days element found");
0818:                }
0819:                result.put("days", days);
0820:
0821:                return result;
0822:            }
0823:
0824:            /*
0825:
0826:            Domestic Rate Calculator Samples: (API=Rate)
0827:
0828:            Request:
0829:            <RateRequest USERID="xxxxxx" PASSWORD="xxxxxxx">
0830:                <Package ID="0">
0831:                    <Service>Priority</Service>
0832:                    <ZipOrigination>20770</ZipOrigination>
0833:                    <ZipDestination>09021</ZipDestination>
0834:                    <Pounds>5</Pounds>
0835:                    <Ounces>1</Ounces>
0836:                    <Container>None</Container>
0837:                    <Size>Regular</Size>
0838:                    <Machinable>False</Machinable>
0839:                </Package>
0840:            </RateRequest>
0841:
0842:            Response:
0843:            <RateResponse>
0844:                <Package ID="0">
0845:                    <Service>Priority</Service>
0846:                    <ZipOrigination>20770</ZipOrigination>
0847:                    <ZipDestination>09021</ZipDestination>
0848:                    <Pounds>5</Pounds>
0849:                    <Ounces>1</Ounces>
0850:                    <Container>None</Container>
0851:                    <Size>REGULAR</Size>
0852:                    <Machinable>FALSE</Machinable>
0853:                    <Zone>3</Zone>
0854:                    <Postage>7.90</Postage>
0855:                    <RestrictionCodes>B-B1-C-D-U</RestrictionCodes>
0856:                    <RestrictionDescription>
0857:                    B. Form 2976-A is required for all mail weighing 16 ounces or more, with exceptions noted below.
0858:                    In addition, mailers must properly complete required customs documentation when mailing any potentially
0859:                    dutiable mail addressed to an APO or FPO regardless of weight. B1. Form 2976 or 2976-A is required.
0860:                    Articles are liable for customs duty and/or purchase tax unless they are bona fide gifts intended for
0861:                    use by military personnel or their dependents. C. Cigarettes and other tobacco products are prohibited.
0862:                    D. Coffee is prohibited. U. Parcels must weigh less than 16 ounces when addressed to Box R.
0863:                    </RestrictionDescription>
0864:                </Package>
0865:            </RateResponse>
0866:
0867:             */
0868:
0869:            public static Map uspsDomesticRate(DispatchContext dctx, Map context) {
0870:
0871:                Document requestDocument = createUspsRequestDocument("RateRequest");
0872:
0873:                Element packageElement = UtilXml.addChildElement(
0874:                        requestDocument.getDocumentElement(), "Package",
0875:                        requestDocument);
0876:                packageElement.setAttribute("ID", "0");
0877:
0878:                UtilXml.addChildElementValue(packageElement, "Service",
0879:                        (String) context.get("service"), requestDocument);
0880:                UtilXml.addChildElementValue(packageElement, "ZipOrigination",
0881:                        (String) context.get("originZip"), requestDocument);
0882:                UtilXml
0883:                        .addChildElementValue(packageElement, "ZipDestination",
0884:                                (String) context.get("destinationZip"),
0885:                                requestDocument);
0886:                UtilXml.addChildElementValue(packageElement, "Pounds",
0887:                        (String) context.get("pounds"), requestDocument);
0888:                UtilXml.addChildElementValue(packageElement, "Ounces",
0889:                        (String) context.get("ounces"), requestDocument);
0890:
0891:                String container = (String) context.get("container");
0892:                if (UtilValidate.isEmpty(container)) {
0893:                    container = "None";
0894:                }
0895:                UtilXml.addChildElementValue(packageElement, "Container",
0896:                        container, requestDocument);
0897:
0898:                String size = (String) context.get("size");
0899:                if (UtilValidate.isEmpty(size)) {
0900:                    size = "Regular";
0901:                }
0902:                UtilXml.addChildElementValue(packageElement, "Size", size,
0903:                        requestDocument);
0904:
0905:                String machinable = (String) context.get("machinable");
0906:                if (UtilValidate.isEmpty(machinable)) {
0907:                    machinable = "False";
0908:                }
0909:                UtilXml.addChildElementValue(packageElement, "Machinable",
0910:                        machinable, requestDocument);
0911:
0912:                Document responseDocument = null;
0913:                try {
0914:                    responseDocument = sendUspsRequest("Rate", requestDocument);
0915:                } catch (UspsRequestException e) {
0916:                    Debug.log(e, module);
0917:                    return ServiceUtil
0918:                            .returnError("Error sending request for USPS Domestic Rate Calculation service: "
0919:                                    + e.getMessage());
0920:                }
0921:
0922:                Element respPackageElement = UtilXml.firstChildElement(
0923:                        responseDocument.getDocumentElement(), "Package");
0924:                if (respPackageElement == null) {
0925:                    return ServiceUtil
0926:                            .returnError("Incomplete response from USPS Domestic Rate Calculation service: no Package element found");
0927:                }
0928:
0929:                Element respErrorElement = UtilXml.firstChildElement(
0930:                        respPackageElement, "Error");
0931:                if (respErrorElement != null) {
0932:                    return ServiceUtil
0933:                            .returnError("The following error was returned by the USPS Domestic Rate Calculation service: "
0934:                                    + UtilXml.childElementValue(
0935:                                            respErrorElement, "Description"));
0936:                }
0937:
0938:                Map result = ServiceUtil.returnSuccess();
0939:
0940:                String zone = UtilXml.childElementValue(respPackageElement,
0941:                        "Zone");
0942:                if (UtilValidate.isEmpty(zone)) {
0943:                    return ServiceUtil
0944:                            .returnError("Incomplete response from USPS Domestic Rate Calculation service: no Zone element found");
0945:                }
0946:                result.put("zone", zone);
0947:
0948:                String postage = UtilXml.childElementValue(respPackageElement,
0949:                        "Postage");
0950:                if (UtilValidate.isEmpty(postage)) {
0951:                    return ServiceUtil
0952:                            .returnError("Incomplete response from USPS Domestic Rate Calculation service: no Postage element found");
0953:                }
0954:                result.put("postage", postage);
0955:
0956:                String restrictionCodes = UtilXml.childElementValue(
0957:                        respPackageElement, "RestrictionCodes");
0958:                if (UtilValidate.isNotEmpty(restrictionCodes)) {
0959:                    result.put("restrictionCodes", restrictionCodes);
0960:                }
0961:
0962:                String restrictionDesc = UtilXml.childElementValue(
0963:                        respPackageElement, "RestrictionDescription");
0964:                if (UtilValidate.isNotEmpty(restrictionCodes)) {
0965:                    result.put("restrictionDesc", restrictionDesc);
0966:                }
0967:
0968:                return result;
0969:            }
0970:
0971:            // Warning: I don't think the following 2 services were completed or fully tested - 2004.09.06 JFE
0972:
0973:            /* --- ShipmentRouteSegment services --------------------------------------------------------------------------- */
0974:
0975:            public static Map uspsUpdateShipmentRateInfo(DispatchContext dctx,
0976:                    Map context) {
0977:
0978:                GenericDelegator delegator = dctx.getDelegator();
0979:                LocalDispatcher dispatcher = dctx.getDispatcher();
0980:
0981:                String shipmentId = (String) context.get("shipmentId");
0982:                String shipmentRouteSegmentId = (String) context
0983:                        .get("shipmentRouteSegmentId");
0984:
0985:                // ShipmentRouteSegment identifier - used in error messages
0986:                String srsKeyString = "[" + shipmentId + ","
0987:                        + shipmentRouteSegmentId + "]";
0988:
0989:                try {
0990:                    GenericValue shipmentRouteSegment = delegator
0991:                            .findByPrimaryKey("ShipmentRouteSegment", UtilMisc
0992:                                    .toMap("shipmentId", shipmentId,
0993:                                            "shipmentRouteSegmentId",
0994:                                            shipmentRouteSegmentId));
0995:                    if (shipmentRouteSegment == null) {
0996:                        return ServiceUtil.returnError("ShipmentRouteSegment "
0997:                                + srsKeyString + " not found");
0998:                    }
0999:
1000:                    // ensure the carrier is USPS
1001:                    if (!"USPS".equals(shipmentRouteSegment
1002:                            .getString("carrierPartyId"))) {
1003:                        return ServiceUtil
1004:                                .returnError("The Carrier for ShipmentRouteSegment "
1005:                                        + srsKeyString + ", is not USPS");
1006:                    }
1007:
1008:                    // get the origin address
1009:                    GenericValue originAddress = shipmentRouteSegment
1010:                            .getRelatedOne("OriginPostalAddress");
1011:                    if (originAddress == null) {
1012:                        return ServiceUtil
1013:                                .returnError("OriginPostalAddress not found for ShipmentRouteSegment ["
1014:                                        + shipmentId
1015:                                        + ":"
1016:                                        + shipmentRouteSegmentId + "]");
1017:                    }
1018:                    if (!"USA".equals(originAddress.getString("countryGeoId"))) {
1019:                        return ServiceUtil.returnError("ShipmentRouteSeqment "
1020:                                + srsKeyString
1021:                                + " does not originate from a US address");
1022:                    }
1023:                    String originZip = originAddress.getString("postalCode");
1024:                    if (UtilValidate.isEmpty(originZip)) {
1025:                        return ServiceUtil
1026:                                .returnError("ZIP code is missing from the origin postal address"
1027:                                        + " (contactMechId "
1028:                                        + originAddress
1029:                                                .getString("contactMechId")
1030:                                        + ")");
1031:                    }
1032:
1033:                    // get the destination address
1034:                    GenericValue destinationAddress = shipmentRouteSegment
1035:                            .getRelatedOne("DestPostalAddress");
1036:                    if (destinationAddress == null) {
1037:                        return ServiceUtil
1038:                                .returnError("DestPostalAddress not found for ShipmentRouteSegment "
1039:                                        + srsKeyString);
1040:                    }
1041:                    if (!"USA".equals(destinationAddress
1042:                            .getString("countryGeoId"))) {
1043:                        return ServiceUtil.returnError("ShipmentRouteSeqment "
1044:                                + srsKeyString
1045:                                + " is not destined for a US address");
1046:                    }
1047:                    String destinationZip = destinationAddress
1048:                            .getString("postalCode");
1049:                    if (UtilValidate.isEmpty(destinationZip)) {
1050:                        return ServiceUtil
1051:                                .returnError("ZIP code is missing from the destination postal address"
1052:                                        + " (contactMechId "
1053:                                        + originAddress
1054:                                                .getString("contactMechId")
1055:                                        + ")");
1056:                    }
1057:
1058:                    // get the service type from the CarrierShipmentMethod
1059:                    String shipmentMethodTypeId = shipmentRouteSegment
1060:                            .getString("shipmentMethodTypeId");
1061:                    String partyId = shipmentRouteSegment
1062:                            .getString("carrierPartyId");
1063:                    String csmKeystring = "[" + shipmentMethodTypeId + ","
1064:                            + partyId + ",CARRIER]";
1065:
1066:                    GenericValue carrierShipmentMethod = delegator
1067:                            .findByPrimaryKey("CarrierShipmentMethod", UtilMisc
1068:                                    .toMap("partyId", partyId, "roleTypeId",
1069:                                            "CARRIER", "shipmentMethodTypeId",
1070:                                            shipmentMethodTypeId));
1071:                    if (carrierShipmentMethod == null) {
1072:                        return ServiceUtil.returnError("CarrierShipmentMethod "
1073:                                + csmKeystring
1074:                                + " not found for ShipmentRouteSegment "
1075:                                + srsKeyString);
1076:                    }
1077:                    String serviceType = carrierShipmentMethod
1078:                            .getString("carrierServiceCode");
1079:                    if (UtilValidate.isEmpty(serviceType)) {
1080:                        return ServiceUtil
1081:                                .returnError("carrierServiceCode not found for CarrierShipmentMethod"
1082:                                        + csmKeystring);
1083:                    }
1084:
1085:                    // get the packages for this shipment route segment
1086:                    List shipmentPackageRouteSegList = shipmentRouteSegment
1087:                            .getRelated("ShipmentPackageRouteSeg", null,
1088:                                    UtilMisc.toList("+shipmentPackageSeqId"));
1089:                    if (UtilValidate.isEmpty(shipmentPackageRouteSegList)) {
1090:                        return ServiceUtil
1091:                                .returnError("No packages found for ShipmentRouteSegment "
1092:                                        + srsKeyString);
1093:                    }
1094:
1095:                    double actualTransportCost = 0;
1096:
1097:                    String carrierDeliveryZone = null;
1098:                    String carrierRestrictionCodes = null;
1099:                    String carrierRestrictionDesc = null;
1100:
1101:                    // send a new request for each package
1102:                    for (Iterator i = shipmentPackageRouteSegList.iterator(); i
1103:                            .hasNext();) {
1104:
1105:                        GenericValue shipmentPackageRouteSeg = (GenericValue) i
1106:                                .next();
1107:                        String sprsKeyString = "["
1108:                                + shipmentPackageRouteSeg
1109:                                        .getString("shipmentId")
1110:                                + ","
1111:                                + shipmentPackageRouteSeg
1112:                                        .getString("shipmentPackageSeqId")
1113:                                + ","
1114:                                + shipmentPackageRouteSeg
1115:                                        .getString("shipmentRouteSegmentId")
1116:                                + "]";
1117:
1118:                        Document requestDocument = createUspsRequestDocument("RateRequest");
1119:
1120:                        Element packageElement = UtilXml.addChildElement(
1121:                                requestDocument.getDocumentElement(),
1122:                                "Package", requestDocument);
1123:                        packageElement.setAttribute("ID", "0");
1124:
1125:                        UtilXml.addChildElementValue(packageElement, "Service",
1126:                                serviceType, requestDocument);
1127:                        UtilXml.addChildElementValue(packageElement,
1128:                                "ZipOrigination", originZip, requestDocument);
1129:                        UtilXml.addChildElementValue(packageElement,
1130:                                "ZipDestination", destinationZip,
1131:                                requestDocument);
1132:
1133:                        GenericValue shipmentPackage = null;
1134:                        shipmentPackage = shipmentPackageRouteSeg
1135:                                .getRelatedOne("ShipmentPackage");
1136:
1137:                        String spKeyString = "["
1138:                                + shipmentPackage.getString("shipmentId")
1139:                                + ","
1140:                                + shipmentPackage
1141:                                        .getString("shipmentPackageSeqId")
1142:                                + "]";
1143:
1144:                        // weight elements - Pounds, Ounces
1145:                        String weightStr = shipmentPackage.getString("weight");
1146:                        if (UtilValidate.isEmpty(weightStr)) {
1147:                            return ServiceUtil
1148:                                    .returnError("weight not found for ShipmentPackage "
1149:                                            + spKeyString);
1150:                        }
1151:
1152:                        double weight = 0;
1153:                        try {
1154:                            weight = Double.parseDouble(weightStr);
1155:                        } catch (NumberFormatException nfe) {
1156:                            nfe.printStackTrace(); // TODO: handle exception
1157:                        }
1158:
1159:                        String weightUomId = shipmentPackage
1160:                                .getString("weightUomId");
1161:                        if (UtilValidate.isEmpty(weightUomId)) {
1162:                            weightUomId = "WT_lb"; // assume weight is in pounds
1163:                        }
1164:                        if (!"WT_lb".equals(weightUomId)) {
1165:                            // attempt a conversion to pounds
1166:                            Map result = new HashMap();
1167:                            try {
1168:                                result = dispatcher.runSync("convertUom",
1169:                                        UtilMisc.toMap("uomId", weightUomId,
1170:                                                "uomIdTo", "WT_lb",
1171:                                                "originalValue", new Double(
1172:                                                        weight)));
1173:                            } catch (GenericServiceException ex) {
1174:                                return ServiceUtil.returnError(ex.getMessage());
1175:                            }
1176:
1177:                            if (result.get(ModelService.RESPONSE_MESSAGE)
1178:                                    .equals(ModelService.RESPOND_SUCCESS)) {
1179:                                weight *= ((Double) result
1180:                                        .get("convertedValue")).doubleValue();
1181:                            } else {
1182:                                return ServiceUtil
1183:                                        .returnError("Unsupported weightUom ["
1184:                                                + weightUomId
1185:                                                + "] for ShipmentPackage "
1186:                                                + spKeyString
1187:                                                + ", could not find a conversion factor for WT_lb");
1188:                            }
1189:
1190:                        }
1191:
1192:                        double weightPounds = Math.floor(weight);
1193:                        double weightOunces = Math.ceil(weight * 16 % 16);
1194:
1195:                        DecimalFormat df = new DecimalFormat("#");
1196:                        UtilXml.addChildElementValue(packageElement, "Pounds",
1197:                                df.format(weightPounds), requestDocument);
1198:                        UtilXml.addChildElementValue(packageElement, "Ounces",
1199:                                df.format(weightOunces), requestDocument);
1200:
1201:                        // Container element
1202:                        GenericValue carrierShipmentBoxType = null;
1203:                        List carrierShipmentBoxTypes = null;
1204:                        carrierShipmentBoxTypes = shipmentPackage.getRelated(
1205:                                "CarrierShipmentBoxType", UtilMisc.toMap(
1206:                                        "partyId", "USPS"), null);
1207:
1208:                        if (carrierShipmentBoxTypes.size() > 0) {
1209:                            carrierShipmentBoxType = (GenericValue) carrierShipmentBoxTypes
1210:                                    .get(0);
1211:                        }
1212:
1213:                        if (carrierShipmentBoxType != null
1214:                                && UtilValidate
1215:                                        .isNotEmpty(carrierShipmentBoxType
1216:                                                .getString("packagingTypeCode"))) {
1217:                            UtilXml.addChildElementValue(packageElement,
1218:                                    "Container", carrierShipmentBoxType
1219:                                            .getString("packagingTypeCode"),
1220:                                    requestDocument);
1221:                        } else {
1222:                            // default to "None", for customers using their own package
1223:                            UtilXml.addChildElementValue(packageElement,
1224:                                    "Container", "None", requestDocument);
1225:                        }
1226:
1227:                        // Size element
1228:                        if (carrierShipmentBoxType != null
1229:                                && UtilValidate.isNotEmpty("oversizeCode")) {
1230:                            UtilXml.addChildElementValue(packageElement,
1231:                                    "Size", carrierShipmentBoxType
1232:                                            .getString("oversizeCode"),
1233:                                    requestDocument);
1234:                        } else {
1235:                            // default to "Regular", length + girth measurement <= 84 inches
1236:                            UtilXml.addChildElementValue(packageElement,
1237:                                    "Size", "Regular", requestDocument);
1238:                        }
1239:
1240:                        // Although only applicable for Parcel Post, this tag is required for all requests
1241:                        UtilXml.addChildElementValue(packageElement,
1242:                                "Machinable", "False", requestDocument);
1243:
1244:                        Document responseDocument = null;
1245:                        try {
1246:                            responseDocument = sendUspsRequest("Rate",
1247:                                    requestDocument);
1248:                        } catch (UspsRequestException e) {
1249:                            Debug.log(e, module);
1250:                            return ServiceUtil
1251:                                    .returnError("Error sending request for USPS Domestic Rate Calculation service: "
1252:                                            + e.getMessage());
1253:                        }
1254:
1255:                        Element respPackageElement = UtilXml.firstChildElement(
1256:                                responseDocument.getDocumentElement(),
1257:                                "Package");
1258:                        if (respPackageElement == null) {
1259:                            return ServiceUtil
1260:                                    .returnError("Incomplete response from USPS Domestic Rate Calculation service: "
1261:                                            + "no Package element found");
1262:                        }
1263:
1264:                        Element respErrorElement = UtilXml.firstChildElement(
1265:                                respPackageElement, "Error");
1266:                        if (respErrorElement != null) {
1267:                            return ServiceUtil
1268:                                    .returnError("The following error was returned by the USPS Domestic Rate Calculation "
1269:                                            + "service for ShipmentPackage "
1270:                                            + spKeyString
1271:                                            + ": "
1272:                                            + UtilXml.childElementValue(
1273:                                                    respErrorElement,
1274:                                                    "Description"));
1275:                        }
1276:
1277:                        // update the ShipmentPackageRouteSeg
1278:                        String postageString = UtilXml.childElementValue(
1279:                                respPackageElement, "Postage");
1280:                        if (UtilValidate.isEmpty(postageString)) {
1281:                            return ServiceUtil
1282:                                    .returnError("Incomplete response from USPS Domestic Rate Calculation service: "
1283:                                            + "missing or empty Postage element");
1284:                        }
1285:
1286:                        double postage = 0;
1287:                        try {
1288:                            postage = Double.parseDouble(postageString);
1289:                        } catch (NumberFormatException nfe) {
1290:                            nfe.printStackTrace(); // TODO: handle exception
1291:                        }
1292:                        actualTransportCost += postage;
1293:
1294:                        shipmentPackageRouteSeg.setString(
1295:                                "packageTransportCost", postageString);
1296:                        shipmentPackageRouteSeg.store();
1297:
1298:                        // if this is the last package, get the zone and APO/FPO restrictions for the ShipmentRouteSegment
1299:                        if (!i.hasNext()) {
1300:                            carrierDeliveryZone = UtilXml.childElementValue(
1301:                                    respPackageElement, "Zone");
1302:                            carrierRestrictionCodes = UtilXml
1303:                                    .childElementValue(respPackageElement,
1304:                                            "RestrictionCodes");
1305:                            carrierRestrictionDesc = UtilXml.childElementValue(
1306:                                    respPackageElement,
1307:                                    "RestrictionDescription");
1308:                        }
1309:                    }
1310:
1311:                    // update the ShipmentRouteSegment
1312:                    shipmentRouteSegment.set("carrierDeliveryZone",
1313:                            carrierDeliveryZone);
1314:                    shipmentRouteSegment.set("carrierRestrictionCodes",
1315:                            carrierRestrictionCodes);
1316:                    shipmentRouteSegment.set("carrierRestrictionDesc",
1317:                            carrierRestrictionDesc);
1318:                    shipmentRouteSegment.setString("actualTransportCost",
1319:                            String.valueOf(actualTransportCost));
1320:                    shipmentRouteSegment.store();
1321:
1322:                } catch (GenericEntityException gee) {
1323:                    Debug.log(gee, module);
1324:                    return ServiceUtil
1325:                            .returnError("Error reading or writing shipment data for the USPS "
1326:                                    + "Domestic Rate Calculation service: "
1327:                                    + gee.getMessage());
1328:                }
1329:
1330:                return ServiceUtil.returnSuccess();
1331:            }
1332:
1333:            /*
1334:
1335:            Delivery Confirmation Samples:
1336:
1337:            <DeliveryConfirmationV2.0Request USERID="xxxxxxx" PASSWORD="xxxxxxxx">
1338:                <Option>3</Option>
1339:                <ImageParameters></ImageParameters>
1340:                <FromName>John Smith</FromName>
1341:                <FromFirm>ABC Corp.</FromFirm>
1342:                <FromAddress1>Ste  4</FromAddress1>
1343:                <FromAddress2>6406  Ivy Lane</FromAddress2>
1344:                <FromCity>Greenbelt</FromCity>
1345:                <FromState>MD</FromState>
1346:                <FromZip5>20770</FromZip5>
1347:                <FromZip4>4354</FromZip4>
1348:                <ToName>Jane Smith</ToName>
1349:                <ToFirm>XYZ Corp.</ToFirm>
1350:                <ToAddress1>Apt 303</ToAddress1>
1351:                <ToAddress2>4411 Romlon Street</ToAddress2>
1352:                <ToCity>Beltsville</ToCity>
1353:                <ToState>MD</ToState>
1354:                <ToZip5>20705</ToZip5>
1355:                <ToZip4>5656</ToZip4>
1356:                <WeightInOunces>22</WeightInOunces>
1357:                <ServiceType>Parcel Post</ServiceType>
1358:                <ImageType>TIF</ImageType>
1359:            </DeliveryConfirmationV2.0Request>
1360:
1361:            <DeliveryConfirmationV2.0Response>
1362:                <DeliveryConfirmationNumber>02805213907052510758</DeliveryConfirmationNumber>
1363:                <DeliveryConfirmationLabel>(Base64 encoded data)</DeliveryConfirmationLabel>
1364:            </DeliveryConfirmationV2.0Response>
1365:
1366:             */
1367:
1368:            public static Map uspsDeliveryConfirmation(DispatchContext dctx,
1369:                    Map context) {
1370:
1371:                GenericDelegator delegator = dctx.getDelegator();
1372:
1373:                String shipmentId = (String) context.get("shipmentId");
1374:                String shipmentRouteSegmentId = (String) context
1375:                        .get("shipmentRouteSegmentId");
1376:
1377:                // ShipmentRouteSegment identifier - used in error messages
1378:                String srsKeyString = "[" + shipmentId + ","
1379:                        + shipmentRouteSegmentId + "]";
1380:
1381:                try {
1382:                    GenericValue shipment = delegator.findByPrimaryKey(
1383:                            "Shipment", UtilMisc
1384:                                    .toMap("shipmentId", shipmentId));
1385:                    if (shipment == null) {
1386:                        return ServiceUtil
1387:                                .returnError("Shipment not found with ID "
1388:                                        + shipmentId);
1389:                    }
1390:
1391:                    GenericValue shipmentRouteSegment = delegator
1392:                            .findByPrimaryKey("ShipmentRouteSegment", UtilMisc
1393:                                    .toMap("shipmentId", shipmentId,
1394:                                            "shipmentRouteSegmentId",
1395:                                            shipmentRouteSegmentId));
1396:                    if (shipmentRouteSegment == null) {
1397:                        return ServiceUtil
1398:                                .returnError("ShipmentRouteSegment not found with shipmentId "
1399:                                        + shipmentId
1400:                                        + " and shipmentRouteSegmentId "
1401:                                        + shipmentRouteSegmentId);
1402:                    }
1403:
1404:                    // ensure the carrier is USPS
1405:                    if (!"USPS".equals(shipmentRouteSegment
1406:                            .getString("carrierPartyId"))) {
1407:                        return ServiceUtil
1408:                                .returnError("The Carrier for ShipmentRouteSegment "
1409:                                        + srsKeyString + ", is not USPS");
1410:                    }
1411:
1412:                    // get the origin address
1413:                    GenericValue originAddress = shipmentRouteSegment
1414:                            .getRelatedOne("OriginPostalAddress");
1415:                    if (originAddress == null) {
1416:                        return ServiceUtil
1417:                                .returnError("OriginPostalAddress not found for ShipmentRouteSegment ["
1418:                                        + shipmentId
1419:                                        + ":"
1420:                                        + shipmentRouteSegmentId + "]");
1421:                    }
1422:                    if (!"USA".equals(originAddress.getString("countryGeoId"))) {
1423:                        return ServiceUtil.returnError("ShipmentRouteSeqment "
1424:                                + srsKeyString
1425:                                + " does not originate from a US address");
1426:                    }
1427:
1428:                    // get the destination address
1429:                    GenericValue destinationAddress = shipmentRouteSegment
1430:                            .getRelatedOne("DestPostalAddress");
1431:                    if (destinationAddress == null) {
1432:                        return ServiceUtil
1433:                                .returnError("DestPostalAddress not found for ShipmentRouteSegment "
1434:                                        + srsKeyString);
1435:                    }
1436:                    if (!"USA".equals(destinationAddress
1437:                            .getString("countryGeoId"))) {
1438:                        return ServiceUtil.returnError("ShipmentRouteSeqment "
1439:                                + srsKeyString
1440:                                + " is not destined for a US address");
1441:                    }
1442:
1443:                    // get the service type from the CarrierShipmentMethod
1444:                    String shipmentMethodTypeId = shipmentRouteSegment
1445:                            .getString("shipmentMethodTypeId");
1446:                    String partyId = shipmentRouteSegment
1447:                            .getString("carrierPartyId");
1448:
1449:                    String csmKeystring = "[" + shipmentMethodTypeId + ","
1450:                            + partyId + ",CARRIER]";
1451:
1452:                    GenericValue carrierShipmentMethod = delegator
1453:                            .findByPrimaryKey("CarrierShipmentMethod", UtilMisc
1454:                                    .toMap("partyId", partyId, "roleTypeId",
1455:                                            "CARRIER", "shipmentMethodTypeId",
1456:                                            shipmentMethodTypeId));
1457:                    if (carrierShipmentMethod == null) {
1458:                        return ServiceUtil.returnError("CarrierShipmentMethod "
1459:                                + csmKeystring
1460:                                + " not found for ShipmentRouteSegment "
1461:                                + srsKeyString);
1462:                    }
1463:                    String serviceType = carrierShipmentMethod
1464:                            .getString("carrierServiceCode");
1465:                    if (UtilValidate.isEmpty(serviceType)) {
1466:                        return ServiceUtil
1467:                                .returnError("carrierServiceCode not found for CarrierShipmentMethod"
1468:                                        + csmKeystring);
1469:                    }
1470:
1471:                    // get the packages for this shipment route segment
1472:                    List shipmentPackageRouteSegList = shipmentRouteSegment
1473:                            .getRelated("ShipmentPackageRouteSeg", null,
1474:                                    UtilMisc.toList("+shipmentPackageSeqId"));
1475:                    if (UtilValidate.isEmpty(shipmentPackageRouteSegList)) {
1476:                        return ServiceUtil
1477:                                .returnError("No packages found for ShipmentRouteSegment "
1478:                                        + srsKeyString);
1479:                    }
1480:
1481:                    for (Iterator i = shipmentPackageRouteSegList.iterator(); i
1482:                            .hasNext();) {
1483:
1484:                        Document requestDocument = createUspsRequestDocument("DeliveryConfirmationV2.0Request");
1485:                        Element requestElement = requestDocument
1486:                                .getDocumentElement();
1487:
1488:                        UtilXml.addChildElementValue(requestElement, "Option",
1489:                                "3", requestDocument);
1490:                        UtilXml.addChildElement(requestElement,
1491:                                "ImageParameters", requestDocument);
1492:
1493:                        // From address
1494:                        if (UtilValidate.isNotEmpty(originAddress
1495:                                .getString("attnName"))) {
1496:                            UtilXml.addChildElementValue(requestElement,
1497:                                    "FromName", originAddress
1498:                                            .getString("attnName"),
1499:                                    requestDocument);
1500:                            UtilXml.addChildElementValue(requestElement,
1501:                                    "FromFirm", originAddress
1502:                                            .getString("toName"),
1503:                                    requestDocument);
1504:                        } else {
1505:                            UtilXml.addChildElementValue(requestElement,
1506:                                    "FromName", originAddress
1507:                                            .getString("toName"),
1508:                                    requestDocument);
1509:                        }
1510:                        // The following 2 assignments are not typos - USPS address1 = OFBiz address2, USPS address2 = OFBiz address1
1511:                        UtilXml
1512:                                .addChildElementValue(requestElement,
1513:                                        "FromAddress1", originAddress
1514:                                                .getString("address2"),
1515:                                        requestDocument);
1516:                        UtilXml
1517:                                .addChildElementValue(requestElement,
1518:                                        "FromAddress2", originAddress
1519:                                                .getString("address1"),
1520:                                        requestDocument);
1521:                        UtilXml.addChildElementValue(requestElement,
1522:                                "FromCity", originAddress.getString("city"),
1523:                                requestDocument);
1524:                        UtilXml.addChildElementValue(requestElement,
1525:                                "FromState", originAddress
1526:                                        .getString("stateProvinceGeoId"),
1527:                                requestDocument);
1528:                        UtilXml.addChildElementValue(requestElement,
1529:                                "FromZip5", originAddress
1530:                                        .getString("postalCode"),
1531:                                requestDocument);
1532:                        UtilXml.addChildElement(requestElement, "FromZip4",
1533:                                requestDocument);
1534:
1535:                        // To address
1536:                        if (UtilValidate.isNotEmpty(destinationAddress
1537:                                .getString("attnName"))) {
1538:                            UtilXml.addChildElementValue(requestElement,
1539:                                    "ToName", destinationAddress
1540:                                            .getString("attnName"),
1541:                                    requestDocument);
1542:                            UtilXml.addChildElementValue(requestElement,
1543:                                    "ToFirm", destinationAddress
1544:                                            .getString("toName"),
1545:                                    requestDocument);
1546:                        } else {
1547:                            UtilXml.addChildElementValue(requestElement,
1548:                                    "ToName", destinationAddress
1549:                                            .getString("toName"),
1550:                                    requestDocument);
1551:                        }
1552:                        // The following 2 assignments are not typos - USPS address1 = OFBiz address2, USPS address2 = OFBiz address1
1553:                        UtilXml
1554:                                .addChildElementValue(requestElement,
1555:                                        "ToAddress1", destinationAddress
1556:                                                .getString("address2"),
1557:                                        requestDocument);
1558:                        UtilXml
1559:                                .addChildElementValue(requestElement,
1560:                                        "ToAddress2", destinationAddress
1561:                                                .getString("address1"),
1562:                                        requestDocument);
1563:                        UtilXml.addChildElementValue(requestElement, "ToCity",
1564:                                destinationAddress.getString("city"),
1565:                                requestDocument);
1566:                        UtilXml.addChildElementValue(requestElement, "ToState",
1567:                                destinationAddress
1568:                                        .getString("stateProvinceGeoId"),
1569:                                requestDocument);
1570:                        UtilXml.addChildElementValue(requestElement, "ToZip5",
1571:                                destinationAddress.getString("postalCode"),
1572:                                requestDocument);
1573:                        UtilXml.addChildElement(requestElement, "ToZip4",
1574:                                requestDocument);
1575:
1576:                        GenericValue shipmentPackageRouteSeg = (GenericValue) i
1577:                                .next();
1578:                        GenericValue shipmentPackage = shipmentPackageRouteSeg
1579:                                .getRelatedOne("ShipmentPackage");
1580:                        String spKeyString = "["
1581:                                + shipmentPackage.getString("shipmentId")
1582:                                + ","
1583:                                + shipmentPackage
1584:                                        .getString("shipmentPackageSeqId")
1585:                                + "]";
1586:
1587:                        // WeightInOunces
1588:                        String weightStr = shipmentPackage.getString("weight");
1589:                        if (UtilValidate.isEmpty(weightStr)) {
1590:                            return ServiceUtil
1591:                                    .returnError("weight not found for ShipmentPackage "
1592:                                            + spKeyString);
1593:                        }
1594:
1595:                        double weight = 0;
1596:                        try {
1597:                            weight = Double.parseDouble(weightStr);
1598:                        } catch (NumberFormatException nfe) {
1599:                            nfe.printStackTrace(); // TODO: handle exception
1600:                        }
1601:
1602:                        String weightUomId = shipmentPackage
1603:                                .getString("weightUomId");
1604:                        if (UtilValidate.isEmpty(weightUomId)) {
1605:                            // assume weight is in pounds for consistency (this assumption is made in uspsDomesticRate also)
1606:                            weightUomId = "WT_lb";
1607:                        }
1608:                        if (!"WT_oz".equals(weightUomId)) {
1609:                            // attempt a conversion to pounds
1610:                            GenericValue uomConversion = delegator
1611:                                    .findByPrimaryKey("UomConversion", UtilMisc
1612:                                            .toMap("uomId", weightUomId,
1613:                                                    "uomIdTo", "WT_oz"));
1614:                            if (uomConversion == null
1615:                                    || UtilValidate.isEmpty(uomConversion
1616:                                            .getString("conversionFactor"))) {
1617:                                return ServiceUtil
1618:                                        .returnError("Unsupported weightUom ["
1619:                                                + weightUomId
1620:                                                + "] for ShipmentPackage "
1621:                                                + spKeyString
1622:                                                + ", could not find a conversion factor for WT_oz");
1623:                            }
1624:                            weight *= uomConversion.getDouble(
1625:                                    "conversionFactor").doubleValue();
1626:                        }
1627:
1628:                        DecimalFormat df = new DecimalFormat("#");
1629:                        UtilXml.addChildElementValue(requestElement,
1630:                                "WeightInOunces", df.format(Math.ceil(weight)),
1631:                                requestDocument);
1632:
1633:                        UtilXml.addChildElementValue(requestElement,
1634:                                "ServiceType", serviceType, requestDocument);
1635:                        UtilXml.addChildElementValue(requestElement,
1636:                                "ImageType", "TIF", requestDocument);
1637:                        UtilXml.addChildElementValue(requestElement,
1638:                                "AddressServiceRequested", "True",
1639:                                requestDocument);
1640:
1641:                        Document responseDocument = null;
1642:                        try {
1643:                            responseDocument = sendUspsRequest(
1644:                                    "DeliveryConfirmationV2", requestDocument);
1645:                        } catch (UspsRequestException e) {
1646:                            Debug.log(e, module);
1647:                            return ServiceUtil
1648:                                    .returnError("Error sending request for USPS Delivery Confirmation service: "
1649:                                            + e.getMessage());
1650:                        }
1651:                        Element responseElement = responseDocument
1652:                                .getDocumentElement();
1653:
1654:                        Element respErrorElement = UtilXml.firstChildElement(
1655:                                responseElement, "Error");
1656:                        if (respErrorElement != null) {
1657:                            return ServiceUtil
1658:                                    .returnError("The following error was returned by the USPS Delivery Confirmation "
1659:                                            + "service for ShipmentPackage "
1660:                                            + spKeyString
1661:                                            + ": "
1662:                                            + UtilXml.childElementValue(
1663:                                                    respErrorElement,
1664:                                                    "Description"));
1665:                        }
1666:
1667:                        String labelImageString = UtilXml.childElementValue(
1668:                                responseElement, "DeliveryConfirmationLabel");
1669:                        if (UtilValidate.isEmpty(labelImageString)) {
1670:                            return ServiceUtil
1671:                                    .returnError("Incomplete response from the USPS Delivery Confirmation service: "
1672:                                            + "missing or empty DeliveryConfirmationLabel element");
1673:                        }
1674:                        shipmentPackageRouteSeg.setBytes("labelImage", Base64
1675:                                .base64Decode(labelImageString.getBytes()));
1676:                        String trackingCode = UtilXml.childElementValue(
1677:                                responseElement, "DeliveryConfirmationNumber");
1678:                        if (UtilValidate.isEmpty(trackingCode)) {
1679:                            return ServiceUtil
1680:                                    .returnError("Incomplete response from the USPS Delivery Confirmation service: "
1681:                                            + "missing or empty DeliveryConfirmationNumber element");
1682:                        }
1683:                        shipmentPackageRouteSeg.set("trackingCode",
1684:                                trackingCode);
1685:                        shipmentPackageRouteSeg.store();
1686:                    }
1687:
1688:                } catch (GenericEntityException gee) {
1689:                    Debug.log(gee, module);
1690:                    return ServiceUtil
1691:                            .returnError("Error reading or writing shipment data for the USPS "
1692:                                    + "Delivery Confirmation service: "
1693:                                    + gee.getMessage());
1694:                }
1695:
1696:                return ServiceUtil.returnSuccess();
1697:            }
1698:
1699:            /* ------------------------------------------------------------------------------------------------------------- */
1700:
1701:            // testing utility service - remove this
1702:            public static Map uspsDumpShipmentLabelImages(DispatchContext dctx,
1703:                    Map context) {
1704:
1705:                GenericDelegator delegator = dctx.getDelegator();
1706:
1707:                try {
1708:
1709:                    String shipmentId = (String) context.get("shipmentId");
1710:                    String shipmentRouteSegmentId = (String) context
1711:                            .get("shipmentRouteSegmentId");
1712:
1713:                    GenericValue shipmentRouteSegment = delegator
1714:                            .findByPrimaryKey("ShipmentRouteSegment", UtilMisc
1715:                                    .toMap("shipmentId", shipmentId,
1716:                                            "shipmentRouteSegmentId",
1717:                                            shipmentRouteSegmentId));
1718:
1719:                    List shipmentPackageRouteSegList = shipmentRouteSegment
1720:                            .getRelated("ShipmentPackageRouteSeg", null,
1721:                                    UtilMisc.toList("+shipmentPackageSeqId"));
1722:
1723:                    for (Iterator i = shipmentPackageRouteSegList.iterator(); i
1724:                            .hasNext();) {
1725:                        GenericValue shipmentPackageRouteSeg = (GenericValue) i
1726:                                .next();
1727:
1728:                        byte[] labelImageBytes = shipmentPackageRouteSeg
1729:                                .getBytes("labelImage");
1730:
1731:                        String outFileName = "UspsLabelImage"
1732:                                + shipmentRouteSegment.getString("shipmentId")
1733:                                + "_"
1734:                                + shipmentRouteSegment
1735:                                        .getString("shipmentRouteSegmentId")
1736:                                + "_"
1737:                                + shipmentPackageRouteSeg
1738:                                        .getString("shipmentPackageSeqId")
1739:                                + ".gif";
1740:
1741:                        FileOutputStream fileOut = new FileOutputStream(
1742:                                outFileName);
1743:                        fileOut.write(labelImageBytes);
1744:                        fileOut.flush();
1745:                        fileOut.close();
1746:                    }
1747:
1748:                } catch (GenericEntityException e) {
1749:                    Debug.log(e, module);
1750:                    return ServiceUtil.returnError(e.getMessage());
1751:                } catch (IOException e) {
1752:                    Debug.log(e, module);
1753:                    return ServiceUtil.returnError(e.getMessage());
1754:                }
1755:
1756:                return ServiceUtil.returnSuccess();
1757:            }
1758:
1759:            private static Document createUspsRequestDocument(String rootElement) {
1760:
1761:                Document requestDocument = UtilXml
1762:                        .makeEmptyXmlDocument(rootElement);
1763:
1764:                Element requestElement = requestDocument.getDocumentElement();
1765:                requestElement.setAttribute("USERID", UtilProperties
1766:                        .getPropertyValue("shipment.properties",
1767:                                "shipment.usps.access.userid"));
1768:                requestElement.setAttribute("PASSWORD", UtilProperties
1769:                        .getPropertyValue("shipment.properties",
1770:                                "shipment.usps.access.password"));
1771:
1772:                return requestDocument;
1773:            }
1774:
1775:            private static Document sendUspsRequest(String requestType,
1776:                    Document requestDocument) throws UspsRequestException {
1777:                String conUrl = UtilProperties.getPropertyValue(
1778:                        "shipment.properties", "shipment.usps.connect.url");
1779:                if (UtilValidate.isEmpty(conUrl)) {
1780:                    throw new UspsRequestException(
1781:                            "Connection URL not specified; please check your configuration");
1782:                }
1783:
1784:                OutputStream os = new ByteArrayOutputStream();
1785:
1786:                OutputFormat format = new OutputFormat(requestDocument);
1787:                format.setOmitDocumentType(true);
1788:                format.setOmitXMLDeclaration(true);
1789:                format.setIndenting(false);
1790:
1791:                XMLSerializer serializer = new XMLSerializer(os, format);
1792:                try {
1793:                    serializer.asDOMSerializer();
1794:                    serializer.serialize(requestDocument.getDocumentElement());
1795:                } catch (IOException e) {
1796:                    throw new UspsRequestException(
1797:                            "Error serializing requestDocument: "
1798:                                    + e.getMessage());
1799:                }
1800:
1801:                String xmlString = os.toString();
1802:
1803:                Debug.logInfo("USPS XML request string: " + xmlString, module);
1804:
1805:                String timeOutStr = UtilProperties.getPropertyValue(
1806:                        "shipment.properties", "shipment.usps.connect.timeout",
1807:                        "60");
1808:                int timeout = 60;
1809:                try {
1810:                    timeout = Integer.parseInt(timeOutStr);
1811:                } catch (NumberFormatException e) {
1812:                    Debug.logError(e, "Unable to set timeout to " + timeOutStr
1813:                            + " using default " + timeout);
1814:                }
1815:
1816:                HttpClient http = new HttpClient(conUrl);
1817:                http.setTimeout(timeout * 1000);
1818:                http.setParameter("API", requestType);
1819:                http.setParameter("XML", xmlString);
1820:
1821:                String responseString = null;
1822:                try {
1823:                    responseString = http.get();
1824:                } catch (HttpClientException e) {
1825:                    throw new UspsRequestException(
1826:                            "Problem connecting with USPS server", e);
1827:                }
1828:
1829:                Debug.logInfo("USPS response: " + responseString, module);
1830:
1831:                Document responseDocument = null;
1832:                try {
1833:                    responseDocument = UtilXml.readXmlDocument(responseString,
1834:                            false);
1835:                } catch (SAXException se) {
1836:                    throw new UspsRequestException(
1837:                            "Error reading request Document from a String: "
1838:                                    + se.getMessage());
1839:                } catch (ParserConfigurationException pce) {
1840:                    throw new UspsRequestException(
1841:                            "Error reading request Document from a String: "
1842:                                    + pce.getMessage());
1843:                } catch (IOException xmlReadException) {
1844:                    throw new UspsRequestException(
1845:                            "Error reading request Document from a String: "
1846:                                    + xmlReadException.getMessage());
1847:                }
1848:
1849:                // If a top-level error document is returned, throw exception
1850:                // Other request-level errors should be handled by the caller
1851:                Element responseElement = responseDocument.getDocumentElement();
1852:                if ("Error".equals(responseElement.getNodeName())) {
1853:                    throw new UspsRequestException(UtilXml.childElementValue(
1854:                            responseElement, "Description"));
1855:                }
1856:
1857:                return responseDocument;
1858:            }
1859:        }
1860:
1861:        class UspsRequestException extends GeneralException {
1862:            UspsRequestException() {
1863:                super ();
1864:            }
1865:
1866:            UspsRequestException(String msg) {
1867:                super (msg);
1868:            }
1869:
1870:            UspsRequestException(Throwable t) {
1871:                super (t);
1872:            }
1873:
1874:            UspsRequestException(String msg, Throwable t) {
1875:                super(msg, t);
1876:            }
1877:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.