Source Code Cross Referenced for EntitySyncServices.java in  » ERP-CRM-Financial » SourceTap-CRM » org » ofbiz » entityext » synchronization » 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 » SourceTap CRM » org.ofbiz.entityext.synchronization 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: EntitySyncServices.java,v 1.25 2004/02/09 22:48:43 jonesde Exp $
0003:         *
0004:         * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
0005:         *
0006:         * Permission is hereby granted, free of charge, to any person obtaining a
0007:         * copy of this software and associated documentation files (the "Software"),
0008:         * to deal in the Software without restriction, including without limitation
0009:         * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010:         * and/or sell copies of the Software, and to permit persons to whom the
0011:         * Software is furnished to do so, subject to the following conditions:
0012:         *
0013:         * The above copyright notice and this permission notice shall be included
0014:         * in all copies or substantial portions of the Software.
0015:         *
0016:         * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0017:         * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0018:         * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0019:         * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
0020:         * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
0021:         * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
0022:         * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0023:         *
0024:         */
0025:        package org.ofbiz.entityext.synchronization;
0026:
0027:        import java.io.IOException;
0028:        import java.sql.Timestamp;
0029:        import java.util.ArrayList;
0030:        import java.util.Calendar;
0031:        import java.util.Iterator;
0032:        import java.util.LinkedList;
0033:        import java.util.List;
0034:        import java.util.Map;
0035:
0036:        import javax.xml.parsers.ParserConfigurationException;
0037:
0038:        import org.ofbiz.base.util.Debug;
0039:        import org.ofbiz.base.util.UtilMisc;
0040:        import org.ofbiz.base.util.UtilValidate;
0041:        import org.ofbiz.entity.GenericDelegator;
0042:        import org.ofbiz.entity.GenericEntity;
0043:        import org.ofbiz.entity.GenericEntityException;
0044:        import org.ofbiz.entity.GenericValue;
0045:        import org.ofbiz.entity.condition.EntityCondition;
0046:        import org.ofbiz.entity.condition.EntityConditionList;
0047:        import org.ofbiz.entity.condition.EntityExpr;
0048:        import org.ofbiz.entity.condition.EntityOperator;
0049:        import org.ofbiz.entity.model.ModelEntity;
0050:        import org.ofbiz.entity.model.ModelViewEntity;
0051:        import org.ofbiz.entity.serialize.SerializeException;
0052:        import org.ofbiz.entity.serialize.XmlSerializer;
0053:        import org.ofbiz.entity.util.EntityListIterator;
0054:        import org.ofbiz.service.DispatchContext;
0055:        import org.ofbiz.service.GenericServiceException;
0056:        import org.ofbiz.service.LocalDispatcher;
0057:        import org.ofbiz.service.ModelService;
0058:        import org.ofbiz.service.ServiceUtil;
0059:        import org.xml.sax.SAXException;
0060:
0061:        /**
0062:         * Entity Engine Sync Services
0063:         *
0064:         * @author     <a href="mailto:jonesde@ofbiz.org">David E. Jones</a> 
0065:         * @version    $Revision: 1.25 $
0066:         * @since      3.0
0067:         */
0068:        public class EntitySyncServices {
0069:
0070:            public static final String module = EntitySyncServices.class
0071:                    .getName();
0072:
0073:            // set default split to 10 seconds, ie try not to get too much data moving over at once
0074:            public static final long defaultSyncSplitMillis = 10000;
0075:
0076:            // default to 5 minutes
0077:            public static final long syncEndBufferMillis = 300000;
0078:
0079:            /**
0080:             * Run an Entity Sync (checks to see if other already running, etc)
0081:             *@param dctx The DispatchContext that this service is operating in
0082:             *@param context Map containing the input parameters
0083:             *@return Map with the result of the service, the output parameters
0084:             */
0085:            public static Map runEntitySync(DispatchContext dctx, Map context) {
0086:                GenericDelegator delegator = dctx.getDelegator();
0087:                LocalDispatcher dispatcher = dctx.getDispatcher();
0088:                GenericValue userLogin = (GenericValue) context
0089:                        .get("userLogin");
0090:
0091:                // make the last time to sync X minutes before the current time so that if this machines clock is up to that amount of time 
0092:                //ahead of another machine writing to the DB it will still work fine and not lose any data
0093:                Timestamp syncEndStamp = new Timestamp(System
0094:                        .currentTimeMillis()
0095:                        - syncEndBufferMillis);
0096:
0097:                String entitySyncId = (String) context.get("entitySyncId");
0098:                Debug.logInfo("Running runEntitySync with entitySyncId="
0099:                        + entitySyncId, module);
0100:
0101:                // this is the other part of the history PK, leave null until we create the history object
0102:                Timestamp startDate = null;
0103:
0104:                try {
0105:                    GenericValue entitySync = delegator.findByPrimaryKey(
0106:                            "EntitySync", UtilMisc.toMap("entitySyncId",
0107:                                    entitySyncId));
0108:                    if (entitySync == null) {
0109:                        return ServiceUtil
0110:                                .returnError("Not running EntitySync ["
0111:                                        + entitySyncId
0112:                                        + "], no record found with that ID.");
0113:                    }
0114:
0115:                    String targetServiceName = entitySync
0116:                            .getString("targetServiceName");
0117:                    if (UtilValidate.isEmpty(targetServiceName)) {
0118:                        return ServiceUtil
0119:                                .returnError("Not running EntitySync ["
0120:                                        + entitySyncId
0121:                                        + "], no targetServiceName is specified, where do we send the data?");
0122:                    }
0123:
0124:                    String targetDelegatorName = entitySync
0125:                            .getString("targetDelegatorName");
0126:
0127:                    // check to see if this sync is already running, if so return error
0128:                    if ("ESR_RUNNING".equals(entitySync
0129:                            .getString("runStatusId"))) {
0130:                        return ServiceUtil
0131:                                .returnError("Not running EntitySync ["
0132:                                        + entitySyncId
0133:                                        + "], an instance is already running.");
0134:                    }
0135:
0136:                    // not running, get started NOW
0137:                    // set running status on entity sync, run in its own tx
0138:                    Map startEntitySyncRes = dispatcher.runSync(
0139:                            "updateEntitySyncRunning", UtilMisc.toMap(
0140:                                    "entitySyncId", entitySyncId,
0141:                                    "runStatusId", "ESR_RUNNING", "userLogin",
0142:                                    userLogin));
0143:                    if (ModelService.RESPOND_ERROR.equals(startEntitySyncRes
0144:                            .get(ModelService.RESPONSE_MESSAGE))) {
0145:                        return ServiceUtil
0146:                                .returnError(
0147:                                        "Could not start Entity Sync service, could not mark as running",
0148:                                        null, null, startEntitySyncRes);
0149:                    }
0150:
0151:                    Timestamp lastSuccessfulSynchTime = entitySync
0152:                            .getTimestamp("lastSuccessfulSynchTime");
0153:                    Timestamp currentRunStartTime = lastSuccessfulSynchTime;
0154:
0155:                    Long syncSplitMillis = entitySync
0156:                            .getLong("syncSplitMillis");
0157:                    long splitMillis = defaultSyncSplitMillis;
0158:                    if (syncSplitMillis != null) {
0159:                        splitMillis = syncSplitMillis.longValue();
0160:                    }
0161:
0162:                    List entityModelToUseList = makeEntityModelToUseList(
0163:                            delegator, entitySync);
0164:
0165:                    // if currentRunStartTime is null, what to do? I guess iterate through all entities and find earliest tx stamp
0166:                    if (currentRunStartTime == null) {
0167:                        Iterator entityModelToUseIter = entityModelToUseList
0168:                                .iterator();
0169:                        while (entityModelToUseIter.hasNext()) {
0170:                            ModelEntity modelEntity = (ModelEntity) entityModelToUseIter
0171:                                    .next();
0172:                            // fields to select will be PK and the STAMP_TX_FIELD, slimmed down so we don't get a ton of data back
0173:                            List fieldsToSelect = new LinkedList(modelEntity
0174:                                    .getPkFieldNames());
0175:                            // find all instances of this entity with the STAMP_TX_FIELD != null, sort ascending to get lowest/oldest value first, then grab first and consider as candidate currentRunStartTime
0176:                            fieldsToSelect.add(ModelEntity.STAMP_TX_FIELD);
0177:                            EntityListIterator eli = delegator
0178:                                    .findListIteratorByCondition(
0179:                                            modelEntity.getEntityName(),
0180:                                            new EntityExpr(
0181:                                                    ModelEntity.STAMP_TX_FIELD,
0182:                                                    EntityOperator.NOT_EQUAL,
0183:                                                    null),
0184:                                            fieldsToSelect,
0185:                                            UtilMisc
0186:                                                    .toList(ModelEntity.STAMP_TX_FIELD));
0187:                            GenericValue nextValue = (GenericValue) eli.next();
0188:                            eli.close();
0189:                            if (nextValue != null) {
0190:                                Timestamp candidateTime = nextValue
0191:                                        .getTimestamp(ModelEntity.STAMP_TX_FIELD);
0192:                                if (currentRunStartTime == null
0193:                                        || candidateTime
0194:                                                .before(currentRunStartTime)) {
0195:                                    currentRunStartTime = candidateTime;
0196:                                }
0197:                            }
0198:                        }
0199:                        if (Debug.infoOn())
0200:                            Debug
0201:                                    .logInfo(
0202:                                            "No currentRunStartTime was stored on the EntitySync record, so searched for the earliest value and got: "
0203:                                                    + currentRunStartTime,
0204:                                            module);
0205:                    }
0206:
0207:                    // create history record, should run in own tx
0208:                    Map initialHistoryRes = dispatcher.runSync(
0209:                            "createEntitySyncHistory", UtilMisc.toMap(
0210:                                    "entitySyncId", entitySyncId,
0211:                                    "runStatusId", "ESR_RUNNING",
0212:                                    "beginningSynchTime", currentRunStartTime,
0213:                                    "userLogin", userLogin));
0214:                    if (ServiceUtil.isError(initialHistoryRes)) {
0215:                        String errorMsg = "Not running EntitySync ["
0216:                                + entitySyncId
0217:                                + "], could not create EntitySyncHistory";
0218:                        List errorList = new LinkedList();
0219:                        saveSyncErrorInfo(entitySyncId, startDate,
0220:                                "ESR_DATA_ERROR", errorList, dispatcher,
0221:                                userLogin);
0222:                        return ServiceUtil.returnError(errorMsg, errorList,
0223:                                null, initialHistoryRes);
0224:                    }
0225:                    startDate = (Timestamp) initialHistoryRes.get("startDate");
0226:
0227:                    long toCreateInserted = 0;
0228:                    long toCreateUpdated = 0;
0229:                    long toCreateNotUpdated = 0;
0230:                    long toStoreInserted = 0;
0231:                    long toStoreUpdated = 0;
0232:                    long toStoreNotUpdated = 0;
0233:                    long toRemoveDeleted = 0;
0234:                    long toRemoveAlreadyDeleted = 0;
0235:
0236:                    long totalRowsToCreate = 0;
0237:                    long totalRowsToStore = 0;
0238:                    long totalRowsToRemove = 0;
0239:
0240:                    long totalStoreCalls = 0;
0241:                    long totalSplits = 0;
0242:                    long perSplitMinMillis = Long.MAX_VALUE;
0243:                    long perSplitMaxMillis = 0;
0244:                    long perSplitMinItems = Long.MAX_VALUE;
0245:                    long perSplitMaxItems = 0;
0246:
0247:                    long startingTimeMillis = System.currentTimeMillis();
0248:
0249:                    // increment starting time to run until now
0250:                    while (currentRunStartTime.before(syncEndStamp)) {
0251:                        long splitStartTime = System.currentTimeMillis();
0252:
0253:                        Timestamp currentRunEndTime = new Timestamp(
0254:                                currentRunStartTime.getTime() + splitMillis);
0255:                        if (currentRunEndTime.after(syncEndStamp)) {
0256:                            currentRunEndTime = syncEndStamp;
0257:                        }
0258:
0259:                        // make sure the following message is commented out before commit:
0260:                        //Debug.logInfo("Doing runEntitySync split, currentRunStartTime=" + currentRunStartTime + ", currentRunEndTime=" + currentRunEndTime, module);
0261:
0262:                        totalSplits++;
0263:
0264:                        // tx times are indexed
0265:                        // keep track of how long these sync runs take and store that info on the history table
0266:                        // saves info about removed, all entities that don't have no-auto-stamp set, this will be done in the GenericDAO like the stamp sets
0267:
0268:                        // ===== INSERTS =====
0269:
0270:                        // first grab all values inserted in the date range, then get the updates (leaving out all values inserted in the data range)
0271:                        ArrayList valuesToCreate = new ArrayList(); // make it an ArrayList to easily merge in sorted lists
0272:
0273:                        // iterate through entities, get all records with tx stamp in the current time range, put all in a single list
0274:                        Iterator entityModelToUseCreateIter = entityModelToUseList
0275:                                .iterator();
0276:                        while (entityModelToUseCreateIter.hasNext()) {
0277:                            int insertBefore = 0;
0278:                            ModelEntity modelEntity = (ModelEntity) entityModelToUseCreateIter
0279:                                    .next();
0280:                            // get the values created within the current time range
0281:                            EntityCondition findValCondition = new EntityConditionList(
0282:                                    UtilMisc
0283:                                            .toList(
0284:                                                    new EntityExpr(
0285:                                                            ModelEntity.CREATE_STAMP_TX_FIELD,
0286:                                                            EntityOperator.GREATER_THAN_EQUAL_TO,
0287:                                                            currentRunStartTime),
0288:                                                    new EntityExpr(
0289:                                                            ModelEntity.CREATE_STAMP_TX_FIELD,
0290:                                                            EntityOperator.LESS_THAN,
0291:                                                            currentRunEndTime)),
0292:                                    EntityOperator.AND);
0293:                            EntityListIterator eli = delegator
0294:                                    .findListIteratorByCondition(
0295:                                            modelEntity.getEntityName(),
0296:                                            findValCondition,
0297:                                            null,
0298:                                            UtilMisc
0299:                                                    .toList(
0300:                                                            ModelEntity.CREATE_STAMP_TX_FIELD,
0301:                                                            ModelEntity.CREATE_STAMP_FIELD));
0302:                            GenericValue nextValue = null;
0303:                            //long valuesPerEntity = 0;
0304:                            while ((nextValue = (GenericValue) eli.next()) != null) {
0305:                                // sort by the tx stamp and then the record stamp 
0306:                                // find first value in valuesToStore list, starting with the current insertBefore value, that has a CREATE_STAMP_TX_FIELD after the nextValue.CREATE_STAMP_TX_FIELD, then do the same with CREATE_STAMP_FIELD
0307:                                while (insertBefore < valuesToCreate.size()
0308:                                        && ((GenericValue) valuesToCreate
0309:                                                .get(insertBefore))
0310:                                                .getTimestamp(
0311:                                                        ModelEntity.CREATE_STAMP_TX_FIELD)
0312:                                                .before(
0313:                                                        nextValue
0314:                                                                .getTimestamp(ModelEntity.CREATE_STAMP_TX_FIELD))) {
0315:                                    insertBefore++;
0316:                                }
0317:                                while (insertBefore < valuesToCreate.size()
0318:                                        && ((GenericValue) valuesToCreate
0319:                                                .get(insertBefore))
0320:                                                .getTimestamp(
0321:                                                        ModelEntity.CREATE_STAMP_FIELD)
0322:                                                .before(
0323:                                                        nextValue
0324:                                                                .getTimestamp(ModelEntity.CREATE_STAMP_FIELD))) {
0325:                                    insertBefore++;
0326:                                }
0327:                                valuesToCreate.add(insertBefore, nextValue);
0328:                                //valuesPerEntity++;
0329:                            }
0330:                            eli.close();
0331:
0332:                            // definately remove this message and related data gathering
0333:                            //long preCount = delegator.findCountByCondition(modelEntity.getEntityName(), findValCondition, null);
0334:                            //long entityTotalCount = delegator.findCountByCondition(modelEntity.getEntityName(), null, null);
0335:                            //if (entityTotalCount > 0 || preCount > 0 || valuesPerEntity > 0) Debug.logInfo("Got " + valuesPerEntity + "/" + preCount + "/" + entityTotalCount + " values for entity " + modelEntity.getEntityName(), module);
0336:                        }
0337:
0338:                        // ===== UPDATES =====
0339:
0340:                        // simulate two ordered lists and merge them on-the-fly for faster combined sorting
0341:                        ArrayList valuesToStore = new ArrayList(); // make it an ArrayList to easily merge in sorted lists
0342:
0343:                        // iterate through entities, get all records with tx stamp in the current time range, put all in a single list
0344:                        Iterator entityModelToUseUpdateIter = entityModelToUseList
0345:                                .iterator();
0346:                        while (entityModelToUseUpdateIter.hasNext()) {
0347:                            int insertBefore = 0;
0348:                            ModelEntity modelEntity = (ModelEntity) entityModelToUseUpdateIter
0349:                                    .next();
0350:                            // get all values that were updated, but NOT created in the current time range; if no info on created stamp, that's okay we'll include it here because it won't have been included in the valuesToCreate list
0351:                            EntityCondition createdBeforeStartCond = new EntityExpr(
0352:                                    new EntityExpr(
0353:                                            ModelEntity.CREATE_STAMP_TX_FIELD,
0354:                                            EntityOperator.EQUALS, null),
0355:                                    EntityOperator.OR, new EntityExpr(
0356:                                            ModelEntity.CREATE_STAMP_TX_FIELD,
0357:                                            EntityOperator.LESS_THAN,
0358:                                            currentRunStartTime));
0359:                            EntityCondition findValCondition = new EntityConditionList(
0360:                                    UtilMisc
0361:                                            .toList(
0362:                                                    new EntityExpr(
0363:                                                            ModelEntity.STAMP_TX_FIELD,
0364:                                                            EntityOperator.GREATER_THAN_EQUAL_TO,
0365:                                                            currentRunStartTime),
0366:                                                    new EntityExpr(
0367:                                                            ModelEntity.STAMP_TX_FIELD,
0368:                                                            EntityOperator.LESS_THAN,
0369:                                                            currentRunEndTime),
0370:                                                    createdBeforeStartCond),
0371:                                    EntityOperator.AND);
0372:                            EntityListIterator eli = delegator
0373:                                    .findListIteratorByCondition(modelEntity
0374:                                            .getEntityName(), findValCondition,
0375:                                            null, UtilMisc.toList(
0376:                                                    ModelEntity.STAMP_TX_FIELD,
0377:                                                    ModelEntity.STAMP_FIELD));
0378:                            GenericValue nextValue = null;
0379:                            //long valuesPerEntity = 0;
0380:                            while ((nextValue = (GenericValue) eli.next()) != null) {
0381:                                // sort by the tx stamp and then the record stamp 
0382:                                // find first value in valuesToStore list, starting with the current insertBefore value, that has a STAMP_TX_FIELD after the nextValue.STAMP_TX_FIELD, then do the same with STAMP_FIELD
0383:                                while (insertBefore < valuesToStore.size()
0384:                                        && ((GenericValue) valuesToStore
0385:                                                .get(insertBefore))
0386:                                                .getTimestamp(
0387:                                                        ModelEntity.STAMP_TX_FIELD)
0388:                                                .before(
0389:                                                        nextValue
0390:                                                                .getTimestamp(ModelEntity.STAMP_TX_FIELD))) {
0391:                                    insertBefore++;
0392:                                }
0393:                                while (insertBefore < valuesToStore.size()
0394:                                        && ((GenericValue) valuesToStore
0395:                                                .get(insertBefore))
0396:                                                .getTimestamp(
0397:                                                        ModelEntity.STAMP_FIELD)
0398:                                                .before(
0399:                                                        nextValue
0400:                                                                .getTimestamp(ModelEntity.STAMP_FIELD))) {
0401:                                    insertBefore++;
0402:                                }
0403:                                valuesToStore.add(insertBefore, nextValue);
0404:                                //valuesPerEntity++;
0405:                            }
0406:                            eli.close();
0407:
0408:                            // definately remove this message and related data gathering
0409:                            //long preCount = delegator.findCountByCondition(modelEntity.getEntityName(), findValCondition, null);
0410:                            //long entityTotalCount = delegator.findCountByCondition(modelEntity.getEntityName(), null, null);
0411:                            //if (entityTotalCount > 0 || preCount > 0 || valuesPerEntity > 0) Debug.logInfo("Got " + valuesPerEntity + "/" + preCount + "/" + entityTotalCount + " values for entity " + modelEntity.getEntityName(), module);
0412:                        }
0413:
0414:                        // ===== DELETES =====
0415:
0416:                        // get all removed items from the given time range, add to list for those
0417:                        List keysToRemove = new LinkedList();
0418:                        // find all instances of this entity with the STAMP_TX_FIELD != null, sort ascending to get lowest/oldest value first, then grab first and consider as candidate currentRunStartTime
0419:                        EntityCondition findValCondition = new EntityConditionList(
0420:                                UtilMisc.toList(new EntityExpr(
0421:                                        ModelEntity.STAMP_TX_FIELD,
0422:                                        EntityOperator.GREATER_THAN_EQUAL_TO,
0423:                                        currentRunStartTime), new EntityExpr(
0424:                                        ModelEntity.STAMP_TX_FIELD,
0425:                                        EntityOperator.LESS_THAN,
0426:                                        currentRunEndTime)), EntityOperator.AND);
0427:                        EntityListIterator removeEli = delegator
0428:                                .findListIteratorByCondition(
0429:                                        "EntitySyncRemove",
0430:                                        findValCondition,
0431:                                        null,
0432:                                        UtilMisc
0433:                                                .toList(ModelEntity.STAMP_FIELD));
0434:                        GenericValue nextValue = null;
0435:                        while ((nextValue = (GenericValue) removeEli.next()) != null) {
0436:                            keysToRemove.add(nextValue);
0437:                        }
0438:                        removeEli.close();
0439:
0440:                        // grab some totals before calling...
0441:                        long totalRowsToCreateCur = valuesToCreate.size();
0442:                        long totalRowsToStoreCur = valuesToStore.size();
0443:                        long totalRowsToRemoveCur = keysToRemove.size();
0444:
0445:                        long totalRowsPerSplit = totalRowsToCreateCur
0446:                                + totalRowsToStoreCur + totalRowsToRemoveCur;
0447:
0448:                        if (totalRowsPerSplit < perSplitMinItems) {
0449:                            perSplitMinItems = totalRowsPerSplit;
0450:                        }
0451:                        if (totalRowsPerSplit > perSplitMaxItems) {
0452:                            perSplitMaxItems = totalRowsPerSplit;
0453:                        }
0454:
0455:                        totalRowsToCreate += totalRowsToCreateCur;
0456:                        totalRowsToStore += totalRowsToStoreCur;
0457:                        totalRowsToRemove += totalRowsToRemoveCur;
0458:
0459:                        // call service named on EntitySync, IFF there is actually data to send over
0460:                        if (totalRowsPerSplit > 0) {
0461:                            Map targetServiceMap = UtilMisc.toMap(
0462:                                    "entitySyncId", entitySyncId,
0463:                                    "valuesToCreate", valuesToCreate,
0464:                                    "valuesToStore", valuesToStore,
0465:                                    "keysToRemove", keysToRemove, "userLogin",
0466:                                    userLogin);
0467:                            if (UtilValidate.isNotEmpty(targetDelegatorName)) {
0468:                                targetServiceMap.put("delegatorName",
0469:                                        targetDelegatorName);
0470:                            }
0471:                            Map remoteStoreResult = dispatcher.runSync(
0472:                                    targetServiceName, targetServiceMap);
0473:                            if (ServiceUtil.isError(remoteStoreResult)) {
0474:                                String errorMsg = "Error running EntitySync ["
0475:                                        + entitySyncId
0476:                                        + "], call to store service ["
0477:                                        + targetServiceName + "] failed.";
0478:                                List errorList = new LinkedList();
0479:                                saveSyncErrorInfo(entitySyncId, startDate,
0480:                                        "ESR_OTHER_ERROR", errorList,
0481:                                        dispatcher, userLogin);
0482:                                return ServiceUtil.returnError(errorMsg,
0483:                                        errorList, null, remoteStoreResult);
0484:                            }
0485:
0486:                            totalStoreCalls++;
0487:
0488:                            long toCreateInsertedCur = remoteStoreResult
0489:                                    .get("toCreateInserted") == null ? 0
0490:                                    : ((Long) remoteStoreResult
0491:                                            .get("toCreateInserted"))
0492:                                            .longValue();
0493:                            long toCreateUpdatedCur = remoteStoreResult
0494:                                    .get("toCreateUpdated") == null ? 0
0495:                                    : ((Long) remoteStoreResult
0496:                                            .get("toCreateUpdated"))
0497:                                            .longValue();
0498:                            long toCreateNotUpdatedCur = remoteStoreResult
0499:                                    .get("toCreateNotUpdated") == null ? 0
0500:                                    : ((Long) remoteStoreResult
0501:                                            .get("toCreateNotUpdated"))
0502:                                            .longValue();
0503:                            long toStoreInsertedCur = remoteStoreResult
0504:                                    .get("toStoreInserted") == null ? 0
0505:                                    : ((Long) remoteStoreResult
0506:                                            .get("toStoreInserted"))
0507:                                            .longValue();
0508:                            long toStoreUpdatedCur = remoteStoreResult
0509:                                    .get("toStoreUpdated") == null ? 0
0510:                                    : ((Long) remoteStoreResult
0511:                                            .get("toStoreUpdated")).longValue();
0512:                            long toStoreNotUpdatedCur = remoteStoreResult
0513:                                    .get("toStoreNotUpdated") == null ? 0
0514:                                    : ((Long) remoteStoreResult
0515:                                            .get("toStoreNotUpdated"))
0516:                                            .longValue();
0517:                            long toRemoveDeletedCur = remoteStoreResult
0518:                                    .get("toRemoveDeleted") == null ? 0
0519:                                    : ((Long) remoteStoreResult
0520:                                            .get("toRemoveDeleted"))
0521:                                            .longValue();
0522:                            long toRemoveAlreadyDeletedCur = remoteStoreResult
0523:                                    .get("toRemoveAlreadyDeleted") == null ? 0
0524:                                    : ((Long) remoteStoreResult
0525:                                            .get("toRemoveAlreadyDeleted"))
0526:                                            .longValue();
0527:
0528:                            toCreateInserted += toCreateInsertedCur;
0529:                            toCreateUpdated += toCreateUpdatedCur;
0530:                            toCreateNotUpdated += toCreateNotUpdatedCur;
0531:                            toStoreInserted += toStoreInsertedCur;
0532:                            toStoreUpdated += toStoreUpdatedCur;
0533:                            toStoreNotUpdated += toStoreNotUpdatedCur;
0534:                            toRemoveDeleted += toRemoveDeletedCur;
0535:                            toRemoveAlreadyDeleted += toRemoveAlreadyDeletedCur;
0536:                        }
0537:
0538:                        long splitTotalTime = System.currentTimeMillis()
0539:                                - splitStartTime;
0540:                        if (splitTotalTime < perSplitMinMillis) {
0541:                            perSplitMinMillis = splitTotalTime;
0542:                        }
0543:                        if (splitTotalTime > perSplitMaxMillis) {
0544:                            perSplitMaxMillis = splitTotalTime;
0545:                        }
0546:
0547:                        long runningTimeMillis = System.currentTimeMillis()
0548:                                - startingTimeMillis;
0549:
0550:                        // store latest result on EntitySync, ie update lastSuccessfulSynchTime, should run in own tx
0551:                        Map updateEsRunResult = dispatcher.runSync(
0552:                                "updateEntitySyncRunning", UtilMisc.toMap(
0553:                                        "entitySyncId", entitySyncId,
0554:                                        "lastSuccessfulSynchTime",
0555:                                        currentRunEndTime, "userLogin",
0556:                                        userLogin));
0557:
0558:                        // store result of service call on history with results so far, should run in own tx
0559:                        Map updateHistoryMap = UtilMisc.toMap("entitySyncId",
0560:                                entitySyncId, "startDate", startDate,
0561:                                "lastSuccessfulSynchTime", currentRunEndTime);
0562:                        updateHistoryMap.put("toCreateInserted", new Long(
0563:                                toCreateInserted));
0564:                        updateHistoryMap.put("toCreateUpdated", new Long(
0565:                                toCreateUpdated));
0566:                        updateHistoryMap.put("toCreateNotUpdated", new Long(
0567:                                toCreateNotUpdated));
0568:                        updateHistoryMap.put("toStoreInserted", new Long(
0569:                                toStoreInserted));
0570:                        updateHistoryMap.put("toStoreUpdated", new Long(
0571:                                toStoreUpdated));
0572:                        updateHistoryMap.put("toStoreNotUpdated", new Long(
0573:                                toStoreNotUpdated));
0574:                        updateHistoryMap.put("toRemoveDeleted", new Long(
0575:                                toRemoveDeleted));
0576:                        updateHistoryMap.put("toRemoveAlreadyDeleted",
0577:                                new Long(toRemoveAlreadyDeleted));
0578:                        updateHistoryMap.put("runningTimeMillis", new Long(
0579:                                runningTimeMillis));
0580:                        updateHistoryMap.put("totalStoreCalls", new Long(
0581:                                totalStoreCalls));
0582:                        updateHistoryMap.put("totalSplits", new Long(
0583:                                totalSplits));
0584:                        updateHistoryMap.put("totalRowsToCreate", new Long(
0585:                                totalRowsToCreate));
0586:                        updateHistoryMap.put("totalRowsToStore", new Long(
0587:                                totalRowsToStore));
0588:                        updateHistoryMap.put("totalRowsToRemove", new Long(
0589:                                totalRowsToRemove));
0590:                        updateHistoryMap.put("perSplitMinMillis", new Long(
0591:                                perSplitMinMillis));
0592:                        updateHistoryMap.put("perSplitMaxMillis", new Long(
0593:                                perSplitMaxMillis));
0594:                        updateHistoryMap.put("perSplitMinItems", new Long(
0595:                                perSplitMinItems));
0596:                        updateHistoryMap.put("perSplitMaxItems", new Long(
0597:                                perSplitMaxItems));
0598:                        updateHistoryMap.put("userLogin", userLogin);
0599:                        Map updateEsHistRunResult = dispatcher.runSync(
0600:                                "updateEntitySyncHistory", updateHistoryMap);
0601:
0602:                        // now we have updated EntitySync and EntitySyncHistory, check both ops for errors...
0603:                        if (ServiceUtil.isError(updateEsRunResult)) {
0604:                            String errorMsg = "Error running EntitySync ["
0605:                                    + entitySyncId
0606:                                    + "], update of EntitySync record with lastSuccessfulSynchTime failed.";
0607:                            List errorList = new LinkedList();
0608:                            saveSyncErrorInfo(entitySyncId, startDate,
0609:                                    "ESR_DATA_ERROR", errorList, dispatcher,
0610:                                    userLogin);
0611:                            return ServiceUtil.returnError(errorMsg, errorList,
0612:                                    null, updateEsRunResult);
0613:                        }
0614:
0615:                        if (ServiceUtil.isError(updateEsHistRunResult)) {
0616:                            String errorMsg = "Error running EntitySync ["
0617:                                    + entitySyncId
0618:                                    + "], update of EntitySyncHistory (startDate:["
0619:                                    + startDate
0620:                                    + "]) record with lastSuccessfulSynchTime and result stats failed.";
0621:                            List errorList = new LinkedList();
0622:                            saveSyncErrorInfo(entitySyncId, startDate,
0623:                                    "ESR_DATA_ERROR", errorList, dispatcher,
0624:                                    userLogin);
0625:                            return ServiceUtil.returnError(errorMsg, errorList,
0626:                                    null, updateEsHistRunResult);
0627:                        }
0628:
0629:                        // update start time, loop
0630:                        currentRunStartTime = currentRunEndTime;
0631:                    }
0632:
0633:                    // the lastSuccessfulSynchTime on EntitySync will already be set, so just set status as completed 
0634:                    Map completeEntitySyncRes = dispatcher.runSync(
0635:                            "updateEntitySyncRunning", UtilMisc.toMap(
0636:                                    "entitySyncId", entitySyncId,
0637:                                    "runStatusId", "ESR_COMPLETE", "userLogin",
0638:                                    userLogin));
0639:                    if (ServiceUtil.isError(completeEntitySyncRes)) {
0640:                        // what to do here? try again?
0641:                        return ServiceUtil
0642:                                .returnError(
0643:                                        "Could not mark Entity Sync as complete, but all synchronization was successful",
0644:                                        null, null, completeEntitySyncRes);
0645:                    }
0646:
0647:                    // if nothing moved over, remove the history record, otherwise store status
0648:                    long totalRows = totalRowsToCreate + totalRowsToStore
0649:                            + totalRowsToRemove;
0650:                    if (totalRows == 0) {
0651:                        Map deleteEntitySyncHistRes = dispatcher.runSync(
0652:                                "deleteEntitySyncHistory", UtilMisc.toMap(
0653:                                        "entitySyncId", entitySyncId,
0654:                                        "startDate", startDate, "userLogin",
0655:                                        userLogin));
0656:                        if (ServiceUtil.isError(deleteEntitySyncHistRes)) {
0657:                            return ServiceUtil
0658:                                    .returnError(
0659:                                            "Could not remove Entity Sync History (done becuase nothing was synced in this call), but all synchronization was successful",
0660:                                            null, null, deleteEntitySyncHistRes);
0661:                        }
0662:                    } else {
0663:                        // the lastSuccessfulSynchTime on EntitySync will already be set, so just set status as completed 
0664:                        Map completeEntitySyncHistRes = dispatcher
0665:                                .runSync("updateEntitySyncHistory", UtilMisc
0666:                                        .toMap("entitySyncId", entitySyncId,
0667:                                                "startDate", startDate,
0668:                                                "runStatusId", "ESR_COMPLETE",
0669:                                                "userLogin", userLogin));
0670:                        if (ServiceUtil.isError(completeEntitySyncHistRes)) {
0671:                            // what to do here? try again?
0672:                            return ServiceUtil
0673:                                    .returnError(
0674:                                            "Could not mark Entity Sync History as complete, but all synchronization was successful",
0675:                                            null, null,
0676:                                            completeEntitySyncHistRes);
0677:                        }
0678:                    }
0679:
0680:                    if (Debug.infoOn())
0681:                        Debug.logInfo("Finished runEntitySync: totalRows="
0682:                                + totalRows + ", totalRowsToCreate="
0683:                                + totalRowsToCreate + ", totalRowsToStore="
0684:                                + totalRowsToStore + ", totalRowsToRemove="
0685:                                + totalRowsToRemove, module);
0686:                } catch (GenericEntityException e) {
0687:                    String errorMessage = "Error running EntitySync ["
0688:                            + entitySyncId + "], data access error: "
0689:                            + e.toString();
0690:                    Debug.logError(e, errorMessage, module);
0691:                    List errorList = new LinkedList();
0692:                    saveSyncErrorInfo(entitySyncId, startDate,
0693:                            "ESR_DATA_ERROR", errorList, dispatcher, userLogin);
0694:                    return ServiceUtil.returnError(errorMessage, errorList,
0695:                            null, null);
0696:                } catch (GenericServiceException e) {
0697:                    String errorMessage = "Error running EntitySync ["
0698:                            + entitySyncId + "], service call error: "
0699:                            + e.toString();
0700:                    Debug.logError(e, errorMessage, module);
0701:                    List errorList = new LinkedList();
0702:                    saveSyncErrorInfo(entitySyncId, startDate,
0703:                            "ESR_SERVICE_ERROR", errorList, dispatcher,
0704:                            userLogin);
0705:                    return ServiceUtil.returnError(errorMessage, errorList,
0706:                            null, null);
0707:                }
0708:
0709:                return ServiceUtil.returnSuccess();
0710:            }
0711:
0712:            protected static void saveSyncErrorInfo(String entitySyncId,
0713:                    Timestamp startDate, String runStatusId,
0714:                    List errorMessages, LocalDispatcher dispatcher,
0715:                    GenericValue userLogin) {
0716:                // set error statuses on the EntitySync and EntitySyncHistory entities
0717:                try {
0718:                    Map errorEntitySyncRes = dispatcher.runSync(
0719:                            "updateEntitySyncRunning", UtilMisc.toMap(
0720:                                    "entitySyncId", entitySyncId,
0721:                                    "runStatusId", runStatusId, "userLogin",
0722:                                    userLogin));
0723:                    if (ServiceUtil.isError(errorEntitySyncRes)) {
0724:                        errorMessages.add("Could not save error run status ["
0725:                                + runStatusId
0726:                                + "] on EntitySync with ID ["
0727:                                + entitySyncId
0728:                                + "]: "
0729:                                + errorEntitySyncRes
0730:                                        .get(ModelService.ERROR_MESSAGE));
0731:                    }
0732:                } catch (GenericServiceException e) {
0733:                    errorMessages.add("Could not save error run status ["
0734:                            + runStatusId + "] on EntitySync with ID ["
0735:                            + entitySyncId + "]: " + e.toString());
0736:                }
0737:                if (startDate != null) {
0738:                    try {
0739:                        Map errorEntitySyncHistoryRes = dispatcher.runSync(
0740:                                "updateEntitySyncHistory", UtilMisc.toMap(
0741:                                        "entitySyncId", entitySyncId,
0742:                                        "startDate", startDate, "runStatusId",
0743:                                        runStatusId, "userLogin", userLogin));
0744:                        if (ServiceUtil.isError(errorEntitySyncHistoryRes)) {
0745:                            errorMessages
0746:                                    .add("Could not save error run status ["
0747:                                            + runStatusId
0748:                                            + "] on EntitySyncHistory with ID ["
0749:                                            + entitySyncId
0750:                                            + "]: "
0751:                                            + errorEntitySyncHistoryRes
0752:                                                    .get(ModelService.ERROR_MESSAGE));
0753:                        }
0754:                    } catch (GenericServiceException e) {
0755:                        errorMessages.add("Could not save error run status ["
0756:                                + runStatusId
0757:                                + "] on EntitySyncHistory with ID ["
0758:                                + entitySyncId + ":" + startDate + "]: "
0759:                                + e.toString());
0760:                    }
0761:                }
0762:            }
0763:
0764:            /** prepare a list of all entities we want to synchronize: remove all view-entities and all entities that don't match the patterns attached to this EntitySync */
0765:            protected static List makeEntityModelToUseList(
0766:                    GenericDelegator delegator, GenericValue entitySync)
0767:                    throws GenericEntityException {
0768:                List entityModelToUseList = new LinkedList();
0769:                List entitySyncIncludes = entitySync
0770:                        .getRelated("EntitySyncInclude");
0771:                Iterator entityNameIter = delegator.getModelReader()
0772:                        .getEntityNamesIterator();
0773:                while (entityNameIter.hasNext()) {
0774:                    String entityName = (String) entityNameIter.next();
0775:                    ModelEntity modelEntity = delegator
0776:                            .getModelEntity(entityName);
0777:
0778:                    // if view-entity, throw it out
0779:                    if (modelEntity instanceof  ModelViewEntity) {
0780:                        continue;
0781:                    }
0782:
0783:                    // if it doesn't have either or both of the two update stamp fields, throw it out
0784:                    if (!modelEntity.isField(ModelEntity.STAMP_FIELD)
0785:                            || !modelEntity.isField(ModelEntity.STAMP_TX_FIELD)) {
0786:                        continue;
0787:                    }
0788:
0789:                    // if no includes records, always include; otherwise check each one to make sure at least one matches
0790:                    if (entitySyncIncludes.size() == 0) {
0791:                        entityModelToUseList.add(modelEntity);
0792:                    } else {
0793:                        // we have different types of include applications: ESIA_INCLUDE, ESIA_EXCLUDE, ESIA_ALWAYS
0794:                        // if we find an always we can break right there because this will always be include regardless of excludes, etc
0795:                        // if we find an include or exclude we have to finish going through the rest of them just in case there is something that overrides it (ie an exclude for an include or an always for an exclude)
0796:                        boolean matchesInclude = false;
0797:                        boolean matchesExclude = false;
0798:                        boolean matchesAlways = false;
0799:                        Iterator entitySyncIncludeIter = entitySyncIncludes
0800:                                .iterator();
0801:                        while (entitySyncIncludeIter.hasNext()) {
0802:                            GenericValue entitySyncInclude = (GenericValue) entitySyncIncludeIter
0803:                                    .next();
0804:                            String entityOrPackage = entitySyncInclude
0805:                                    .getString("entityOrPackage");
0806:                            boolean matches = false;
0807:                            if (entityName.equals(entityOrPackage)) {
0808:                                matches = true;
0809:                            } else if (modelEntity.getPackageName().startsWith(
0810:                                    entityOrPackage)) {
0811:                                matches = true;
0812:                            }
0813:
0814:                            if (matches) {
0815:                                if ("ESIA_INCLUDE".equals(entitySyncInclude
0816:                                        .getString("applEnumId"))) {
0817:                                    matchesInclude = true;
0818:                                } else if ("ESIA_EXCLUDE"
0819:                                        .equals(entitySyncInclude
0820:                                                .getString("applEnumId"))) {
0821:                                    matchesExclude = true;
0822:                                } else if ("ESIA_ALWAYS"
0823:                                        .equals(entitySyncInclude
0824:                                                .getString("applEnumId"))) {
0825:                                    matchesAlways = true;
0826:                                    break;
0827:                                }
0828:                            }
0829:                        }
0830:
0831:                        if (matchesAlways
0832:                                || (matchesInclude && !matchesExclude)) {
0833:                            // make sure this log message is not checked in uncommented:
0834:                            //Debug.log("In runEntitySync adding [" + modelEntity.getEntityName() + "] to list of Entities to sync", module);
0835:                            entityModelToUseList.add(modelEntity);
0836:                        }
0837:                    }
0838:                }
0839:
0840:                if (Debug.infoOn())
0841:                    Debug
0842:                            .logInfo(
0843:                                    "In runEntitySync with ID ["
0844:                                            + entitySync.get("entitySyncId")
0845:                                            + "] syncing "
0846:                                            + entityModelToUseList.size()
0847:                                            + " entities", module);
0848:                return entityModelToUseList;
0849:            }
0850:
0851:            /**
0852:             * Store Entity Sync Data
0853:             *@param dctx The DispatchContext that this service is operating in
0854:             *@param context Map containing the input parameters
0855:             *@return Map with the result of the service, the output parameters
0856:             */
0857:            public static Map storeEntitySyncData(DispatchContext dctx,
0858:                    Map context) {
0859:                GenericDelegator delegator = dctx.getDelegator();
0860:                String overrideDelegatorName = (String) context
0861:                        .get("delegatorName");
0862:                if (UtilValidate.isNotEmpty(overrideDelegatorName)) {
0863:                    delegator = GenericDelegator
0864:                            .getGenericDelegator(overrideDelegatorName);
0865:                    if (delegator == null) {
0866:                        return ServiceUtil
0867:                                .returnError("Could not find delegator with specified name "
0868:                                        + overrideDelegatorName);
0869:                    }
0870:                }
0871:                //LocalDispatcher dispatcher = dctx.getDispatcher();
0872:
0873:                String entitySyncId = (String) context.get("entitySyncId");
0874:                // incoming lists will already be sorted by lastUpdatedStamp (or lastCreatedStamp)
0875:                List valuesToCreate = (List) context.get("valuesToCreate");
0876:                List valuesToStore = (List) context.get("valuesToStore");
0877:                List keysToRemove = (List) context.get("keysToRemove");
0878:
0879:                try {
0880:                    long toCreateInserted = 0;
0881:                    long toCreateUpdated = 0;
0882:                    long toCreateNotUpdated = 0;
0883:                    long toStoreInserted = 0;
0884:                    long toStoreUpdated = 0;
0885:                    long toStoreNotUpdated = 0;
0886:                    long toRemoveDeleted = 0;
0887:                    long toRemoveAlreadyDeleted = 0;
0888:
0889:                    // create all values in the valuesToCreate List; if the value already exists update it, or if exists and was updated more recently than this one dont update it
0890:                    Iterator valueToCreateIter = valuesToCreate.iterator();
0891:                    while (valueToCreateIter.hasNext()) {
0892:                        GenericValue valueToCreate = (GenericValue) valueToCreateIter
0893:                                .next();
0894:                        // to Create check if exists (find by pk), if not insert; if exists check lastUpdatedStamp: if null or before the candidate value insert, otherwise don't insert
0895:                        // NOTE: use the delegator from this DispatchContext rather than the one named in the GenericValue
0896:
0897:                        // maintain the original timestamps when doing storage of synced data, by default with will update the timestamps to now
0898:                        valueToCreate.setIsFromEntitySync(true);
0899:
0900:                        GenericValue existingValue = delegator
0901:                                .findByPrimaryKey(valueToCreate.getPrimaryKey());
0902:                        if (existingValue == null) {
0903:                            delegator.create(valueToCreate);
0904:                            toCreateInserted++;
0905:                        } else {
0906:                            // if the existing value has a stamp field that is AFTER the stamp on the valueToCreate, don't update it
0907:                            if (existingValue.get(ModelEntity.STAMP_FIELD) != null
0908:                                    && existingValue
0909:                                            .getTimestamp(
0910:                                                    ModelEntity.STAMP_FIELD)
0911:                                            .after(
0912:                                                    valueToCreate
0913:                                                            .getTimestamp(ModelEntity.STAMP_FIELD))) {
0914:                                toCreateNotUpdated++;
0915:                            } else {
0916:                                delegator.store(valueToCreate);
0917:                                toCreateUpdated++;
0918:                            }
0919:                        }
0920:                    }
0921:
0922:                    // iterate through to store list and store each
0923:                    Iterator valueToStoreIter = valuesToStore.iterator();
0924:                    while (valueToStoreIter.hasNext()) {
0925:                        GenericValue valueToStore = (GenericValue) valueToStoreIter
0926:                                .next();
0927:                        // to store check if exists (find by pk), if not insert; if exists check lastUpdatedStamp: if null or before the candidate value insert, otherwise don't insert
0928:
0929:                        // maintain the original timestamps when doing storage of synced data, by default with will update the timestamps to now
0930:                        valueToStore.setIsFromEntitySync(true);
0931:
0932:                        GenericValue existingValue = delegator
0933:                                .findByPrimaryKey(valueToStore.getPrimaryKey());
0934:                        if (existingValue == null) {
0935:                            delegator.create(valueToStore);
0936:                            toStoreInserted++;
0937:                        } else {
0938:                            // if the existing value has a stamp field that is AFTER the stamp on the valueToStore, don't update it
0939:                            if (existingValue.get(ModelEntity.STAMP_FIELD) != null
0940:                                    && existingValue
0941:                                            .getTimestamp(
0942:                                                    ModelEntity.STAMP_FIELD)
0943:                                            .after(
0944:                                                    valueToStore
0945:                                                            .getTimestamp(ModelEntity.STAMP_FIELD))) {
0946:                                toStoreNotUpdated++;
0947:                            } else {
0948:                                delegator.store(valueToStore);
0949:                                toStoreUpdated++;
0950:                            }
0951:                        }
0952:                    }
0953:
0954:                    // iterate through to remove list and remove each
0955:                    Iterator keyToRemoveIter = keysToRemove.iterator();
0956:                    while (keyToRemoveIter.hasNext()) {
0957:                        GenericValue entitySyncRemove = (GenericValue) keyToRemoveIter
0958:                                .next();
0959:                        // pull the PK from the EntitySyncRemove in the primaryKeyRemoved field, de-XML-serialize it and check to see if it exists, if so remove and count, if not just count already removed
0960:                        String primaryKeyRemoved = entitySyncRemove
0961:                                .getString("primaryKeyRemoved");
0962:                        GenericEntity pkToRemove = null;
0963:                        try {
0964:                            pkToRemove = (GenericEntity) XmlSerializer
0965:                                    .deserialize(primaryKeyRemoved, delegator);
0966:                        } catch (IOException e) {
0967:                            String errorMsg = "Error deserializing GenericPK to remove in Entity Sync Data for entitySyncId ["
0968:                                    + entitySyncId
0969:                                    + "] and entitySyncRemoveId ["
0970:                                    + entitySyncRemove
0971:                                            .getString("entitySyncRemoveId")
0972:                                    + "]: " + e.toString();
0973:                            Debug.logError(e, errorMsg, module);
0974:                            return ServiceUtil.returnError(errorMsg);
0975:                        } catch (SAXException e) {
0976:                            String errorMsg = "Error deserializing GenericPK to remove in Entity Sync Data for entitySyncId ["
0977:                                    + entitySyncId
0978:                                    + "] and entitySyncRemoveId ["
0979:                                    + entitySyncRemove
0980:                                            .getString("entitySyncRemoveId")
0981:                                    + "]: " + e.toString();
0982:                            Debug.logError(e, errorMsg, module);
0983:                            return ServiceUtil.returnError(errorMsg);
0984:                        } catch (ParserConfigurationException e) {
0985:                            String errorMsg = "Error deserializing GenericPK to remove in Entity Sync Data for entitySyncId ["
0986:                                    + entitySyncId
0987:                                    + "] and entitySyncRemoveId ["
0988:                                    + entitySyncRemove
0989:                                            .getString("entitySyncRemoveId")
0990:                                    + "]: " + e.toString();
0991:                            Debug.logError(e, errorMsg, module);
0992:                            return ServiceUtil.returnError(errorMsg);
0993:                        } catch (SerializeException e) {
0994:                            String errorMsg = "Error deserializing GenericPK to remove in Entity Sync Data for entitySyncId ["
0995:                                    + entitySyncId
0996:                                    + "] and entitySyncRemoveId ["
0997:                                    + entitySyncRemove
0998:                                            .getString("entitySyncRemoveId")
0999:                                    + "]: " + e.toString();
1000:                            Debug.logError(e, errorMsg, module);
1001:                            return ServiceUtil.returnError(errorMsg);
1002:                        }
1003:
1004:                        // always do a removeByAnd, if it was a removeByAnd great, if it was a removeByPrimaryKey, this will also work and save us a query
1005:                        pkToRemove.setIsFromEntitySync(true);
1006:                        int numRemByAnd = delegator.removeByAnd(pkToRemove
1007:                                .getEntityName(), pkToRemove);
1008:                        if (numRemByAnd == 0) {
1009:                            toRemoveAlreadyDeleted++;
1010:                        } else {
1011:                            toRemoveDeleted++;
1012:                        }
1013:                    }
1014:
1015:                    Map result = ServiceUtil.returnSuccess();
1016:                    result.put("toCreateInserted", new Long(toCreateInserted));
1017:                    result.put("toCreateUpdated", new Long(toCreateUpdated));
1018:                    result.put("toCreateNotUpdated", new Long(
1019:                            toCreateNotUpdated));
1020:                    result.put("toStoreInserted", new Long(toStoreInserted));
1021:                    result.put("toStoreUpdated", new Long(toStoreUpdated));
1022:                    result
1023:                            .put("toStoreNotUpdated", new Long(
1024:                                    toStoreNotUpdated));
1025:                    result.put("toRemoveDeleted", new Long(toRemoveDeleted));
1026:                    result.put("toRemoveAlreadyDeleted", new Long(
1027:                            toRemoveAlreadyDeleted));
1028:                    return result;
1029:                } catch (GenericEntityException e) {
1030:                    String errorMsg = "Error saving Entity Sync Data for entitySyncId ["
1031:                            + entitySyncId + "]: " + e.toString();
1032:                    Debug.logError(e, errorMsg, module);
1033:                    return ServiceUtil.returnError(errorMsg);
1034:                }
1035:            }
1036:
1037:            /**
1038:             * Clean EntitySyncRemove Info
1039:             *@param dctx The DispatchContext that this service is operating in
1040:             *@param context Map containing the input parameters
1041:             *@return Map with the result of the service, the output parameters
1042:             */
1043:            public static Map cleanSyncRemoveInfo(DispatchContext dctx,
1044:                    Map context) {
1045:                Debug.logInfo("Running cleanSyncRemoveInfo", module);
1046:                GenericDelegator delegator = dctx.getDelegator();
1047:
1048:                try {
1049:                    // find the largest keepRemoveInfoHours value on an EntitySyncRemove and kill everything before that, if none found default to 10 days (240 hours)
1050:                    double keepRemoveInfoHours = 24;
1051:
1052:                    List entitySyncRemoveList = delegator.findAll("EntitySync");
1053:                    Iterator entitySyncRemoveIter = entitySyncRemoveList
1054:                            .iterator();
1055:                    while (entitySyncRemoveIter.hasNext()) {
1056:                        GenericValue entitySyncRemove = (GenericValue) entitySyncRemoveIter
1057:                                .next();
1058:                        Double curKrih = entitySyncRemove
1059:                                .getDouble("keepRemoveInfoHours");
1060:                        if (curKrih != null) {
1061:                            double curKrihVal = curKrih.doubleValue();
1062:                            if (curKrihVal > keepRemoveInfoHours) {
1063:                                keepRemoveInfoHours = curKrihVal;
1064:                            }
1065:                        }
1066:                    }
1067:
1068:                    int keepSeconds = (int) Math
1069:                            .floor(keepRemoveInfoHours * 60);
1070:
1071:                    Calendar nowCal = Calendar.getInstance();
1072:                    nowCal.setTimeInMillis(System.currentTimeMillis());
1073:                    nowCal.add(Calendar.SECOND, -keepSeconds);
1074:                    Timestamp keepAfterStamp = new Timestamp(nowCal
1075:                            .getTimeInMillis());
1076:
1077:                    EntityListIterator eli = delegator
1078:                            .findListIteratorByCondition("EntitySyncRemove",
1079:                                    new EntityExpr(ModelEntity.STAMP_TX_FIELD,
1080:                                            EntityOperator.LESS_THAN,
1081:                                            keepAfterStamp), null, UtilMisc
1082:                                            .toList(ModelEntity.STAMP_TX_FIELD));
1083:                    GenericValue entitySyncRemove = null;
1084:                    int numRemoved = 0;
1085:                    List valuesToRemove = new LinkedList();
1086:                    while ((entitySyncRemove = (GenericValue) eli.next()) != null) {
1087:                        valuesToRemove.add(entitySyncRemove.getPrimaryKey());
1088:                        numRemoved++;
1089:                        // do 1000 at a time to avoid possible problems with removing values while iterating over a cursor
1090:                        if (numRemoved > 1000) {
1091:                            eli.close();
1092:                            delegator.removeAll(valuesToRemove);
1093:                            eli = delegator
1094:                                    .findListIteratorByCondition(
1095:                                            "EntitySyncRemove",
1096:                                            new EntityExpr(
1097:                                                    ModelEntity.STAMP_TX_FIELD,
1098:                                                    EntityOperator.LESS_THAN,
1099:                                                    keepAfterStamp),
1100:                                            null,
1101:                                            UtilMisc
1102:                                                    .toList(ModelEntity.STAMP_TX_FIELD));
1103:                        }
1104:                    }
1105:                    eli.close();
1106:
1107:                    return ServiceUtil.returnSuccess();
1108:                } catch (GenericEntityException e) {
1109:                    String errorMsg = "Error cleaning out EntitySyncRemove info: "
1110:                            + e.toString();
1111:                    Debug.logError(e, errorMsg, module);
1112:                    return ServiceUtil.returnError(errorMsg);
1113:                }
1114:            }
1115:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.