├── .gitignore ├── CODEOWNERS ├── CONTRIBUTING-ARCHIVED.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── datamigrator-core ├── .gitignore ├── pom.xml └── src │ └── main │ ├── java │ ├── META-INF │ │ └── MANIFEST.MF │ └── migrator │ │ └── core │ │ ├── MigrationProcess.java │ │ ├── buffer │ │ ├── SObjectBuffer.java │ │ └── SObjectDeleteBuffer.java │ │ ├── connect │ │ ├── SfdcConnection.java │ │ └── SfdcConnectionFactory.java │ │ ├── mask │ │ ├── IMasker.java │ │ └── Masker.java │ │ ├── service │ │ ├── ISforceObjectPair.java │ │ ├── ISourceLoader.java │ │ ├── MetadataObjectHolder.java │ │ ├── MetadataRefObject.java │ │ ├── MetadataService.java │ │ ├── PropertiesReader.java │ │ ├── SfdcApiService.java │ │ ├── SforceLookupProperties.java │ │ ├── SforceMasterDetail.java │ │ ├── SforceObject.java │ │ ├── SforceObjectPair.java │ │ └── impl │ │ │ ├── MappingGeneratorService.java │ │ │ ├── MetadataCompareService.java │ │ │ ├── MetadataServiceImpl.java │ │ │ ├── SfdcApiServiceImpl.java │ │ │ ├── SfdcSerializerService.java │ │ │ └── ValidatorService.java │ │ ├── sobject │ │ ├── Migrable.java │ │ ├── MigrableHierarchicalObject.java │ │ ├── MigrableLookupObject.java │ │ ├── MigrableMasterDetailObject.java │ │ ├── MigrableObject.java │ │ ├── MigrableObjectFactory.java │ │ └── ObjectMappingConfig.java │ │ └── utils │ │ ├── ComamndArgs.java │ │ ├── CommandVO.java │ │ ├── ForceFileUtils.java │ │ └── Utils.java │ └── resources │ └── log4j.properties ├── datamigrator-module ├── .gitignore ├── pom.xml └── src │ └── main │ ├── java │ └── migrator │ │ └── module │ │ └── client │ │ ├── DeleteAccounts.java │ │ ├── DeleteAll.java │ │ ├── DeleteProducts.java │ │ ├── GenerateMappingExample.java │ │ ├── MetadataCompareExample.java │ │ ├── MigrateAccounts.java │ │ ├── MigrateAccountsHierarchical.java │ │ ├── MigrateAll.java │ │ ├── MigrateOnlyProducts.java │ │ ├── MigrateProducts.java │ │ ├── MigrateProductsDelete.java │ │ ├── MigrateProductsWithExternalId.java │ │ ├── SfdcSerializeExample.java │ │ └── ValidateExample.java │ └── resources │ ├── build.properties │ └── object-mappings │ ├── AccountwithAssetsAndOppties.json │ ├── AccountwithAssetsAndOppties_hierarchical.json │ ├── PricebookEntry_nonstandard.json │ ├── PricebookEntry_nonstandard_extId.json │ ├── PricebookEntry_standard.json │ ├── PricebookEntry_standard_extId.json │ ├── Products.json │ └── Products2_extId.json ├── images ├── design.jpeg ├── json-mapping.png └── objects-relationships.png └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | bin/ 3 | target/ 4 | *.log 5 | 6 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Comment line immediately above ownership line is reserved for related gus information. Please be careful while editing. 2 | #ECCN:Open Source 3 | -------------------------------------------------------------------------------- /CONTRIBUTING-ARCHIVED.md: -------------------------------------------------------------------------------- 1 | # ARCHIVED 2 | 3 | This project is `Archived` and is no longer actively maintained; 4 | We are not accepting contributions or Pull Requests. 5 | 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | 1. Familiarize yourself with the codebase by reading the [wiki](wiki). 4 | 1. Create a new issue before starting your project so that we can keep track of 5 | what you are trying to add/fix. That way, we can also offer suggestions or 6 | let you know if there is already an effort in progress. 7 | 1. Fork this repository. 8 | 1. The [README](README.md) has details on how to set up your environment. 9 | 1. Create a _topic_ branch in your fork based on the correct branch (usually the **develop** branch, see [Branches section](#branches) below). Note, this step is recommended but technically not required if contributing using a fork. 10 | 1. Edit the code in your fork. 11 | 1. Sign CLA (see [CLA](#cla) below) 12 | 1. Send us a pull request when you are done. We'll review your code, suggest any 13 | needed changes, and merge it in. 14 | 15 | ### CLA 16 | 17 | External contributors will be required to sign a Contributor's License 18 | Agreement. You can do so by going to https://cla.salesforce.com/sign-cla. 19 | 20 | ## Branches 21 | 22 | - We work in `develop`. 23 | - Our released (aka. _production_) branch is `master`. 24 | - Our work happens in _topic_ branches (feature and/or bug-fix). 25 | - feature as well as bug-fix branches are based on `develop` 26 | - branches _should_ be kept up-to-date using `rebase` 27 | - see below for further merge instructions 28 | 29 | ### Merging between branches 30 | 31 | - We try to limit merge commits as much as possible. 32 | 33 | - They are usually only ok when done by our release automation. 34 | 35 | - _Topic_ branches are: 36 | 37 | 1. based on `develop` and will be 38 | 1. squash-merged into `develop`. 39 | 40 | - Hot-fix branches are an exception. 41 | - Instead we aim for faster cycles and a generally stable `develop` branch. 42 | 43 | ### Merging `develop` into `master` 44 | 45 | - When a development cycle finishes, the content of the `develop` branch will become the `master` branch 46 | 47 | ``` 48 | $ git checkout master 49 | $ git reset --hard develop 50 | $ 51 | $ # Using a custom commit message for the merge below 52 | $ git merge -m 'Merge -s our (where _ours_ is develop) releasing stream x.y.z.' -s ours origin/master 53 | $ git push origin master 54 | ``` 55 | 56 | ## Pull Requests 57 | 58 | - Develop features and bug fixes in _topic_ branches. 59 | - _Topic_ branches can live in forks (external contributors) or within this repository (committers). 60 | \*\* When creating _topic_ branches in this repository please prefix with `/`. 61 | 62 | ### Merging Pull Requests 63 | 64 | - Pull request merging is restricted to squash & merge only. 65 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Salesforce.com, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | * Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data-Migration-Tool (Datafall) 2 | 3 | *Data-Migration-Tool (Datafall)* is a tool that migrates the data from one Salesforce Org to another Salesforce Org. 4 | 5 | Migrating data between orgs can be a daunting ask, this is specially true if you have a complex data model in the form of parent-child, hierarchical, lookups, record types etc relationships. 6 | 7 | Doing so manually is error prone, time consuming, frustrating and not an ideal approach. We wrote a Java based tool using Salesforce SOAP to migrate the data from one Salesforce Org to another Salesforce Org. Data-Migration-Tool tool lets you migrate the data from one Salesforce Org to another Salesforce Org. This is a standalone java tool that one can run from a local machine. 8 | 9 | ## Build Data Migrator 10 | 11 | #### Tool has two modules. 12 | 13 | * datamigrator-core: This module has tools core classes 14 | * datamigrator-module: This module has sample examples on how the tool can be used to migrate different kind of related objects from one Salesforce org to another Salesforce org. *datamigrator-module* contains sample JSON object relationship mappings. 15 | 16 | #### Build 17 | git clone git@github.com:forcedotcom/Data-Migration-Tool.git 18 | cd Data-Migration-Tool 19 | mvn clean install 20 | 21 | #### Usage: Migrate Products, Pricebooks and PricebookEntries Sample 22 | 23 | # Enter Source and Target org credentials in `/datamigrator-module/src/main/resources/build.properties` 24 | mvn clean install 25 | mvn exec:java -Dexec.mainClass="migrator.module.client.MigrateProducts" -pl datamigrator-module 26 | 27 | ## Running in your IDE 28 | 29 | ### Overview 30 | 31 | You can load the project into your IDE and run the main class to kick-off the migration. We recommend using [Eclipse](http://www.eclipse.org/downloads/). Because this tool is a standard Maven project, you can import it into your IDE using the root `pom.xml` file. In Eclipse, choose Open from the File menu -> Import -> Maven -> and select `Existing Maven Projects` -> select the the root folder. 32 | 33 | After opening the project in Eclipse, you will see below two modules: 34 | 35 | * datamigrator-core: This module has tools core classes 36 | * datamigrator-module: Contains the mapping and main java classes to run the migration 37 | 38 | Tool comes with many main classes as a way to show different kind of mappings and migrations: 39 | 40 | * Main Class: `migrator.module.client.MigrateProducts` 41 | * Main Class: `migrator.module.client.MigrateAll` 42 | * Main Class: `migrator.module.client.MigrateAccounts` 43 | * Main Class: `migrator.module.client.MigrateAccountsHierarchical` 44 | 45 | and many more... 46 | 47 | 48 | ## Running using command line (More Sample Migrations...) 49 | To avoid creating duplicates in the target org, use [external ids](https://github.com/forcedotcom/Data-Migration-Tool/wiki/External-Id). This section has some examples using external ids. 50 | 51 | Migrate a simple object's records (no relationships) 52 | 53 | # Edit the object-mappings/Products.json with your object API name, save 54 | 55 | mvn exec:java -Dexec.mainClass="migrator.module.client.MigrateOnlyProducts" -pl datamigrator-module 56 | 57 | Migrate an object with lookups (Pricebook2 with lookup to Product) relationship 58 | 59 | # Edit the object-mappings/Products.json, PricebookEntry_nonstandard.json, PricebookEntry_standard.json with your object API name, save. 60 | 61 | mvn exec:java -Dexec.mainClass="migrator.module.client.MigrateProducts" -pl datamigrator-module 62 | 63 | Migrate an object with lookups (Pricebook2 with lookup to Product) relationship with External Ids 64 | 65 | # Edit the object-mappings/Products_extId.json, PricebookEntry_nonstandard_extId.json, PricebookEntry_standard_extId.json with your object API name, save. 66 | 67 | mvn exec:java -Dexec.mainClass="migrator.module.client.MigrateProductsWithExternalId" -pl datamigrator-module 68 | 69 | Migrate object's with masterdetail (Accounts/Assets/Oppties) relationships 70 | 71 | # Edit the object-mappings/AccountwithAssetsAndOppties.json with your object API names, save 72 | 73 | mvn exec:java -Dexec.mainClass="migrator.module.client.MigrateAccounts" -pl datamigrator-module 74 | 75 | Migrate object's with hierarchical relationships 76 | 77 | # Edit the object-mappings/AccountwithAssetsAndOppties_hierarchical.json with your object API names, save 78 | 79 | mvn exec:java -Dexec.mainClass="migrator.module.client.MigrateAccountsHierarchical" -pl datamigrator-module 80 | 81 | Migrate multiple object's in a single run 82 | 83 | # Edit the object-mappings as referenced in MigrateAll.java with your object API names, save 84 | 85 | mvn exec:java -Dexec.mainClass="migrator.module.client.MigrateAll" -pl 86 | datamigrator-module 87 | 88 | Migrate Accounts with Opportunities and Assets. Make sure you edit the JSON with your external ids from Accounts with Opportunities and Assets objects. 89 | 90 | # Edit the object-mappings/AccountwithAssetsAndOppties_hierarchical.json with your object's external Id API name, save 91 | 92 | mvn exec:java -Dexec.mainClass="migrator.module.client.MigrateAccountsHierarchical" -pl datamigrator-module 93 | 94 | 95 | ## Usage (Sample Deletions from Target Org) 96 | 97 | Delete a simple object's records 98 | 99 | # Edit the object-mappings/Products.json with your object API name, save 100 | 101 | mvn exec:java -Dexec.mainClass="migrator.module.client.DeleteProducts" -pl datamigrator-module 102 | 103 | Delete multiple object's records in a single run 104 | 105 | # Edit the object-mappings as referenced in DeleteAll.java with your object API names, save 106 | 107 | mvn exec:java -Dexec.mainClass="migrator.module.client.DeleteAll" -pl datamigrator-module 108 | 109 | 110 | ## Usage (Compare objects metadata in source and target org) 111 | 112 | Compare objects Metadata in source and target org 113 | 114 | mvn exec:java -Dexec.mainClass="migrator.module.client.MetadataCompareExample" -Dexec.args="object1,object2" -pl datamigrator-module 115 | 116 | ## Usage (Given a set of objects, create a JSON mapping structure) 117 | 118 | Given a set of objects, create a JSON mapping structure 119 | 120 | mvn exec:java -Dexec.mainClass="migrator.module.client.GenerateMappingExample" -Dexec.args="object1,object2" -pl datamigrator-module 121 | 122 | ## Usage (Counts the number of records in source and target org) 123 | 124 | Once migration has completed, you may want to compare the number of records in source and target org 125 | 126 | mvn exec:java -Dexec.mainClass="migrator.module.client.ValidateExample" -Dexec.args="object1,object2" -pl datamigrator-module 127 | 128 | 129 | # More Advanced Object Relationship JSON Mappings, Resources 130 | 131 | For more information, see the [wiki](https://github.com/forcedotcom/Data-Migration-Tool/wiki) 132 | 133 | ## Authors 134 | 135 | Anoop Singh by [Anoop Singh](mailto:anoop.singh@salesforce.com, anoop_76@yahoo.com) 136 | -------------------------------------------------------------------------------- /datamigrator-core/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /datamigrator-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | datamigrator.main 9 | datamigrator 10 | 0.0.1-SNAPSHOT 11 | 12 | 13 | datamigrator.main 14 | 0.0.1-SNAPSHOT 15 | datamigrator-core 16 | jar 17 | datamigrator-core 18 | 19 | 20 | 21 | 22 | maven-compiler-plugin 23 | 2.0.2 24 | 25 | 1.8 26 | 1.8 27 | 28 | 29 | 30 | org.codehaus.mojo 31 | exec-maven-plugin 32 | 33 | datamigrator.core.MigrationProcess 34 | 35 | 36 | 37 | maven-compiler-plugin 38 | 2.0.2 39 | 40 | 1.8 41 | 1.8 42 | 43 | 44 | 45 | org.codehaus.mojo 46 | exec-maven-plugin 47 | 48 | datamigrator.core.test.ValidatorExample 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | log4j 57 | log4j 58 | 1.2.17 59 | 60 | 61 | org.slf4j 62 | slf4j-api 63 | 1.7.7 64 | 65 | 66 | 67 | org.slf4j 68 | jcl-over-slf4j 69 | 1.7.7 70 | 71 | 72 | org.json 73 | json 74 | 20090211 75 | 76 | 77 | commons-io 78 | commons-io 79 | 2.5 80 | 81 | 82 | com.force.api 83 | force-wsc 84 | 44.0.0 85 | 86 | 87 | com.force.api 88 | force-partner-api 89 | 44.0.0 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/MigrationProcess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core; 27 | 28 | import migrator.core.sobject.MigrableObjectFactory; 29 | import migrator.core.utils.CommandVO; 30 | 31 | /** 32 | * Main class to kick-off migrations 33 | * 34 | * @author anoop.singh 35 | */ 36 | public class MigrationProcess { 37 | 38 | // Constructor 39 | public MigrationProcess() {} 40 | 41 | public void process(String operation, String json) { 42 | 43 | // USAGE: -operation create|delete -mapping 44 | // mapping/checkout/1.productpackaging_masterdetail.json 45 | CommandVO vo = new CommandVO(operation, json); 46 | MigrableObjectFactory.migrate(vo, false); 47 | } 48 | 49 | /** 50 | * 51 | * -Dexec.args="-operation $Operation -json $JSON 52 | * 53 | * 54 | */ 55 | static public void main(String[] args) { 56 | MigrationProcess connector = new MigrationProcess(); 57 | String json = null; 58 | StringBuffer jsonSb = new StringBuffer(); 59 | int counter = 0; 60 | for (String arg : args) { 61 | if (counter < 3) { 62 | } else { 63 | jsonSb.append(arg); 64 | } 65 | counter++; 66 | } 67 | json = jsonSb.toString(); 68 | if (System.getProperty("json") != null) { 69 | json = System.getProperty("json"); 70 | } 71 | 72 | System.out.println("Operation::: " + args[1]); 73 | System.out.println("JSON::: " + json); 74 | connector.process(args[1], json); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/buffer/SObjectBuffer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.buffer; 27 | 28 | import com.sforce.soap.partner.sobject.SObject; 29 | 30 | /** 31 | * Acts as a buffer 32 | * 33 | * @author anoop.singh 34 | */ 35 | public class SObjectBuffer { 36 | private SObject[] inserts = null; 37 | int index = 0; 38 | 39 | int size = 0; 40 | // adjust the buffer size as per your need 41 | int batchSize = 200; 42 | 43 | public SObjectBuffer(SObject[] inserts) { 44 | this.inserts = inserts; 45 | this.size = inserts.length; 46 | } 47 | 48 | public SObjectBuffer(SObject[] inserts, int batchSize) { 49 | this.inserts = inserts; 50 | this.size = inserts.length; 51 | this.batchSize = batchSize; 52 | } 53 | 54 | public boolean hasAvailable() { 55 | if (index == size) { 56 | return false; 57 | } 58 | if (index < size) 59 | return true; 60 | return false; 61 | } 62 | 63 | public SObject[] getBuffer() { 64 | int newSize = 0; 65 | if ((size - index) > batchSize) { 66 | newSize = batchSize; 67 | } else { 68 | newSize = size - index; 69 | } 70 | SObject[] buffer = new SObject[newSize]; 71 | 72 | for (int i = 0; i < newSize; i++) { 73 | buffer[i] = inserts[index]; 74 | index++; 75 | } 76 | return buffer; 77 | } 78 | 79 | /** 80 | * @return the inserts 81 | */ 82 | public SObject[] getInserts() { 83 | return inserts; 84 | } 85 | 86 | /** 87 | * @return the index 88 | */ 89 | public int getIndex() { 90 | return index; 91 | } 92 | 93 | /** 94 | * @return the size 95 | */ 96 | public int getSize() { 97 | return size; 98 | } 99 | 100 | /** 101 | * @return the batchSize 102 | */ 103 | public int getBatchSize() { 104 | return batchSize; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/buffer/SObjectDeleteBuffer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.buffer; 27 | 28 | /** 29 | * Acts as a delete buffer 30 | * 31 | * @author anoop.singh 32 | */ 33 | 34 | public class SObjectDeleteBuffer { 35 | private String[] ids = null; 36 | int index = 0; 37 | int size = 0; 38 | // adjust the buffer size as per your need 39 | int batchSize = 200; 40 | 41 | public SObjectDeleteBuffer(String[] ids) { 42 | this.ids = ids; 43 | this.size = ids.length; 44 | } 45 | 46 | public boolean hasAvailable() { 47 | if (index == size) { 48 | return false; 49 | } 50 | if (index < size) 51 | return true; 52 | return false; 53 | } 54 | 55 | public String[] getBuffer() { 56 | int newSize = 0; 57 | if ((size - index) > batchSize) { 58 | newSize = batchSize; 59 | } else { 60 | newSize = size - index; 61 | } 62 | String[] buffer = new String[newSize]; 63 | 64 | for (int i = 0; i < newSize; i++) { 65 | buffer[i] = ids[index]; 66 | index++; 67 | } 68 | return buffer; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/connect/SfdcConnection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.connect; 27 | 28 | import java.util.List; 29 | import java.util.ArrayList; 30 | import org.apache.log4j.Logger; 31 | import com.sforce.soap.partner.PartnerConnection; 32 | import com.sforce.soap.partner.GetUserInfoResult; 33 | import com.sforce.ws.ConnectorConfig; 34 | import com.sforce.ws.ConnectionException; 35 | import migrator.core.service.PropertiesReader; 36 | import migrator.core.sobject.MigrableObject; 37 | import migrator.core.utils.Utils; 38 | 39 | /** 40 | * SfdcConnection 41 | * 42 | * @author anoop.singh 43 | */ 44 | public class SfdcConnection { 45 | 46 | PartnerConnection connectionSource; 47 | PartnerConnection connectionTarget; 48 | 49 | List connectionTargets; 50 | 51 | String sourceUserName = ""; 52 | String sourcePassword = ""; 53 | String sourceAuthEndPoint = ""; 54 | String targetUserName = ""; 55 | String targetPassword = ""; 56 | String targetAuthEndPoint = ""; 57 | String proxyHost = ""; 58 | String proxyPort = ""; 59 | 60 | long lastSalesforceLoginTime; 61 | 62 | static Logger log = Logger.getLogger(SfdcConnection.class.getName()); 63 | 64 | public enum ORG_TYPE { 65 | SOURCE, TARGET 66 | } 67 | 68 | public SfdcConnection() { 69 | lastSalesforceLoginTime = System.currentTimeMillis(); 70 | this.connectionTargets = new ArrayList(); 71 | readProperties(); 72 | } 73 | 74 | // Constructor 75 | 76 | public SfdcConnection(String sourceAuthEndPoint, String targetAuthEndPoint) { 77 | lastSalesforceLoginTime = System.currentTimeMillis(); 78 | this.connectionTargets = new ArrayList(); 79 | 80 | this.sourceAuthEndPoint = sourceAuthEndPoint; 81 | this.targetAuthEndPoint = targetAuthEndPoint; 82 | readProperties(); 83 | } 84 | 85 | public PartnerConnection getSourceConnection() { 86 | return connectionSource; 87 | } 88 | 89 | public PartnerConnection getTargetConnection() { 90 | return connectionTarget; 91 | } 92 | 93 | public boolean login() { 94 | boolean isSuccess = loginTarget(); 95 | if (!isSuccess) 96 | return false; 97 | 98 | String sourceType = 99 | PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "source.type"); 100 | if (sourceType == null || sourceType.equals("org")) { 101 | // Make a login call 102 | isSuccess = loginSource(); 103 | if (!isSuccess) 104 | return false; 105 | } 106 | return true; 107 | } 108 | 109 | public boolean loginSource() { 110 | System.out.println("\nloginSource START..."); 111 | 112 | boolean success = false; 113 | 114 | try { 115 | ConnectorConfig config = new ConnectorConfig(); 116 | config.setUsername(sourceUserName); 117 | config.setPassword(sourcePassword); 118 | 119 | System.out.println("AuthEndPoint: " + sourceAuthEndPoint); 120 | config.setAuthEndpoint(sourceAuthEndPoint); 121 | if (!proxyHost.equals("")) { 122 | config.setProxy(proxyHost, new Integer(proxyPort)); 123 | } 124 | 125 | connectionSource = new PartnerConnection(config); 126 | 127 | // Add source to blacklisted urls. We never want to 128 | // create/update/delete anything in source 129 | Utils.updateBlackListedUrls(config.getServiceEndpoint().toLowerCase()); 130 | 131 | printUserInfo(config); 132 | 133 | success = true; 134 | } catch (ConnectionException ce) { 135 | ce.printStackTrace(); 136 | } 137 | System.out.println("loginSource END...\n\n"); 138 | return success; 139 | } 140 | 141 | public boolean loginTarget() { 142 | System.out.println("\nloginTarget START ..."); 143 | 144 | boolean success = false; 145 | 146 | try { 147 | ConnectorConfig config = new ConnectorConfig(); 148 | config.setUsername(targetUserName); 149 | config.setPassword(targetPassword); 150 | 151 | System.out.println("AuthEndPoint: " + targetAuthEndPoint); 152 | config.setAuthEndpoint(targetAuthEndPoint); 153 | if (!proxyHost.equals("")) { 154 | config.setProxy(proxyHost, new Integer(proxyPort)); 155 | } 156 | 157 | connectionTarget = new PartnerConnection(config); 158 | 159 | printUserInfoImport(config, connectionTarget); 160 | 161 | success = true; 162 | } catch (ConnectionException ce) { 163 | ce.printStackTrace(); 164 | } 165 | 166 | loginTargetMulti(); 167 | 168 | System.out.println("loginTarget END..."); 169 | return success; 170 | } 171 | 172 | private void loginTargetMulti() { 173 | if (connectionTargets.size() > 0) { 174 | return; 175 | } 176 | 177 | try { 178 | int threadCount = 1; 179 | 180 | System.out.println("target.threads.count=" 181 | + PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, 182 | "target.threads.count")); 183 | if (PropertiesReader.getInstance() 184 | .getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "target.threads.count") != null 185 | && !PropertiesReader.getInstance() 186 | .getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "target.threads.count").equals("")) { 187 | threadCount = 188 | new Integer(PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, 189 | "target.threads.count")).intValue(); 190 | } 191 | 192 | if (threadCount <= 1) { 193 | connectionTargets.add(connectionTarget); 194 | return; 195 | } 196 | 197 | for (int i = 0; i < threadCount; i++) { 198 | 199 | ConnectorConfig config = new ConnectorConfig(); 200 | config.setUsername(PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, 201 | "target.sfdc.login")); 202 | config.setPassword(PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, 203 | "target.sfdc.password")); 204 | 205 | System.out.println("AuthEndPoint:: " + targetAuthEndPoint); 206 | config.setAuthEndpoint(targetAuthEndPoint); 207 | 208 | PartnerConnection connTarget = new PartnerConnection(config); 209 | connectionTargets.add(connTarget); 210 | 211 | printUserInfoImport(config, connTarget); 212 | } 213 | 214 | } catch (ConnectionException ce) { 215 | ce.printStackTrace(); 216 | } 217 | 218 | } 219 | 220 | private void readProperties() { 221 | // get the property value and print it out 222 | sourceUserName = 223 | PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "source.sfdc.login"); 224 | sourcePassword = 225 | PropertiesReader.getInstance() 226 | .getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "source.sfdc.password"); 227 | sourceAuthEndPoint = 228 | PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "source.env.endpoint"); 229 | targetUserName = 230 | PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "target.sfdc.login"); 231 | targetPassword = 232 | PropertiesReader.getInstance() 233 | .getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "target.sfdc.password"); 234 | targetAuthEndPoint = 235 | PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "target.env.endpoint"); 236 | proxyHost = PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "env.proxy.host"); 237 | proxyPort = PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "env.proxy.port"); 238 | } 239 | 240 | private void printUserInfo(ConnectorConfig config) { 241 | try { 242 | GetUserInfoResult userInfo = connectionSource.getUserInfo(); 243 | 244 | System.out.println("\nSource Logging in ...\n"); 245 | System.out.println("Source UserID: " + userInfo.getUserId()); 246 | System.out.println("Source User Name: " + userInfo.getUserName()); 247 | System.out.println("Source User Email: " + userInfo.getUserEmail()); 248 | System.out.println(); 249 | 250 | System.out.println("Source Auth End Point: " + config.getAuthEndpoint()); 251 | System.out.println("Source Service End Point: " + config.getServiceEndpoint()); 252 | System.out.println(); 253 | } catch (ConnectionException ce) { 254 | ce.printStackTrace(); 255 | } 256 | } 257 | 258 | private void printUserInfoImport(ConnectorConfig config, PartnerConnection connectionTarget) { 259 | try { 260 | GetUserInfoResult userInfoImport = connectionTarget.getUserInfo(); 261 | 262 | System.out.println("\nTarget Logging in ...\n"); 263 | System.out.println("Target UserID: " + userInfoImport.getUserId()); 264 | System.out.println("Target User Name: " + userInfoImport.getUserName()); 265 | System.out.println("Target User Email: " + userInfoImport.getUserEmail()); 266 | System.out.println(); 267 | 268 | System.out.println("Target Auth End Point: " + config.getAuthEndpoint()); 269 | System.out.println("Target Service End Point: " + config.getServiceEndpoint()); 270 | System.out.println(); 271 | } catch (ConnectionException ce) { 272 | ce.printStackTrace(); 273 | } 274 | } 275 | 276 | /** 277 | * @return the lastSalesforceLoginTime 278 | */ 279 | public long getLastSalesforceLoginTime() { 280 | return lastSalesforceLoginTime; 281 | } 282 | 283 | /** 284 | * @param lastSalesforceLoginTime the lastSalesforceLoginTime to set 285 | */ 286 | public void setLastSalesforceLoginTime(long lastSalesforceLoginTime) { 287 | this.lastSalesforceLoginTime = lastSalesforceLoginTime; 288 | } 289 | 290 | /** 291 | * @return the connectionTargets 292 | */ 293 | public List getConnectionTargets() { 294 | return connectionTargets; 295 | } 296 | 297 | /** 298 | * @param connectionTargets the connectionTargets to set 299 | */ 300 | public void setConnectionTargets(List connectionTargets) { 301 | this.connectionTargets = connectionTargets; 302 | } 303 | 304 | private void logout(PartnerConnection connection) { 305 | /* 306 | * try { connection.logout(); 307 | * 308 | * for(PartnerConnection conn : connectionTargets) { conn.logout(); } 309 | * connectionTargets.clear(); 310 | * 311 | * } catch (ConnectionException ce) { ce.printStackTrace(); } 312 | */ 313 | } 314 | 315 | public void disconnect() { 316 | log.info("Logging out..."); 317 | logout(connectionSource); 318 | // logout(connectionTarget); 319 | } 320 | 321 | } 322 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/connect/SfdcConnectionFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.connect; 27 | 28 | import org.apache.log4j.Logger; 29 | import com.sforce.soap.partner.PartnerConnection; 30 | import com.sforce.soap.partner.GetUserInfoResult; 31 | import com.sforce.ws.ConnectorConfig; 32 | import com.sforce.ws.ConnectionException; 33 | import migrator.core.service.PropertiesReader; 34 | import migrator.core.sobject.MigrableObject; 35 | import migrator.core.utils.Utils; 36 | 37 | /** 38 | * SfdcConnection 39 | * 40 | * @author anoop.singh 41 | */ 42 | public class SfdcConnectionFactory { 43 | 44 | private static SfdcConnection conn; 45 | 46 | static Logger log = Logger.getLogger(SfdcConnectionFactory.class.getName()); 47 | 48 | public static SfdcConnection getConnection() { 49 | if (conn == null) 50 | conn = new SfdcConnection(); 51 | return conn; 52 | } 53 | 54 | public static SfdcConnection getConnection(String sourceAccessToken, String targetAccessToken) { 55 | if (conn == null) 56 | conn = new SfdcConnection(sourceAccessToken, targetAccessToken); 57 | return conn; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/mask/IMasker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.mask; 27 | 28 | /** 29 | * Masker 30 | * 31 | * @author anoop.singh 32 | */ 33 | public interface IMasker { 34 | 35 | String mask(String input); 36 | 37 | Integer mask(Integer input); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/mask/Masker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.mask; 27 | 28 | import java.util.Random; 29 | 30 | /** 31 | * Masker 32 | * 33 | * @author anoop.singh At present very limited functionality, needs to add more. 34 | * 35 | */ 36 | public class Masker implements IMasker { 37 | 38 | final String cons = "bcdfghjklmnpqrstvwxz"; 39 | final String vowel = "aeiouy"; 40 | final String digit = "0123456789"; 41 | 42 | public String mask(String input) { 43 | int seed = 0; 44 | 45 | Random random = new Random(seed); 46 | char data[] = input.toCharArray(); 47 | 48 | for (int n = 0; n < data.length; ++n) { 49 | char ln = Character.toLowerCase(data[n]); 50 | if (cons.indexOf(ln) >= 0) 51 | data[n] = randomChar(random, cons, ln != data[n]); 52 | else if (vowel.indexOf(ln) >= 0) 53 | data[n] = randomChar(random, vowel, ln != data[n]); 54 | else if (digit.indexOf(ln) >= 0) 55 | data[n] = randomChar(random, digit, ln != data[n]); 56 | } 57 | return new String(data); 58 | } 59 | 60 | public Integer mask(Integer input) { 61 | return input; 62 | } 63 | 64 | char randomChar(Random random, String cs, boolean uppercase) { 65 | char c = cs.charAt(random.nextInt(cs.length())); 66 | return uppercase ? Character.toUpperCase(c) : c; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/ISforceObjectPair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service; 27 | 28 | import java.util.Map; 29 | import com.sforce.soap.partner.sobject.SObject; 30 | 31 | /** 32 | * Relate the source and target environment records 33 | * 34 | * @author anoop.singh 35 | */ 36 | public interface ISforceObjectPair { 37 | 38 | public String getSourceId(); 39 | 40 | public String getTargetId(); 41 | 42 | public void setSourceId(String id); 43 | 44 | public void setTargetId(String id); 45 | 46 | public SObject getSourceSObject(); 47 | 48 | public void setSourceSObject(SObject sObjectSelf); 49 | 50 | public Map getSourceSObjectParentMap(); 51 | 52 | public void setSourceSObjectParentMap(Map s); 53 | 54 | } 55 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/ISourceLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service; 27 | 28 | import java.util.ArrayList; 29 | import java.util.Map; 30 | import com.sforce.soap.partner.PartnerConnection; 31 | import com.sforce.soap.partner.QueryResult; 32 | 33 | /** 34 | * Queries the source (Source org or JSON from file system) 35 | * 36 | * @author anoop.singh 37 | */ 38 | public interface ISourceLoader { 39 | 40 | public ArrayList querySource(PartnerConnection connection, SforceObject sforceObject); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/MetadataObjectHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service; 27 | 28 | import java.util.HashSet; 29 | import java.util.List; 30 | import java.util.Map; 31 | import java.util.HashMap; 32 | import java.util.ArrayList; 33 | import java.util.Set; 34 | import com.sforce.soap.partner.Field; 35 | import com.sforce.soap.partner.FieldType; 36 | import migrator.core.connect.SfdcConnection; 37 | import migrator.core.service.impl.MetadataServiceImpl; 38 | 39 | /** 40 | * MetadataObjectHolder 41 | * 42 | * @author anoop.singh 43 | */ 44 | public class MetadataObjectHolder { 45 | private static MetadataObjectHolder holder = new MetadataObjectHolder(); 46 | private Map describeObjectMap = null; 47 | private Map targetDescribeObjectMap = null; 48 | 49 | private MetadataObjectHolder() { 50 | describeObjectMap = new HashMap(); 51 | targetDescribeObjectMap = new HashMap(); 52 | } 53 | 54 | public static MetadataObjectHolder getInstance() { 55 | return holder; 56 | } 57 | 58 | public Map getDescribeRefObjectMap() { 59 | return describeObjectMap; 60 | } 61 | 62 | public MetadataRefObject get(String key) { 63 | return describeObjectMap.get(key); 64 | } 65 | 66 | public void put(String key, MetadataRefObject value) { 67 | describeObjectMap.put(key, value); 68 | } 69 | 70 | public Map getTargetDescribeRefObjectMap() { 71 | return targetDescribeObjectMap; 72 | } 73 | 74 | public MetadataRefObject init(SfdcConnection.ORG_TYPE orgType, SfdcConnection connection, String sObjectAPIName) { 75 | MetadataRefObject describeRefObject = holder.get(sObjectAPIName); 76 | if (describeRefObject == null) { 77 | describeRefObject = new MetadataServiceImpl(connection).process(orgType, sObjectAPIName); 78 | describeObjectMap.put(sObjectAPIName, describeRefObject); 79 | } 80 | return describeRefObject; 81 | } 82 | 83 | public MetadataRefObject init(SfdcConnection.ORG_TYPE orgType, SfdcConnection connection, String sObjectAPIName, 84 | List migrableObjects) { 85 | MetadataRefObject describeRefObject = holder.get(sObjectAPIName); 86 | describeRefObject = 87 | new MetadataServiceImpl(connection).process(orgType, sObjectAPIName, true, migrableObjects); 88 | describeObjectMap.put(sObjectAPIName, describeRefObject); 89 | return describeRefObject; 90 | } 91 | 92 | public MetadataRefObject initTarget(SfdcConnection.ORG_TYPE orgType, SfdcConnection connection, 93 | String sObjectAPIName, List migrableObjects) { 94 | MetadataRefObject describeRefObject = 95 | new MetadataServiceImpl(connection).process(orgType, sObjectAPIName, true, migrableObjects); 96 | targetDescribeObjectMap.put(sObjectAPIName, describeRefObject); 97 | return describeRefObject; 98 | } 99 | 100 | public static class MetadataRefObject { 101 | 102 | private String objectName; 103 | private Map fieldInfoMap; 104 | private List fieldList; 105 | private String fieldsAsString; 106 | private String primitiveFieldAsString; 107 | 108 | private List referecensTo; 109 | private String spitMapping; 110 | private List primitiveFieldList; 111 | private Map referecensToMap; 112 | private Map fieldToTypeMap; 113 | private Map fieldToTypeMapAll; 114 | 115 | private Map sourceIdToNameRecordTypeMap; 116 | private Map targetNameToIdRecordTypeMap; 117 | private List childRelationships; 118 | 119 | private List masters; 120 | private Map lookupsMap; 121 | 122 | private Set fieldListAsSet; 123 | private Set createableFieldSet; 124 | private Set updateableFieldSet; 125 | 126 | public MetadataRefObject(String objectName) { 127 | this.objectName = objectName; 128 | this.childRelationships = new ArrayList(); 129 | this.masters = new ArrayList(); 130 | this.lookupsMap = new HashMap(); 131 | this.fieldToTypeMapAll = new HashMap(); 132 | this.fieldListAsSet = new HashSet(); 133 | this.createableFieldSet = new HashSet(); 134 | this.updateableFieldSet = new HashSet(); 135 | } 136 | 137 | public String getObjectName() { 138 | return objectName; 139 | } 140 | 141 | public Map getFieldInfoMap() { 142 | return fieldInfoMap; 143 | } 144 | 145 | public void setFieldInfoMap(Map map) { 146 | this.fieldInfoMap = map; 147 | } 148 | 149 | public List getFieldList() { 150 | return fieldList; 151 | } 152 | 153 | public void setFieldList(List list) { 154 | this.fieldList = list; 155 | } 156 | 157 | public List getPrimitiveFieldList() { 158 | return primitiveFieldList; 159 | } 160 | 161 | public void setPrimitiveFieldList(List primitiveFieldList) { 162 | this.primitiveFieldList = primitiveFieldList; 163 | } 164 | 165 | public List getReferecensTo() { 166 | return referecensTo; 167 | } 168 | 169 | public void setReferecensTo(List list) { 170 | this.referecensTo = list; 171 | } 172 | 173 | public Map getReferecensToMap() { 174 | return referecensToMap; 175 | } 176 | 177 | public void setReferecensToMap(Map referecensToMap) { 178 | this.referecensToMap = referecensToMap; 179 | } 180 | 181 | public String getFieldsAsString() { 182 | return fieldsAsString; 183 | } 184 | 185 | public void setFieldsAsString(String fieldAsString) { 186 | this.fieldsAsString = fieldAsString; 187 | } 188 | 189 | public Map getSourceIdToNameRecordTypeMap() { 190 | return sourceIdToNameRecordTypeMap; 191 | } 192 | 193 | public void setSourceIdToNameRecordTypeMap(Map sourceIdToNameRecordTypeMap) { 194 | this.sourceIdToNameRecordTypeMap = sourceIdToNameRecordTypeMap; 195 | } 196 | 197 | public Map getTargetNameToIdRecordTypeMap() { 198 | return targetNameToIdRecordTypeMap; 199 | } 200 | 201 | public void setTargetNameToIdRecordTypeMap(Map targetNameToIdRecordTypeMap) { 202 | this.targetNameToIdRecordTypeMap = targetNameToIdRecordTypeMap; 203 | } 204 | 205 | public String getSpitMapping() { 206 | return spitMapping; 207 | } 208 | 209 | public void setSpitMapping(String spitMapping) { 210 | this.spitMapping = spitMapping; 211 | } 212 | 213 | public List getChildRelationships() { 214 | return childRelationships; 215 | } 216 | 217 | public List getMasters() { 218 | return masters; 219 | } 220 | 221 | public Map getLookupsMap() { 222 | return lookupsMap; 223 | } 224 | 225 | /** 226 | * @return the primitiveFieldAsString 227 | */ 228 | public String getPrimitiveFieldAsString() { 229 | return primitiveFieldAsString; 230 | } 231 | 232 | /** 233 | * @param primitiveFieldAsString the primitiveFieldAsString to set 234 | */ 235 | public void setPrimitiveFieldAsString(String primitiveFieldAsString) { 236 | this.primitiveFieldAsString = primitiveFieldAsString; 237 | } 238 | 239 | /** 240 | * @return the fieldListAsSet 241 | */ 242 | public Set getFieldListAsSet() { 243 | return fieldListAsSet; 244 | } 245 | 246 | /** 247 | * @param fieldListAsSet the fieldListAsSet to set 248 | */ 249 | public void setFieldListAsSet(Set fieldListAsSet) { 250 | this.fieldListAsSet = fieldListAsSet; 251 | } 252 | 253 | /** 254 | * @return the fieldToTypeMap 255 | */ 256 | public Map getFieldToTypeMap() { 257 | return fieldToTypeMap; 258 | } 259 | 260 | /** 261 | * @param fieldToTypeMap the fieldToTypeMap to set 262 | */ 263 | public void setFieldToTypeMap(Map fieldToTypeMap) { 264 | this.fieldToTypeMap = fieldToTypeMap; 265 | } 266 | 267 | /** 268 | * @return the fieldToTypeMapAll 269 | */ 270 | public Map getFieldToTypeMapAll() { 271 | return fieldToTypeMapAll; 272 | } 273 | 274 | public Set getCreateableFieldSet() { 275 | return createableFieldSet; 276 | } 277 | 278 | public void setCreateableFieldSet(Set createableFieldSet) { 279 | this.createableFieldSet = createableFieldSet; 280 | } 281 | 282 | public Set getUpdateableFieldSet() { 283 | return updateableFieldSet; 284 | } 285 | 286 | public void setUpdateableFieldSet(Set updateableFieldSet) { 287 | this.updateableFieldSet = updateableFieldSet; 288 | } 289 | 290 | /** 291 | * @param fieldToTypeMapAll the fieldToTypeMapAll to set 292 | */ 293 | public void setFieldToTypeMapAll(Map fieldToTypeMapAll) { 294 | this.fieldToTypeMapAll = fieldToTypeMapAll; 295 | } 296 | 297 | public static class ChildRelationship { 298 | private String childSObject; 299 | private String field; 300 | private String relationshipName; 301 | 302 | public ChildRelationship(String childSObject, String field, String relationshipName) { 303 | this.childSObject = childSObject; 304 | this.field = field; 305 | this.relationshipName = relationshipName; 306 | } 307 | 308 | public String getChildSObject() { 309 | return childSObject; 310 | } 311 | 312 | public String getField() { 313 | return field; 314 | } 315 | 316 | public String getRelationshipName() { 317 | return relationshipName; 318 | } 319 | 320 | public String toString() { 321 | return "\n ChildSObject: " + childSObject + ", field: " + field + ", relationshipName:" 322 | + relationshipName + "\n"; 323 | } 324 | } 325 | 326 | public String toString() { 327 | return "\n" + spitMapping + "\n"; 328 | } 329 | } 330 | } 331 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/MetadataRefObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service; 27 | 28 | import java.util.List; 29 | import java.util.Map; 30 | import com.sforce.soap.partner.Field; 31 | 32 | /** 33 | * Container for describe object info. 34 | * 35 | * @author anoop.singh 36 | */ 37 | public class MetadataRefObject { 38 | 39 | private String objectName; 40 | private Map fieldInfoMap; 41 | private List fieldList; 42 | private String fieldsAsString; 43 | private List referecensTo; 44 | private String spitMapping; 45 | 46 | public MetadataRefObject(String objectName) { 47 | this.objectName = objectName; 48 | } 49 | 50 | public String getObjectName() { 51 | return objectName; 52 | } 53 | 54 | public Map getFieldInfoMap() { 55 | return fieldInfoMap; 56 | } 57 | 58 | public void setFieldInfoMap(Map map) { 59 | this.fieldInfoMap = map; 60 | } 61 | 62 | public List getFieldList() { 63 | return fieldList; 64 | } 65 | 66 | public void setFieldList(List list) { 67 | this.fieldList = list; 68 | } 69 | 70 | 71 | public List getReferecensTo() { 72 | return referecensTo; 73 | } 74 | 75 | public void setReferecensTo(List list) { 76 | this.referecensTo = list; 77 | } 78 | 79 | public String getFieldsAsString() { 80 | return fieldsAsString; 81 | } 82 | 83 | public void setFieldsAsString(String fieldAsString) { 84 | this.fieldsAsString = fieldAsString; 85 | } 86 | 87 | public String getSpitMapping() { 88 | return spitMapping; 89 | } 90 | 91 | public void setSpitMapping(String spitMapping) { 92 | this.spitMapping = spitMapping; 93 | } 94 | 95 | public String toString() { 96 | return "\n" + spitMapping + "\n"; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/MetadataService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service; 27 | 28 | import java.util.List; 29 | import migrator.core.connect.SfdcConnection; 30 | 31 | /** 32 | * MetadataService 33 | * 34 | * @author anoop.singh 35 | */ 36 | public interface MetadataService { 37 | 38 | public MetadataObjectHolder.MetadataRefObject process(SfdcConnection.ORG_TYPE orgType, String sObjectName); 39 | 40 | public List getFields(); 41 | 42 | public String getFieldsAsString(); 43 | 44 | public List getReferenceTo(); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/PropertiesReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service; 27 | 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.util.Properties; 31 | import java.util.Set; 32 | 33 | /** 34 | * PropertiesReader 35 | * 36 | * @author anoop.singh 37 | */ 38 | public class PropertiesReader { 39 | 40 | public static enum PROPERTY_TYPE { 41 | BUILD 42 | } 43 | 44 | private final Properties buildProp = new Properties(); 45 | 46 | private PropertiesReader() { 47 | InputStream in2 = this.getClass().getClassLoader().getResourceAsStream("build.properties"); 48 | try { 49 | buildProp.load(in2); 50 | // Load override if available as system properties 51 | for (Object key : this.buildProp.keySet()) { 52 | String override = System.getProperty((String) key); 53 | if (override != null) 54 | buildProp.put(key, override); 55 | } 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | 61 | private static class LazyHolder { 62 | private static final PropertiesReader INSTANCE = new PropertiesReader(); 63 | } 64 | 65 | public static PropertiesReader getInstance() { 66 | return LazyHolder.INSTANCE; 67 | } 68 | 69 | public String getProperty(PROPERTY_TYPE propType, String key) { 70 | switch (propType) { 71 | case BUILD: 72 | return buildProp.getProperty(key) != null ? buildProp.getProperty(key).trim() : buildProp 73 | .getProperty(key); 74 | } 75 | return ""; 76 | } 77 | 78 | public Set getAllPropertyNames(PROPERTY_TYPE propType) { 79 | 80 | switch (propType) { 81 | case BUILD: 82 | return buildProp.stringPropertyNames(); 83 | } 84 | return null; 85 | } 86 | 87 | public boolean containsKey(PROPERTY_TYPE propType, String key) { 88 | switch (propType) { 89 | case BUILD: 90 | return buildProp.containsKey(key); 91 | } 92 | return false; 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/SfdcApiService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service; 27 | 28 | import com.sforce.soap.partner.PartnerConnection; 29 | import com.sforce.soap.partner.QueryResult; 30 | import com.sforce.soap.partner.sobject.SObject; 31 | import migrator.core.connect.SfdcConnection; 32 | import java.util.ArrayList; 33 | import java.util.List; 34 | import java.util.Map; 35 | 36 | /** 37 | * SfdcApiService 38 | * 39 | * @author anoop.singh 40 | */ 41 | public interface SfdcApiService { 42 | 43 | public Map persistJson(PartnerConnection connection, SforceObject sforceObject, 44 | Map sObjectRecordsMap, boolean bSource); 45 | 46 | 47 | /** 48 | * Queries the Object based on the its API name. The results are stored in the sObjectRecords 49 | * List This method queries the standalone objects only (aka parent). 50 | * 51 | * @param PartnerConnection connection: connection to Salesforce org 52 | * @param String sObjectAPIName: Object to be queried (API name) 53 | * @param Map sObjectRecordsMap: Map to park the results of the query 54 | * (SObjects) with source id being the key 55 | * @param boolean source: True for source environment, otherwise its for target environment 56 | * 57 | */ 58 | public Map query(PartnerConnection connection, SforceObject sforceObject, 59 | Map sObjectRecordsMap, boolean bSource); 60 | 61 | /** 62 | * Queries the Object based on the its API name. The results are stored in the sObjectRecords 63 | * List This method queries the standalone objects only (aka parent). 64 | * 65 | * @param PartnerConnection connection: connection to Salesforce org 66 | * @param String sObjectAPIName: Object to be queried (API name) 67 | * @param Map sObjectRecordsMap: List to park the results of the query (SObjects) 68 | * @param boolean source: True for source environment, otherwise its for target environment 69 | * 70 | */ 71 | public String query(PartnerConnection connection, SforceObject sforceObject, 72 | final Map sObjectRecordsMap, List compositeKeys, boolean source); 73 | 74 | public String queryValidate(PartnerConnection connection, SforceObject sforceObject, 75 | final Map sObjectRecordsMap, List compositeKeys, boolean source); 76 | 77 | /** 78 | * Counts number of records 79 | * 80 | * @param PartnerConnection connection: connection to Salesforce org 81 | * @param String sObjectAPIName: Object to be queried (API name) 82 | * 83 | */ 84 | public Integer queryValidate(PartnerConnection connection, SforceObject sforceObject); 85 | 86 | public String queryLookup(PartnerConnection connection, SforceObject sforceObject, 87 | Map> lookupPropertiesMap, boolean bSource); 88 | 89 | /** 90 | * Queries the Object based on the its API name. The results are stored in the sObjectRecords 91 | * List. This method queries the children objects. 92 | * 93 | * @param PartnerConnection connection: connection to Salesforce org 94 | * @param String sObjectAPIName: Object to be queried (API name) 95 | * @param Map sObjectRecordsMap: List to park the results of the query (SObjects) 96 | * @param SforceMasterDetail masterDetail: The field name and object names of the parents in 97 | * child SObject 98 | * 99 | */ 100 | public Map queryChildren(PartnerConnection connection, SforceObject sforceObject, 101 | Map sObjectRecordsMap, // Current object 102 | // records 103 | SforceMasterDetail masterDetail, // All the master records (few 104 | // cases may have more than 1 105 | // master) 106 | List sForceObjectList, boolean bSource); 107 | 108 | /** 109 | * Queries the Object based on the its API name. Returns the List of QueryResults 110 | * 111 | * @param PartnerConnection connection: connection to Salesforce org 112 | * @param String sObjectAPIName: Object to be queried (API name) 113 | * 114 | */ 115 | public ArrayList getQueryResults(PartnerConnection connection, SforceObject sforceObject); 116 | 117 | /** 118 | * Creates the records in the Target Salesforce Org. 119 | * 120 | * @param PartnerConnection connection: connection to Salesforce org 121 | * @param String sObjectAPIName: Object to be queried (API name) 122 | * @param List sObjectSourceRecords: SObject records from the source Org - Used to relate 123 | * records in source and target Orgs 124 | * @param SObject [] sObjectInsertRecords: SObject records to insert in the Target Org - Used to 125 | * fetch 126 | * @param Boolean relateSourceTargetRecs: True if source-target records needs to be mapped 1-1 127 | * 128 | */ 129 | public String[] create(PartnerConnection connection, SforceObject sforceObject, final List sObjectSourceRecords, 130 | final SObject[] sObjectInsertRecords, boolean relateSourceTargetRecs); 131 | 132 | public String[] upsertWithExternalId(PartnerConnection connection, SforceObject sforceObject, 133 | String sExternalIdField, final List sObjectSourceRecords, 134 | final SObject[] sObjectInsertRecords, boolean relateSourceTargetRecs, boolean bUpdate); 135 | 136 | /** 137 | * Delete the sobject records 138 | * 139 | * @param String sObjectAPIName: Object to be queried (API name) 140 | * @param sfdcConnection : always TARGET Org 141 | * 142 | */ 143 | public void delete(String sObjectName, SfdcConnection sfdcConnection); 144 | 145 | } 146 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/SforceLookupProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service; 27 | 28 | import java.util.List; 29 | import java.util.Set; 30 | 31 | /** 32 | * SforceLookupProperties 33 | * 34 | * @author anoop.singh 35 | */ 36 | public class SforceLookupProperties { 37 | String sObjectName; 38 | 39 | // e.g. {AccFunct__c, AccountFunction__c} 40 | String sLookupField; 41 | 42 | String sLookupSObjectName; 43 | 44 | private String where; 45 | 46 | List compositeKeyFields = null; 47 | 48 | private Set unmappedFieldsSet; 49 | 50 | // External Id field 51 | private String externalIdField; 52 | 53 | public String getExternalIdField() { 54 | return externalIdField; 55 | } 56 | 57 | public void setExternalIdField(String externalIdField) { 58 | this.externalIdField = externalIdField; 59 | } 60 | 61 | public Set getUnmappedFieldsSet() { 62 | return unmappedFieldsSet; 63 | } 64 | 65 | public void setUnmappedFieldsSet(Set unmappedFieldsSet) { 66 | this.unmappedFieldsSet = unmappedFieldsSet; 67 | } 68 | 69 | public SforceLookupProperties() {} 70 | 71 | public SforceLookupProperties(String sObjectName, String sLookupField, String sLookupSObjectName, 72 | List compositeKeyFields) { 73 | this.sObjectName = sObjectName; 74 | this.sLookupField = sLookupField; 75 | this.sLookupSObjectName = sLookupSObjectName; 76 | this.compositeKeyFields = compositeKeyFields; 77 | } 78 | 79 | public String getsObjectName() { 80 | return sObjectName; 81 | } 82 | 83 | public void setsObjectName(String sObjectName) { 84 | this.sObjectName = sObjectName; 85 | } 86 | 87 | public String getsLookupField() { 88 | return sLookupField; 89 | } 90 | 91 | public void setsLookupField(String sLookupField) { 92 | this.sLookupField = sLookupField; 93 | } 94 | 95 | public String getsLookupSObjectName() { 96 | return sLookupSObjectName; 97 | } 98 | 99 | public void setsLookupSObjectName(String sLookupSObjectName) { 100 | this.sLookupSObjectName = sLookupSObjectName; 101 | } 102 | 103 | public List getCompositeKeyFields() { 104 | return compositeKeyFields; 105 | } 106 | 107 | public void setCompositeKeyFields(List compositeKeyFields) { 108 | this.compositeKeyFields = compositeKeyFields; 109 | } 110 | 111 | public String getWhere() { 112 | return where; 113 | } 114 | 115 | public void setWhere(String where) { 116 | this.where = where; 117 | } 118 | 119 | public String toString() { 120 | return "SforceLookupProperties[" + "sObjectName:" + sObjectName + ", sLookupField:" + sLookupField 121 | + ", sLookupSObjectName:" + sLookupSObjectName + ", compositeKeyFields:" + compositeKeyFields + "]"; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/SforceMasterDetail.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service; 27 | 28 | import java.util.List; 29 | import java.util.Map; 30 | import java.util.Set; 31 | 32 | /** 33 | * Represents the child (detail) object in master-detail relationship 34 | * 35 | * @author anoop.singh 36 | */ 37 | public class SforceMasterDetail { 38 | String sObjectName; 39 | 40 | // e.g. {AccFunct__c, AccountFunction__c} 41 | Map parentFieldObjectMap; 42 | 43 | private int sequence; 44 | 45 | private String where; 46 | 47 | private Set unmappedFieldsSet; 48 | 49 | private List nullableFields; 50 | 51 | // Masked fields 52 | private Set maskedFieldsSet; 53 | 54 | // fields mapping 55 | private Map fieldsMapping; 56 | 57 | // default values 58 | private Map defaultValues; 59 | 60 | // Does this needs to be refreshed(this is mainly for hierarchical 61 | // relationships. e.g. Product2) 62 | private boolean refresh = false; 63 | 64 | // External Id field 65 | private String externalIdField; 66 | 67 | // batch size, default is 200 68 | private int batchSize; 69 | 70 | public SforceMasterDetail() { 71 | this.batchSize = 200; 72 | } 73 | 74 | public SforceMasterDetail(String sObjectName, Map parentFieldObjectMap) { 75 | this.sObjectName = sObjectName; 76 | this.parentFieldObjectMap = parentFieldObjectMap; 77 | this.batchSize = 200; 78 | } 79 | 80 | public String getsObjectName() { 81 | return sObjectName; 82 | } 83 | 84 | public void setsObjectName(String sObjectName) { 85 | this.sObjectName = sObjectName; 86 | } 87 | 88 | public Map getParentFieldObjectMap() { 89 | return parentFieldObjectMap; 90 | } 91 | 92 | public void setParentFieldObjectMap(Map parentFieldObjectMap) { 93 | this.parentFieldObjectMap = parentFieldObjectMap; 94 | } 95 | 96 | public int getSequence() { 97 | return sequence; 98 | } 99 | 100 | public void setSequence(int sequence) { 101 | this.sequence = sequence; 102 | } 103 | 104 | public String getExternalIdField() { 105 | return externalIdField; 106 | } 107 | 108 | public void setExternalIdField(String externalIdField) { 109 | this.externalIdField = externalIdField; 110 | } 111 | 112 | public String getWhere() { 113 | return where; 114 | } 115 | 116 | public void setWhere(String where) { 117 | this.where = where; 118 | } 119 | 120 | public boolean isRefresh() { 121 | return refresh; 122 | } 123 | 124 | public void setRefresh(boolean refresh) { 125 | this.refresh = refresh; 126 | } 127 | 128 | /** 129 | * @return the unmappedFieldsSet 130 | */ 131 | public Set getUnmappedFieldsSet() { 132 | return unmappedFieldsSet; 133 | } 134 | 135 | /** 136 | * @return the nullableFields 137 | */ 138 | public List getNullableFields() { 139 | return nullableFields; 140 | } 141 | 142 | /** 143 | * @param nullableFields the nullableFields to set 144 | */ 145 | public void setNullableFields(List nullableFields) { 146 | this.nullableFields = nullableFields; 147 | } 148 | 149 | /** 150 | * @param unmappedFieldsSet the unmappedFieldsSet to set 151 | */ 152 | public void setUnmappedFieldsSet(Set unmappedFieldsSet) { 153 | this.unmappedFieldsSet = unmappedFieldsSet; 154 | } 155 | 156 | public Set getMaskedFieldsSet() { 157 | return maskedFieldsSet; 158 | } 159 | 160 | public void setMaskedFieldsSet(Set maskedFieldsSet) { 161 | this.maskedFieldsSet = maskedFieldsSet; 162 | } 163 | 164 | public Map getFieldsMapping() { 165 | return fieldsMapping; 166 | } 167 | 168 | public void setFieldsMapping(Map fieldsMapping) { 169 | this.fieldsMapping = fieldsMapping; 170 | } 171 | 172 | public Map getDefaultValues() { 173 | return defaultValues; 174 | } 175 | 176 | public void setDefaultValues(Map defaultValues) { 177 | this.defaultValues = defaultValues; 178 | } 179 | 180 | public int getBatchSize() { 181 | return batchSize; 182 | } 183 | 184 | public void setBatchSize(int batchSize) { 185 | this.batchSize = batchSize; 186 | } 187 | 188 | public String toString() { 189 | return "SforceMasterDetail[" + "sObjectName:" + sObjectName + "]"; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/SforceObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service; 27 | 28 | import java.util.List; 29 | import java.util.Map; 30 | import java.util.HashMap; 31 | import java.util.Set; 32 | 33 | /** 34 | * Holds SObject fields and records 35 | * 36 | * @author anoop.singh 37 | */ 38 | 39 | public class SforceObject { 40 | 41 | // Object API name 42 | private String sObjectName; 43 | 44 | // External Id field 45 | private String externalIdField; 46 | 47 | // Unmapped fields 48 | private Set unmappedFieldsSet; 49 | 50 | // Nullbale fields 51 | private List nullableFields; 52 | 53 | // Masked fields 54 | private Set maskedFieldsSet; 55 | 56 | // fields mapping 57 | private Map fieldsMapping; 58 | 59 | // default values 60 | private Map defaultValues; 61 | 62 | // Where clause to use as-as 63 | private String where; 64 | 65 | // lookup keys 66 | private List compositeKeyFields; 67 | 68 | // Object API name 69 | private Class clazz; 70 | 71 | // 72 | private MetadataObjectHolder.MetadataRefObject descRefObject; 73 | 74 | // Map of SObject records (Paired records: from source and target orgs) 75 | // Key is source org id 76 | Map recordsMap = null; 77 | 78 | // Map of SObject records (Paired records: from source and target orgs) 79 | // based on composite key 80 | Map lookupRecordsMap = null; 81 | 82 | // Object API name 83 | private boolean isLookup = false; 84 | 85 | // Does this needs to be refreshed(this is mainly for hierarchical 86 | // relationships. e.g. Product2) 87 | private boolean refresh = false; 88 | 89 | // The lookup may have more than one lookup properties 90 | List lookupProperties; 91 | 92 | // e.g. {AccFunct__c, AccountFunction__c} 93 | Map parentFieldObjectMap; 94 | 95 | SforceMasterDetail masterDetail; 96 | 97 | private int sequence; 98 | 99 | private Set commonFields; 100 | 101 | // batch size, default is 200 102 | private int batchSize; 103 | 104 | public SforceObject() { 105 | recordsMap = new HashMap(); 106 | lookupRecordsMap = new HashMap(); 107 | parentFieldObjectMap = new HashMap(); 108 | 109 | isLookup = false; 110 | batchSize = 200; 111 | } 112 | 113 | public String getsObjectName() { 114 | return sObjectName; 115 | } 116 | 117 | public void setsObjectName(String sObjectName) { 118 | this.sObjectName = sObjectName; 119 | } 120 | 121 | public String getWhere() { 122 | return where; 123 | } 124 | 125 | public void setWhere(String where) { 126 | this.where = where; 127 | } 128 | 129 | public Class getsObjectClass() { 130 | return this.clazz; 131 | } 132 | 133 | public void setsObjectClass(Class cls) { 134 | clazz = cls; 135 | } 136 | 137 | public MetadataObjectHolder.MetadataRefObject getDescRefObject() { 138 | return descRefObject; 139 | } 140 | 141 | public void setDescRefObject(MetadataObjectHolder.MetadataRefObject descRefObject) { 142 | this.descRefObject = descRefObject; 143 | } 144 | 145 | public Map getRecordsMap() { 146 | return recordsMap; 147 | } 148 | 149 | public void setRecordsMap(Map records) { 150 | this.recordsMap = records; 151 | } 152 | 153 | public Map getLookupRecordsMap() { 154 | return lookupRecordsMap; 155 | } 156 | 157 | public void setLookupRecordsMap(Map lookupRecordsMap) { 158 | this.lookupRecordsMap = lookupRecordsMap; 159 | } 160 | 161 | public boolean isLookup() { 162 | return isLookup; 163 | } 164 | 165 | public void setLookup(boolean isLookup) { 166 | this.isLookup = isLookup; 167 | } 168 | 169 | public Map getParentFieldObjectMap() { 170 | return parentFieldObjectMap; 171 | } 172 | 173 | public void setParentFieldObjectMap(Map parentFieldObjectMap) { 174 | this.parentFieldObjectMap = parentFieldObjectMap; 175 | } 176 | 177 | public SforceMasterDetail getMasterDetail() { 178 | return masterDetail; 179 | } 180 | 181 | public void setMasterDetail(SforceMasterDetail masterDetail) { 182 | this.masterDetail = masterDetail; 183 | } 184 | 185 | public int getSequence() { 186 | return sequence; 187 | } 188 | 189 | public void setSequence(int sequence) { 190 | this.sequence = sequence; 191 | } 192 | 193 | public String getExternalIdField() { 194 | return externalIdField; 195 | } 196 | 197 | public void setExternalIdField(String externalIdField) { 198 | this.externalIdField = externalIdField; 199 | } 200 | 201 | public List getLookupProperties() { 202 | return lookupProperties; 203 | } 204 | 205 | public void setLookupProperties(List lookupProperties) { 206 | this.lookupProperties = lookupProperties; 207 | } 208 | 209 | public boolean isRefresh() { 210 | return refresh; 211 | } 212 | 213 | public void setRefresh(boolean refresh) { 214 | this.refresh = refresh; 215 | } 216 | 217 | /** 218 | * @return the unmappedFieldsSet 219 | */ 220 | public Set getUnmappedFieldsSet() { 221 | return unmappedFieldsSet; 222 | } 223 | 224 | /** 225 | * @param unmappedFieldsSet the unmappedFieldsSet to set 226 | */ 227 | public void setUnmappedFieldsSet(Set unmappedFieldsSet) { 228 | this.unmappedFieldsSet = unmappedFieldsSet; 229 | } 230 | 231 | public Set getMaskedFieldsSet() { 232 | return maskedFieldsSet; 233 | } 234 | 235 | public void setMaskedFieldsSet(Set maskedFieldsSet) { 236 | this.maskedFieldsSet = maskedFieldsSet; 237 | } 238 | 239 | public Map getFieldsMapping() { 240 | return fieldsMapping; 241 | } 242 | 243 | public void setFieldsMapping(Map fieldsMapping) { 244 | this.fieldsMapping = fieldsMapping; 245 | } 246 | 247 | public Map getDefaultValues() { 248 | return defaultValues; 249 | } 250 | 251 | public void setDefaultValues(Map defaultValues) { 252 | this.defaultValues = defaultValues; 253 | } 254 | 255 | /** 256 | * @return the nullableFields 257 | */ 258 | public List getNullableFields() { 259 | return nullableFields; 260 | } 261 | 262 | /** 263 | * @param nullableFields the nullableFields to set 264 | */ 265 | public void setNullableFields(List nullableFields) { 266 | this.nullableFields = nullableFields; 267 | } 268 | 269 | public List getCompositeKeyFields() { 270 | return compositeKeyFields; 271 | } 272 | 273 | public void setCompositeKeyFields(List compositeKeyFields) { 274 | this.compositeKeyFields = compositeKeyFields; 275 | } 276 | 277 | public String getTargetRecordTypeId(String sourceRecordTypeId) { 278 | String recordTypeName = descRefObject.getSourceIdToNameRecordTypeMap().get(sourceRecordTypeId); 279 | if (recordTypeName == null) { 280 | return null; 281 | } 282 | return descRefObject.getTargetNameToIdRecordTypeMap().get(recordTypeName); 283 | } 284 | 285 | /** 286 | * @return the commonFields 287 | */ 288 | public Set getCommonFields() { 289 | return commonFields; 290 | } 291 | 292 | /** 293 | * @param commonFields the commonFields to set 294 | */ 295 | public void setCommonFields(Set commonFields) { 296 | this.commonFields = commonFields; 297 | } 298 | 299 | public int getBatchSize() { 300 | return batchSize; 301 | } 302 | 303 | public void setBatchSize(int batchSize) { 304 | this.batchSize = batchSize; 305 | } 306 | 307 | public void cleanup() { 308 | if (recordsMap != null) 309 | recordsMap.clear(); 310 | if (lookupRecordsMap != null) 311 | lookupRecordsMap.clear(); 312 | if (lookupProperties != null) 313 | lookupProperties.clear(); 314 | if (parentFieldObjectMap != null) 315 | parentFieldObjectMap.clear(); 316 | if (masterDetail != null) 317 | masterDetail = null; 318 | if (commonFields != null) 319 | commonFields.clear(); 320 | } 321 | 322 | public String toString() { 323 | return "SforceObject[" + "sObjectName:" + sObjectName + ", isLookup:" + isLookup + ", sequence:" + sequence 324 | + ", refresh:" + refresh + ", externalIdField:" + externalIdField 325 | // + ", compositeKeyFields:" + compositeKeyFields 326 | + "]"; 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/SforceObjectPair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service; 27 | 28 | import java.util.Map; 29 | import java.util.HashMap; 30 | import com.sforce.soap.partner.sobject.SObject; 31 | 32 | /** 33 | * Wrapper class - Relate the source and target environment records 34 | * 35 | * @author anoop.singh 36 | */ 37 | public class SforceObjectPair implements ISforceObjectPair { 38 | 39 | // record id from source org 40 | protected String sourceId; 41 | // record id from target org 42 | protected String targetId; 43 | // This is self SObject (from source org) 44 | protected SObject sourceSObject; 45 | // This is self SObject (from target org) 46 | protected SObject targetSObject; 47 | // This is from source org (field, sobject) 48 | protected Map sourceSObjectParentMap; 49 | 50 | public SforceObjectPair() { 51 | sourceSObjectParentMap = new HashMap(); 52 | } 53 | 54 | public String getSourceId() { 55 | return this.sourceId; 56 | } 57 | 58 | public String getTargetId() { 59 | return this.targetId; 60 | } 61 | 62 | public void setSourceId(String id) { 63 | this.sourceId = id; 64 | } 65 | 66 | public void setTargetId(String id) { 67 | this.targetId = id; 68 | } 69 | 70 | public SObject getSourceSObject() { 71 | return this.sourceSObject; 72 | } 73 | 74 | public void setSourceSObject(SObject sObjectSelf) { 75 | this.sourceSObject = sObjectSelf; 76 | } 77 | 78 | public SObject getTargetSObject() { 79 | return targetSObject; 80 | } 81 | 82 | public void setTargetSObject(SObject targetSObjectSelf) { 83 | this.targetSObject = targetSObjectSelf; 84 | } 85 | 86 | public Map getSourceSObjectParentMap() { 87 | return sourceSObjectParentMap; 88 | } 89 | 90 | public void setSourceSObjectParentMap(Map sourceSObjectParentMap) { 91 | this.sourceSObjectParentMap = sourceSObjectParentMap; 92 | } 93 | 94 | public String toString() { 95 | return "SforceObjectPair[" + "sourceId:" + sourceId + ", targetId:" + targetId + "]"; 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/impl/MappingGeneratorService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service.impl; 27 | 28 | import java.util.Arrays; 29 | import java.util.Collections; 30 | import java.util.Comparator; 31 | import java.util.Map; 32 | import java.util.List; 33 | import java.util.ArrayList; 34 | import migrator.core.connect.SfdcConnection; 35 | import migrator.core.service.MetadataObjectHolder; 36 | 37 | /** 38 | * MappingGeneratorService - Generates the Java mapping from source to target 39 | * 40 | * @author anoop.singh 41 | */ 42 | public class MappingGeneratorService { 43 | 44 | public enum Type { 45 | METHOD, CLASS 46 | } 47 | 48 | public enum ImplType { 49 | LOOKUP, MASTERDETAIL, HIERARCHICAL 50 | } 51 | 52 | SfdcConnection sfdcConnection; 53 | List allRefObjects = null; 54 | 55 | public MappingGeneratorService() { 56 | sfdcConnection = new SfdcConnection(); 57 | if (!sfdcConnection.loginTarget()) { 58 | System.out.println("Login failed!"); 59 | return; 60 | } 61 | } 62 | 63 | public String generate(String args) { 64 | String[] objectsArray = args.split(","); 65 | List migrableObjects = Arrays.asList(objectsArray); 66 | 67 | for (String migrableObject : migrableObjects) { 68 | MetadataObjectHolder.getInstance().initTarget(SfdcConnection.ORG_TYPE.TARGET, sfdcConnection, 69 | migrableObject, migrableObjects); 70 | } 71 | // disconnect from source and target 72 | sfdcConnection.disconnect(); 73 | 74 | Map refObjectMap = 75 | MetadataObjectHolder.getInstance().getTargetDescribeRefObjectMap(); 76 | 77 | allRefObjects = new ArrayList(refObjectMap.values()); 78 | Collections.sort(allRefObjects, new Comparator() { 79 | @Override 80 | public int compare(MetadataObjectHolder.MetadataRefObject p1, MetadataObjectHolder.MetadataRefObject p2) { 81 | return -(p1.getChildRelationships().size() - p2.getChildRelationships().size()); // Ascending 82 | } 83 | }); 84 | 85 | attachParents(allRefObjects); 86 | attachLookups(allRefObjects); 87 | 88 | // Objects that don't have any parent, top-level 89 | List topRefObjects = getTopLevelObjects(allRefObjects); 90 | 91 | String json = generateJSON(topRefObjects); 92 | System.out.println("####### json #######: \n\n" + json); 93 | 94 | return json; 95 | } 96 | 97 | private void attachParents(List refObjects) { 98 | for (MetadataObjectHolder.MetadataRefObject refObject : refObjects) { 99 | 100 | if (refObject.getChildRelationships().size() > 0) { 101 | // This is parent object, get child and related parent-child 102 | for (MetadataObjectHolder.MetadataRefObject.ChildRelationship cr : refObject.getChildRelationships()) { 103 | MetadataObjectHolder.MetadataRefObject childRefObject = 104 | getRefObject(cr.getChildSObject(), refObjects); 105 | List masters = childRefObject.getMasters(); 106 | masters.add(refObject); 107 | } 108 | 109 | } 110 | } 111 | } 112 | 113 | private void attachLookups(List refObjects) { 114 | for (MetadataObjectHolder.MetadataRefObject refObject : refObjects) { 115 | 116 | if (refObject.getReferecensToMap().size() > 0) { 117 | // There are lookups, check if they are master detail, if so, just ignore them 118 | for (Map.Entry entry : refObject.getReferecensToMap().entrySet()) { 119 | 120 | String key = entry.getKey(); 121 | String value = entry.getValue(); 122 | 123 | if (key.equalsIgnoreCase("OwnerId") || key.equalsIgnoreCase("OwnerId") 124 | || key.equalsIgnoreCase("RecordTypeId") || key.equalsIgnoreCase("RecordType") 125 | || key.equalsIgnoreCase("User") || key.equalsIgnoreCase("Owner")) { 126 | continue; 127 | } 128 | 129 | // check if value is an actual object (parent or child), if so, ignore it, 130 | // otherwise, its a lookup (hack) 131 | if (getRefObject(value, refObjects) == null) { 132 | Map lookupMap = refObject.getLookupsMap(); 133 | lookupMap.put(key, value); 134 | } else { 135 | continue; 136 | } 137 | } 138 | } 139 | } 140 | } 141 | 142 | private MetadataObjectHolder.MetadataRefObject getRefObject(String childSObject, 143 | List refObjects) { 144 | for (MetadataObjectHolder.MetadataRefObject refObect : refObjects) { 145 | if (refObect.getObjectName().equalsIgnoreCase(childSObject)) { 146 | return refObect; 147 | } 148 | } 149 | return null; 150 | } 151 | 152 | private List getTopLevelObjects( 153 | List refObjects) { 154 | List topRefObjects = 155 | new ArrayList(); 156 | for (MetadataObjectHolder.MetadataRefObject refObject : refObjects) { 157 | if (refObject.getMasters() == null || refObject.getMasters().size() == 0) { 158 | topRefObjects.add(refObject); 159 | } 160 | } 161 | return topRefObjects; 162 | } 163 | 164 | private String generateJSON(List topRefObjects) { 165 | String json = "[\n"; 166 | 167 | for (MetadataObjectHolder.MetadataRefObject topRefObject : topRefObjects) { 168 | json = json + " {\n"; 169 | json = json + " parent: " + topRefObject.getObjectName() + " ,\n"; 170 | 171 | if (topRefObject.getChildRelationships() != null && topRefObject.getChildRelationships().size() > 0) { 172 | json = json + " childs: [ \n"; 173 | for (MetadataObjectHolder.MetadataRefObject.ChildRelationship cr : topRefObject.getChildRelationships()) { 174 | json = generateJSONChild(json, cr, 1); 175 | } 176 | json = json + " ]"; 177 | } 178 | if (topRefObject.getLookupsMap() != null && topRefObject.getLookupsMap().size() > 0) { 179 | 180 | json = json + ",\n"; 181 | json = json + " lookups: [ \n"; 182 | for (String key : topRefObject.getLookupsMap().keySet()) { 183 | json = generateJSONLookup(json, key, topRefObject.getLookupsMap().get(key)); 184 | } 185 | json = json + " ] \n"; 186 | } 187 | json = json + " },\n"; 188 | } 189 | json = json + "]"; 190 | return json; 191 | } 192 | 193 | private String generateJSONChild(String json, MetadataObjectHolder.MetadataRefObject.ChildRelationship cr, 194 | int sequence) { 195 | 196 | if (sequence >= 8) { 197 | return json; 198 | } 199 | json = json + " {\n"; 200 | json = json + " parentMappedField: " + cr.getField() + ",\n"; 201 | json = json + " childObject: " + cr.getChildSObject() + ",\n"; 202 | json = json + " sequence: " + sequence + ",\n"; 203 | 204 | MetadataObjectHolder.MetadataRefObject childRefObject = getRefObject(cr.getChildSObject()); 205 | // Does this child have another child? 206 | if (childRefObject.getChildRelationships() != null && childRefObject.getChildRelationships().size() > 0) { 207 | json = json + " childs: [ \n"; 208 | for (MetadataObjectHolder.MetadataRefObject.ChildRelationship crChild : childRefObject 209 | .getChildRelationships()) { 210 | json = generateJSONChild(json, crChild, sequence + 1); 211 | } 212 | json = json + " ] \n"; 213 | } 214 | 215 | // Does this child have lookups? 216 | if (childRefObject.getLookupsMap() != null && childRefObject.getLookupsMap().size() > 0) { 217 | 218 | json = json + ",\n"; 219 | json = json + " lookups: [ \n"; 220 | for (String key : childRefObject.getLookupsMap().keySet()) { 221 | json = generateJSONLookup(json, key, childRefObject.getLookupsMap().get(key)); 222 | } 223 | json = json + " ] \n"; 224 | } 225 | json = json + " },\n"; 226 | return json; 227 | } 228 | 229 | private String generateJSONLookup(String json, String field, String sobject) { 230 | json = json + " {\n"; 231 | 232 | json = json + " lookupMappedField : " + field + ",\n"; 233 | json = json + " lookupObject : " + sobject + ",\n"; 234 | json = json + " keys : [External_Id_Field__c], //*** edit this \n"; 235 | 236 | json = json + " },\n"; 237 | 238 | return json; 239 | } 240 | 241 | private MetadataObjectHolder.MetadataRefObject getRefObject(String sObjectName) { 242 | for (MetadataObjectHolder.MetadataRefObject refObject : allRefObjects) { 243 | if (refObject.getObjectName().equalsIgnoreCase(sObjectName)) { 244 | return refObject; 245 | } 246 | } 247 | return null; 248 | } 249 | 250 | } 251 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/service/impl/ValidatorService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.service.impl; 27 | 28 | import java.util.Arrays; 29 | import java.util.ArrayList; 30 | import java.util.HashMap; 31 | import java.util.List; 32 | import java.util.Map; 33 | import migrator.core.connect.SfdcConnection; 34 | import migrator.core.service.MetadataObjectHolder; 35 | import migrator.core.service.SforceObject; 36 | import migrator.core.service.SforceObjectPair; 37 | import migrator.core.utils.Utils; 38 | 39 | /** 40 | * ValidatorService : Counts the number of records in source / target orgs 41 | * 42 | * @author anoop.singh 43 | */ 44 | 45 | public class ValidatorService { 46 | 47 | SfdcConnection sfdcConnection; 48 | List resultCompareList = new ArrayList(); 49 | 50 | // Constructor 51 | public ValidatorService() { 52 | sfdcConnection = new SfdcConnection(); 53 | if (!sfdcConnection.login()) { 54 | System.out.println("Login failed!"); 55 | return; 56 | } 57 | } 58 | 59 | private void validate(String sObjectName, List uniquefieldNames, String where) { 60 | 61 | SforceObject sForceObjSrc = new SforceObject(); 62 | sForceObjSrc.setsObjectName(sObjectName); 63 | sForceObjSrc.setWhere(where); 64 | 65 | 66 | SforceObject sForceObjTgt = new SforceObject(); 67 | sForceObjTgt.setsObjectName(sObjectName); 68 | sForceObjTgt.setWhere(where); 69 | 70 | 71 | MetadataObjectHolder.getInstance().init(SfdcConnection.ORG_TYPE.SOURCE, sfdcConnection, sObjectName); 72 | 73 | Map sourceSforceObjPairMap = new HashMap(); 74 | SfdcApiServiceImpl.getSOQLQueryService().queryValidate(sfdcConnection.getSourceConnection(), sForceObjSrc, 75 | sourceSforceObjPairMap, uniquefieldNames, true); 76 | 77 | Map targetSforceObjPairMap = new HashMap(); 78 | SfdcApiServiceImpl.getSOQLQueryService().queryValidate(sfdcConnection.getTargetConnection(), sForceObjTgt, 79 | targetSforceObjPairMap, uniquefieldNames, false); 80 | 81 | int srcCounter = 0; 82 | List missingSrcRecords = new ArrayList(); 83 | for (Map.Entry entry : sourceSforceObjPairMap.entrySet()) { 84 | String key = entry.getKey(); 85 | if (key.startsWith(Utils.PREFIX_COMPOSITE_KEY)) { 86 | SforceObjectPair pair = entry.getValue(); 87 | 88 | // This is the record in source based on unique key. Does it exists in target Org, 89 | // check it 90 | if (!targetSforceObjPairMap.containsKey(key)) { 91 | missingSrcRecords.add(pair.getSourceId()); 92 | } 93 | } else { 94 | srcCounter++; 95 | } 96 | } 97 | int tgtCounter = 0; 98 | for (Map.Entry entry1 : targetSforceObjPairMap.entrySet()) { 99 | String key = entry1.getKey(); 100 | if (key.startsWith(Utils.PREFIX_COMPOSITE_KEY)) { 101 | SforceObjectPair pair = entry1.getValue(); 102 | } else { 103 | tgtCounter++; 104 | } 105 | } 106 | 107 | // Compare number for records: 108 | System.out.println("Source records for sObjectName: [" + sObjectName + "]: " + srcCounter); 109 | System.out.println("Target records for sObjectName: [" + sObjectName + "]: " + tgtCounter); 110 | 111 | System.out.println("Records missing in Target\n"); 112 | 113 | System.out.println(missingSrcRecords); 114 | 115 | // disconnect from source and target 116 | sfdcConnection.disconnect(); 117 | } 118 | 119 | public void validateCounts(String args) { 120 | String[] objectsArray = args.split(","); 121 | List sObjectNames = Arrays.asList(objectsArray); 122 | 123 | for (String sObjectName : sObjectNames) { 124 | SforceObject sforceObject = new SforceObject(); 125 | sforceObject.setsObjectName(sObjectName); 126 | 127 | MetadataObjectHolder.getInstance().init(SfdcConnection.ORG_TYPE.SOURCE, sfdcConnection, sObjectName); 128 | 129 | Integer sourceCounts = 130 | SfdcApiServiceImpl.getSOQLQueryService().queryValidate(sfdcConnection.getSourceConnection(), 131 | sforceObject); 132 | 133 | Integer targetCounts = 134 | SfdcApiServiceImpl.getSOQLQueryService().queryValidate(sfdcConnection.getTargetConnection(), 135 | sforceObject); 136 | 137 | resultCompareList.add(new ResultCompare(sObjectName, sourceCounts, targetCounts)); 138 | } 139 | 140 | // print counts 141 | System.out.format("\n\n"); 142 | System.out.format("%-50s%-20s%-20s\n", "Object_Name,", "Source_Records,", "Target_Records"); 143 | 144 | for (ResultCompare resultCompare : resultCompareList) { 145 | System.out.format("%-50s%-20s%-20s\n", resultCompare.sObjectName + ",", resultCompare.sourceRecordsCount 146 | + ",", resultCompare.targetRecordsCount); 147 | } 148 | System.out.format("\n\n"); 149 | 150 | // disconnect from source and target 151 | sfdcConnection.disconnect(); 152 | 153 | } 154 | 155 | public static class ResultCompare { 156 | String sObjectName; 157 | Integer sourceRecordsCount; 158 | Integer targetRecordsCount; 159 | 160 | public ResultCompare(String sObjectName, Integer sourceRecordsCount, Integer targetRecordsCount) { 161 | this.sObjectName = sObjectName; 162 | this.sourceRecordsCount = sourceRecordsCount; 163 | this.targetRecordsCount = targetRecordsCount; 164 | } 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/sobject/Migrable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.sobject; 27 | 28 | import com.sforce.soap.partner.sobject.SObject; 29 | import migrator.core.service.SforceObject; 30 | import migrator.core.service.SforceObjectPair; 31 | 32 | /** 33 | * Migrable interface : 34 | * 35 | * @author anoop.singh 36 | */ 37 | public interface Migrable { 38 | 39 | public enum RelationType { 40 | LOOKUP("lookup"), MASTERDETAIL("masterdetail"), HIERARCHICAL("hierarchical"); 41 | 42 | final String v; 43 | 44 | RelationType(String v) { 45 | this.v = v; 46 | } 47 | 48 | public String toString() { 49 | return v; 50 | } 51 | } 52 | 53 | public enum Operation { 54 | CREATE("create"), DELETE("delete"); 55 | 56 | final String v; 57 | 58 | Operation(String v) { 59 | this.v = v; 60 | } 61 | 62 | public String toString() { 63 | return v; 64 | } 65 | } 66 | 67 | public void process(); 68 | 69 | // Source org 70 | public void query(); 71 | 72 | // Target org 73 | public void insert(); 74 | 75 | public void setup(); 76 | 77 | public SObject buildMapping(SforceObject sforceObject, SforceObjectPair sourcePairObj); 78 | 79 | } 80 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/sobject/MigrableHierarchicalObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.sobject; 27 | 28 | import java.util.ArrayList; 29 | import java.util.HashMap; 30 | import java.util.List; 31 | import java.util.Map; 32 | import org.apache.log4j.Logger; 33 | import com.sforce.soap.partner.sobject.SObject; 34 | import migrator.core.service.SforceMasterDetail; 35 | import migrator.core.service.SforceObject; 36 | import migrator.core.service.SforceObjectPair; 37 | import migrator.core.service.impl.SfdcApiServiceImpl; 38 | import migrator.core.utils.Utils; 39 | 40 | /** 41 | * MigrableHierarchicalObject : Class to support hierarchical relationships 42 | * 43 | * @author anoop.singh 44 | */ 45 | public class MigrableHierarchicalObject extends MigrableMasterDetailObject { 46 | 47 | static Logger log = Logger.getLogger(MigrableHierarchicalObject.class.getName()); 48 | 49 | public MigrableHierarchicalObject() { 50 | super(); 51 | } 52 | 53 | public MigrableHierarchicalObject(ObjectMappingConfig objectMapping, String operation) { 54 | super(objectMapping, operation); 55 | } 56 | 57 | // Source environment 58 | @Override 59 | public void query() { 60 | exportLookup(); 61 | exportSource(); 62 | } 63 | 64 | // Target environment 65 | @Override 66 | public void insert() { 67 | createTarget(); 68 | updateTarget(); 69 | } 70 | 71 | // Hook for self-references 72 | public SObject buildMappingUpdate(SforceObject sforceObject, SforceObjectPair sourcePairObj) { 73 | SObject insertRecord = buildMapping(sforceObject, sourcePairObj); 74 | insertRecord.setId(sourcePairObj.getTargetId()); 75 | return insertRecord; 76 | } 77 | 78 | // Using source Org only 79 | @SuppressWarnings("unchecked") 80 | private void exportSource() { 81 | for (SforceObject sforceObject : sForceObjectList) { 82 | if (sforceObject.getMasterDetail() == null && !sforceObject.isLookup()) { 83 | Map sforceObjPairMap = new HashMap(); 84 | sforceObjPairMap = 85 | SfdcApiServiceImpl.getSOQLQueryService().query(sfdcConnection.getSourceConnection(), 86 | sforceObject, sforceObjPairMap, true); 87 | sforceObject.setRecordsMap(sforceObjPairMap); 88 | } 89 | // We have a master-detail relationship: 90 | else if (sforceObject.getMasterDetail() != null) { 91 | SforceMasterDetail masterDetail = sforceObject.getMasterDetail(); 92 | Map sforceObjPairMap = sforceObject.getRecordsMap(); 93 | if (sforceObjPairMap == null) { 94 | sforceObjPairMap = new HashMap(); 95 | } 96 | sforceObjPairMap = 97 | SfdcApiServiceImpl.getSOQLQueryService().queryChildren(sfdcConnection.getSourceConnection(), 98 | sforceObject, sforceObjPairMap, masterDetail, sForceObjectList, true); 99 | } 100 | } 101 | } 102 | 103 | // Inserts records 104 | @Override 105 | public void createTarget() { 106 | 107 | for (SforceObject sforceObject : sForceObjectList) { 108 | String objectName = sforceObject.getsObjectName(); 109 | 110 | boolean reIssueQuery = false; 111 | 112 | if (sforceObject.isLookup()) { 113 | continue; 114 | } 115 | 116 | if (bReIssueLookupQuery(objectName)) { 117 | reIssueQuery = true; 118 | } 119 | 120 | Map sourceRecordsMap = sforceObject.getRecordsMap(); 121 | if (sourceRecordsMap == null) { 122 | return; 123 | } 124 | 125 | List sourceRecords = new ArrayList(); 126 | for (Map.Entry entry : sourceRecordsMap.entrySet()) { 127 | // This map contains composite key also, discard those while 128 | // inserting/updating 129 | String mapKey = entry.getKey(); 130 | if (!mapKey.startsWith(Utils.PREFIX_COMPOSITE_KEY)) { 131 | sourceRecords.add(entry.getValue()); 132 | } 133 | } 134 | 135 | int size = 0; 136 | if (sourceRecords == null || sourceRecords.size() == 0) { 137 | continue; 138 | } else { 139 | size = sourceRecords.size(); 140 | } 141 | 142 | SObject[] insertRecords = new SObject[size]; 143 | 144 | int counter = 0; 145 | 146 | for (SforceObjectPair sObjectPairRecord : sourceRecords) { 147 | SObject insertRecord = buildMapping(sforceObject, sObjectPairRecord); 148 | insertRecords[counter] = insertRecord; 149 | counter++; 150 | } 151 | SfdcApiServiceImpl.getSOQLQueryService().upsertWithExternalId(sfdcConnection.getTargetConnection(), 152 | sforceObject, sforceObject.getExternalIdField(), sourceRecords, insertRecords, true, false); 153 | 154 | // TODO: This might be needed, just depends on JSON mapping 155 | // Solving this issue little differently if this part of 156 | // hierarchical structure. Use refresh flag in JSON 157 | 158 | if (reIssueQuery) { 159 | // super.reIssueLookupQuery(objectName); 160 | super.exportLookup(objectName); 161 | updateTarget(objectName); 162 | } 163 | } 164 | } 165 | 166 | // Update to get the hierarchical relationship right 167 | public void updateTarget() { 168 | 169 | for (SforceObject sforceObject : sForceObjectList) { 170 | if (sforceObject.isLookup() || (sforceObject.isRefresh() == false)) { 171 | continue; 172 | } 173 | 174 | super.exportLookup(); 175 | 176 | Map sourceRecordsMap = sforceObject.getRecordsMap(); 177 | if (sourceRecordsMap == null) { 178 | return; 179 | } 180 | 181 | List sourceRecords = new ArrayList(); 182 | for (Map.Entry entry : sourceRecordsMap.entrySet()) { 183 | // This map contains composite key also, discard those while 184 | // inserting/updating 185 | String mapKey = entry.getKey(); 186 | if (!mapKey.startsWith(Utils.PREFIX_COMPOSITE_KEY)) { 187 | sourceRecords.add(entry.getValue()); 188 | } 189 | } 190 | 191 | int size = 0; 192 | if (sourceRecords == null || sourceRecords.size() == 0) { 193 | continue; 194 | } else { 195 | size = sourceRecords.size(); 196 | } 197 | SObject[] insertRecords = new SObject[size]; 198 | int counter = 0; 199 | for (SforceObjectPair sObjectPairRecord : sourceRecords) { 200 | SObject insertRecord = buildMappingUpdate(sforceObject, sObjectPairRecord); 201 | insertRecords[counter] = insertRecord; 202 | counter++; 203 | } 204 | SfdcApiServiceImpl.getSOQLQueryService().upsertWithExternalId(sfdcConnection.getTargetConnection(), 205 | sforceObject, sforceObject.getExternalIdField(), sourceRecords, insertRecords, true, true); 206 | } 207 | } 208 | 209 | // Update to get the hierarchical relationship right 210 | public void updateTarget(String sObjectName) { 211 | for (SforceObject sforceObject : sForceObjectList) { 212 | String objectName = sforceObject.getsObjectName(); 213 | 214 | if (sforceObject.isLookup() || (sforceObject.isRefresh() == false)) { 215 | continue; 216 | } 217 | if (!sObjectName.equals(objectName)) { 218 | return; 219 | } 220 | super.exportLookup(); 221 | 222 | Map sourceRecordsMap = sforceObject.getRecordsMap(); 223 | if (sourceRecordsMap == null) { 224 | return; 225 | } 226 | 227 | List sourceRecords = new ArrayList(); 228 | for (Map.Entry entry : sourceRecordsMap.entrySet()) { 229 | // This map contains composite key also, discard those while 230 | // inserting/updating 231 | String mapKey = entry.getKey(); 232 | if (!mapKey.startsWith(Utils.PREFIX_COMPOSITE_KEY)) { 233 | sourceRecords.add(entry.getValue()); 234 | } 235 | } 236 | 237 | int size = 0; 238 | if (sourceRecords == null || sourceRecords.size() == 0) { 239 | continue; 240 | } else { 241 | size = sourceRecords.size(); 242 | } 243 | SObject[] insertRecords = new SObject[size]; 244 | 245 | int counter = 0; 246 | for (SforceObjectPair sObjectPairRecord : sourceRecords) { 247 | SObject insertRecord = buildMappingUpdate(sforceObject, sObjectPairRecord); 248 | insertRecords[counter] = insertRecord; 249 | counter++; 250 | } 251 | 252 | SfdcApiServiceImpl.getSOQLQueryService().upsertWithExternalId(sfdcConnection.getTargetConnection(), 253 | sforceObject, sforceObject.getExternalIdField(), sourceRecords, insertRecords, true, true); 254 | } 255 | } 256 | 257 | // Finds the lookup (Note: lookup!) SForceObject from the list 258 | public SforceObject getLookupSforceObj(String lookObjectName) { 259 | for (SforceObject sforceObject : sForceObjectList) { 260 | String objectName = sforceObject.getsObjectName(); 261 | 262 | if (sforceObject.isLookup()) { 263 | if (lookObjectName != null && objectName != null) { 264 | if (lookObjectName.equalsIgnoreCase(objectName)) { 265 | return sforceObject; 266 | } 267 | } 268 | 269 | } 270 | } 271 | return null; 272 | } 273 | 274 | } 275 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/sobject/MigrableObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.sobject; 27 | 28 | import java.util.List; 29 | import java.util.ArrayList; 30 | import java.util.ListIterator; 31 | import java.text.SimpleDateFormat; 32 | import java.util.Date; 33 | import org.apache.log4j.Logger; 34 | import migrator.core.connect.SfdcConnection; 35 | import migrator.core.connect.SfdcConnectionFactory; 36 | import migrator.core.service.PropertiesReader; 37 | import migrator.core.service.SforceObject; 38 | import migrator.core.service.impl.SfdcApiServiceImpl; 39 | 40 | /** 41 | * MigrableObject : Abstract class to support relationships 42 | * 43 | * @author anoop.singh 44 | */ 45 | public abstract class MigrableObject implements Migrable { 46 | protected SfdcConnection sfdcConnection; 47 | 48 | protected ObjectMappingConfig objectMapping = null; 49 | protected String operation; 50 | protected List sForceObjectList = new ArrayList(); 51 | 52 | static { 53 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hhmmss"); 54 | System.setProperty("current.date", dateFormat.format(new Date())); 55 | } 56 | 57 | static Logger log = Logger.getLogger(MigrableObject.class.getName()); 58 | 59 | public MigrableObject() {} 60 | 61 | public MigrableObject(ObjectMappingConfig objectMapping, String operation) { 62 | this.objectMapping = objectMapping; 63 | 64 | this.operation = operation; 65 | } 66 | 67 | @Override 68 | public void process() { 69 | if (!connect()) { 70 | return; 71 | } 72 | setup(); 73 | if (handleDelete()) { 74 | return; 75 | } 76 | query(); 77 | insert(); 78 | disconnect(); 79 | } 80 | 81 | /** 82 | * Setup the migrable objects: 1. Gets the Describe details for each SObject 2. Creates a 83 | * SforceObject (holder of sobjectName, describe details and records) 3. Add SforceObject into a 84 | * map 85 | * 86 | */ 87 | @Override 88 | public void setup() {} 89 | 90 | public SforceObject getSforceObject(String sObjectName) { 91 | for (SforceObject sforceObj : sForceObjectList) { 92 | if (sObjectName.equalsIgnoreCase(sforceObj.getsObjectName())) { 93 | return sforceObj; 94 | } 95 | } 96 | return null; 97 | } 98 | 99 | public boolean handleDelete() { 100 | if (operation.equals(Migrable.Operation.DELETE.toString())) { 101 | for (int counter = 0; counter < 2; counter++) { 102 | for (ListIterator iterator = sForceObjectList.listIterator(sForceObjectList.size()); iterator 103 | .hasPrevious();) { 104 | SforceObject sforceObject = iterator.previous(); 105 | if (!sforceObject.isLookup()) { 106 | SfdcApiServiceImpl.getSOQLQueryService().delete(sforceObject.getsObjectName(), sfdcConnection); 107 | } 108 | } 109 | } 110 | return true; 111 | } 112 | return false; 113 | } 114 | 115 | public boolean connect() { 116 | PropertiesReader.getInstance(); 117 | 118 | this.sfdcConnection = SfdcConnectionFactory.getConnection(); 119 | if (!sfdcConnection.login()) { 120 | System.out.println("Login failed!"); 121 | return false; 122 | } 123 | return true; 124 | } 125 | 126 | public void disconnect() { 127 | // disconnect from source and target 128 | sfdcConnection.disconnect(); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/sobject/MigrableObjectFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.sobject; 27 | 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | import org.apache.log4j.Logger; 31 | import migrator.core.service.PropertiesReader; 32 | import migrator.core.sobject.MigrableObject; 33 | import migrator.core.utils.CommandVO; 34 | import migrator.core.utils.ForceFileUtils; 35 | 36 | /** 37 | * MigrableObjectFactory 38 | * 39 | * @author anoop.singh 40 | */ 41 | public class MigrableObjectFactory { 42 | 43 | static Logger log = Logger.getLogger(MigrableObjectFactory.class.getName()); 44 | 45 | public static MigrableObject migrate(CommandVO comamndArgs, boolean jsonfilePath) { 46 | MigrableObject migrable = getMigrableObject(comamndArgs, jsonfilePath); 47 | migrable.process(); 48 | return migrable; 49 | } 50 | 51 | public static MigrableObject migrate(CommandVO comamndArgs) { 52 | MigrableObject migrable = getMigrableObject(comamndArgs, true); 53 | migrable.process(); 54 | return migrable; 55 | } 56 | 57 | public static List migrate(List comamndArgs) { 58 | List mirableObjects = new ArrayList(); 59 | for (CommandVO vo : comamndArgs) { 60 | MigrableObject migrable = getMigrableObject(vo, true); 61 | mirableObjects.add(migrable); 62 | } 63 | // Cleanup 64 | for (CommandVO vo : comamndArgs) { 65 | vo = null; 66 | } 67 | for (MigrableObject migrable : mirableObjects) { 68 | migrable.process(); 69 | // Cleanup 70 | migrable = null; 71 | } 72 | return mirableObjects; 73 | } 74 | 75 | private static MigrableObject getMigrableObject(CommandVO comamndArgs, boolean jsonfilePath) { 76 | MigrableObject migrable = null; 77 | 78 | String mappingFile = comamndArgs.getMapping(); 79 | if (jsonfilePath) { 80 | String mappingPath = "/object-mappings/"; 81 | if (PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, "object.mapping.dir") != null) { 82 | mappingPath = 83 | PropertiesReader.getInstance().getProperty(PropertiesReader.PROPERTY_TYPE.BUILD, 84 | "object.mapping.dir"); 85 | } 86 | mappingFile = new ForceFileUtils().getFileAsString(mappingPath + comamndArgs.getMapping()); 87 | } 88 | log.debug("mappingFile=\n" + mappingFile); 89 | 90 | ObjectMappingConfig objectMapping = ObjectMappingConfig.getMapping(mappingFile); 91 | log.debug("objectMapping.getRelationType()=" + objectMapping.getRelationType()); 92 | 93 | if (objectMapping.getRelationType() == Migrable.RelationType.LOOKUP) { 94 | migrable = new MigrableLookupObject(objectMapping, comamndArgs.getOperation()); 95 | } else if (objectMapping.getRelationType() == Migrable.RelationType.MASTERDETAIL) { 96 | migrable = new MigrableMasterDetailObject(objectMapping, comamndArgs.getOperation()); 97 | } else if (objectMapping.getRelationType() == Migrable.RelationType.HIERARCHICAL) { 98 | migrable = new MigrableHierarchicalObject(objectMapping, comamndArgs.getOperation()); 99 | } 100 | return migrable; 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/utils/ComamndArgs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.utils; 27 | 28 | import java.lang.reflect.Field; 29 | import java.util.ArrayList; 30 | import java.util.HashMap; 31 | import java.util.List; 32 | import java.util.TreeSet; 33 | 34 | /** 35 | * ComamndArgs 36 | * 37 | * @author anoop.singh 38 | */ 39 | public class ComamndArgs { 40 | 41 | private String[] args = null; 42 | 43 | private HashMap switchIndexes = new HashMap(); 44 | private TreeSet takenIndexes = new TreeSet(); 45 | 46 | private List targets = new ArrayList(); 47 | 48 | public CommandVO getCommandVO() { 49 | CommandVO vo = new CommandVO(); 50 | vo.setOperation(getOperation()); 51 | vo.setMapping(getMapping()); 52 | 53 | return vo; 54 | } 55 | 56 | /** 57 | * @return the operation 58 | */ 59 | public String getOperation() { 60 | return switchValue("-operation"); 61 | } 62 | 63 | /** 64 | * @return the mapping 65 | */ 66 | public String getMapping() { 67 | return switchValue("-mapping"); 68 | } 69 | 70 | /** 71 | * @return the type 72 | */ 73 | public String getRelationType() { 74 | return switchValue("-relationType"); 75 | } 76 | 77 | public String toString() { 78 | return usage() + "\n\n" + "ComamndArgs[operation:" + switchValue("-operation") + " mapping:" 79 | + switchValue("-mapping") + " relationType:" + switchValue("-relationType") + "]"; 80 | } 81 | 82 | public String usage() { 83 | return "-operation create|delete -mapping -relationType lookup|masterdetail|hierarchical"; 84 | } 85 | 86 | public ComamndArgs(String[] args) { 87 | 88 | parse(args); 89 | } 90 | 91 | public void parse(String[] arguments) { 92 | this.args = arguments; 93 | // locate switches. 94 | switchIndexes.clear(); 95 | takenIndexes.clear(); 96 | for (int i = 0; i < args.length; i++) { 97 | if (args[i].startsWith("-")) { 98 | switchIndexes.put(args[i], i); 99 | takenIndexes.add(i); 100 | } 101 | } 102 | } 103 | 104 | public String[] args() { 105 | return args; 106 | } 107 | 108 | public String arg(int index) { 109 | return args[index]; 110 | } 111 | 112 | public boolean switchPresent(String switchName) { 113 | return switchIndexes.containsKey(switchName); 114 | } 115 | 116 | public String switchValue(String switchName) { 117 | return switchValue(switchName, null); 118 | } 119 | 120 | public String switchValue(String switchName, String defaultValue) { 121 | if (!switchIndexes.containsKey(switchName)) 122 | return defaultValue; 123 | 124 | int switchIndex = switchIndexes.get(switchName); 125 | if (switchIndex + 1 < args.length) { 126 | takenIndexes.add(switchIndex + 1); 127 | return args[switchIndex + 1]; 128 | } 129 | return defaultValue; 130 | } 131 | 132 | public Long switchLongValue(String switchName) { 133 | return switchLongValue(switchName, null); 134 | } 135 | 136 | public Long switchLongValue(String switchName, Long defaultValue) { 137 | String switchValue = switchValue(switchName, null); 138 | 139 | if (switchValue == null) 140 | return defaultValue; 141 | return Long.parseLong(switchValue); 142 | } 143 | 144 | public Double switchDoubleValue(String switchName) { 145 | return switchDoubleValue(switchName, null); 146 | } 147 | 148 | public Double switchDoubleValue(String switchName, Double defaultValue) { 149 | String switchValue = switchValue(switchName, null); 150 | 151 | if (switchValue == null) 152 | return defaultValue; 153 | return Double.parseDouble(switchValue); 154 | } 155 | 156 | 157 | public String[] switchValues(String switchName) { 158 | if (!switchIndexes.containsKey(switchName)) 159 | return new String[0]; 160 | 161 | int switchIndex = switchIndexes.get(switchName); 162 | 163 | int nextArgIndex = switchIndex + 1; 164 | while (nextArgIndex < args.length && !args[nextArgIndex].startsWith("-")) { 165 | takenIndexes.add(nextArgIndex); 166 | nextArgIndex++; 167 | } 168 | 169 | String[] values = new String[nextArgIndex - switchIndex - 1]; 170 | for (int j = 0; j < values.length; j++) { 171 | values[j] = args[switchIndex + j + 1]; 172 | } 173 | return values; 174 | } 175 | 176 | public T switchPojo(Class pojoClass) { 177 | try { 178 | T pojo = pojoClass.newInstance(); 179 | 180 | Field[] fields = pojoClass.getFields(); 181 | for (Field field : fields) { 182 | Class fieldType = field.getType(); 183 | String fieldName = "-" + field.getName().replace('_', '-'); 184 | 185 | if (fieldType.equals(Boolean.class) || fieldType.equals(boolean.class)) { 186 | field.set(pojo, switchPresent(fieldName)); 187 | } else if (fieldType.equals(String.class)) { 188 | if (switchValue(fieldName) != null) { 189 | field.set(pojo, switchValue(fieldName)); 190 | } 191 | } else if (fieldType.equals(Long.class) || fieldType.equals(long.class)) { 192 | if (switchLongValue(fieldName) != null) { 193 | field.set(pojo, switchLongValue(fieldName)); 194 | } 195 | } else if (fieldType.equals(Integer.class) || fieldType.equals(int.class)) { 196 | if (switchLongValue(fieldName) != null) { 197 | field.set(pojo, switchLongValue(fieldName).intValue()); 198 | } 199 | } else if (fieldType.equals(Short.class) || fieldType.equals(short.class)) { 200 | if (switchLongValue(fieldName) != null) { 201 | field.set(pojo, switchLongValue(fieldName).shortValue()); 202 | } 203 | } else if (fieldType.equals(Byte.class) || fieldType.equals(byte.class)) { 204 | if (switchLongValue(fieldName) != null) { 205 | field.set(pojo, switchLongValue(fieldName).byteValue()); 206 | } 207 | } else if (fieldType.equals(Double.class) || fieldType.equals(double.class)) { 208 | if (switchDoubleValue(fieldName) != null) { 209 | field.set(pojo, switchDoubleValue(fieldName)); 210 | } 211 | } else if (fieldType.equals(Float.class) || fieldType.equals(float.class)) { 212 | if (switchDoubleValue(fieldName) != null) { 213 | field.set(pojo, switchDoubleValue(fieldName).floatValue()); 214 | } 215 | } else if (fieldType.equals(String[].class)) { 216 | String[] values = switchValues(fieldName); 217 | if (values.length != 0) { 218 | field.set(pojo, values); 219 | } 220 | } 221 | } 222 | 223 | return pojo; 224 | } catch (Exception e) { 225 | throw new RuntimeException("Error creating switch POJO", e); 226 | } 227 | } 228 | 229 | public String[] targets() { 230 | String[] targetArray = new String[args.length - takenIndexes.size()]; 231 | int targetIndex = 0; 232 | for (int i = 0; i < args.length; i++) { 233 | if (!takenIndexes.contains(i)) { 234 | targetArray[targetIndex++] = args[i]; 235 | } 236 | } 237 | 238 | return targetArray; 239 | } 240 | 241 | } 242 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/utils/CommandVO.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.utils; 27 | 28 | /** 29 | * CommandVO 30 | * 31 | * @author anoop.singh 32 | */ 33 | public class CommandVO { 34 | 35 | private String operation; 36 | private String mapping; 37 | 38 | public CommandVO() {} 39 | 40 | public CommandVO(String operation, String mapping) { 41 | this.operation = operation; 42 | this.mapping = mapping; 43 | } 44 | 45 | /** 46 | * @return the operation 47 | */ 48 | public String getOperation() { 49 | return operation; 50 | } 51 | 52 | /** 53 | * @param operation the operation to set 54 | */ 55 | public void setOperation(String operation) { 56 | this.operation = operation; 57 | } 58 | 59 | /** 60 | * @return the mapping 61 | */ 62 | public String getMapping() { 63 | return mapping; 64 | } 65 | 66 | /** 67 | * @param mapping the mapping to set 68 | */ 69 | public void setMapping(String mapping) { 70 | this.mapping = mapping; 71 | } 72 | 73 | public String toString() { 74 | return "CommandVO[operation:" + operation + ", mapping:" + mapping + "]"; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/utils/ForceFileUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.utils; 27 | 28 | import java.io.BufferedReader; 29 | import java.io.BufferedWriter; 30 | import java.io.File; 31 | import java.io.FileNotFoundException; 32 | import java.io.FileReader; 33 | import java.io.FileWriter; 34 | import java.io.IOException; 35 | import java.io.InputStreamReader; 36 | import java.util.ArrayList; 37 | import java.util.List; 38 | import org.apache.commons.io.FileUtils; 39 | import org.apache.log4j.Logger; 40 | 41 | public class ForceFileUtils { 42 | 43 | static Logger log = Logger.getLogger(ForceFileUtils.class.getName()); 44 | private static final String FILE_PREFIX = "file:"; 45 | 46 | public String getFileAsString(String fileName) { 47 | String data = null; 48 | try { 49 | data = FileUtils.readFileToString(FileUtils.toFile(ForceFileUtils.class.getResource(fileName)), "UTF-8"); 50 | } catch (FileNotFoundException e) { 51 | log.error("Exception, couldn't find " + fileName, e); 52 | } catch (IOException e) { 53 | log.error("Exception, couldn't find " + fileName, e); 54 | } finally { 55 | } 56 | return data; 57 | } 58 | 59 | public String readFile(String fileName) { 60 | StringBuffer data = new StringBuffer(); 61 | BufferedReader reader = null; 62 | 63 | try { 64 | fileName = getAbsoluteFileName(fileName); 65 | 66 | // Are we looking in the jar? 67 | if (fileName.startsWith(FILE_PREFIX)) { 68 | 69 | String[] parts = fileName.split("!"); 70 | 71 | if (parts.length == 2) { 72 | reader = 73 | new BufferedReader( 74 | new InputStreamReader(ForceFileUtils.class.getResourceAsStream(parts[1]))); 75 | } 76 | // No? So we're looking in the file system 77 | } else { 78 | try { 79 | reader = new BufferedReader(new FileReader(fileName)); 80 | } catch (FileNotFoundException e) { 81 | log.error("Couldn't find " + fileName, e); 82 | } 83 | } 84 | String line; 85 | while ((line = reader.readLine()) != null) { 86 | data.append(line); 87 | } 88 | } catch (Exception e) { 89 | e.printStackTrace(); 90 | } finally { 91 | try { 92 | reader.close(); 93 | } catch (Exception e) { 94 | } 95 | } 96 | return data.toString(); 97 | } 98 | 99 | public String writeToFile(String fileName, String data, boolean append) { 100 | // fileName = getAbsoluteFileName(fileName); 101 | BufferedWriter wr = null; 102 | try { 103 | // Open the file for writing, without removing its current content. 104 | wr = new BufferedWriter(new FileWriter(new File(fileName).getCanonicalFile(), append)); 105 | 106 | // Write a sample string to the end of the file. 107 | wr.write(data); 108 | } catch (IOException ex) { 109 | System.err.println("An IOException was caught!"); 110 | ex.printStackTrace(); 111 | } finally { 112 | // Close the file. 113 | try { 114 | wr.close(); 115 | } catch (IOException ex) { 116 | System.err.println("An IOException was caught!"); 117 | ex.printStackTrace(); 118 | } 119 | } 120 | return data; 121 | } 122 | 123 | public static void closeFile(BufferedReader br) { 124 | if (br != null) { 125 | try { 126 | br.close(); 127 | } catch (IOException e) { 128 | log.error("BufferedReader exception", e); 129 | } 130 | } 131 | } 132 | 133 | public List getFileNamesInDirectory(String inputDirectory, boolean includeDirectories) { 134 | List fileNames = new ArrayList(); 135 | 136 | inputDirectory = getAbsoluteFileName(inputDirectory); 137 | 138 | 139 | File dir = new File(inputDirectory); 140 | 141 | if (dir != null && dir.isDirectory()) { 142 | for (File file : dir.listFiles()) { 143 | if (includeDirectories || (!includeDirectories && file.isFile())) { 144 | fileNames.add(file.getAbsolutePath()); 145 | } 146 | } 147 | } else { 148 | log.warn("\"" + inputDirectory + "\" does not exist in directory."); 149 | } 150 | 151 | return fileNames; 152 | } 153 | 154 | public String getAbsoluteFileName(String inputFileName) { 155 | 156 | if (inputFileName.startsWith("/")) { 157 | return inputFileName; 158 | } 159 | 160 | if (ClassLoader.getSystemResource(inputFileName) != null) { 161 | inputFileName = ClassLoader.getSystemResource(inputFileName).getFile(); 162 | inputFileName = inputFileName.replaceAll("%20", "\\ "); 163 | } 164 | 165 | return inputFileName; 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/java/migrator/core/utils/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted 5 | * provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | * and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials provided with 12 | * the distribution. 13 | * 14 | * 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or 15 | * promote products derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 24 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | package migrator.core.utils; 27 | 28 | import java.util.Arrays; 29 | import java.util.HashSet; 30 | import java.util.List; 31 | import java.util.Set; 32 | import com.sforce.soap.partner.PartnerConnection; 33 | import com.sforce.soap.partner.sobject.SObject; 34 | import migrator.core.service.SforceObjectPair; 35 | 36 | /** 37 | * Utils 38 | * 39 | * @author anoop.singh 40 | */ 41 | public class Utils { 42 | 43 | public static String PREFIX_COMPOSITE_KEY = "KEY_"; 44 | 45 | private static String[] blackListedEndPoints = new String[] {"https://login.salesforce.com".toLowerCase()}; 46 | 47 | // We never want to create/update/delete anything in source 48 | public static Set BLACK_LISTED_TARGET_ENDPOINTS = new HashSet(Arrays.asList(blackListedEndPoints)); 49 | 50 | private static String[] exclude = new String[] {"Id", "OwnerId", "IsDeleted", "CurrencyIsoCode", "CreatedDate", 51 | "CreatedById", "LastModifiedDate", "LastModifiedById", "SystemModstamp", "MayEdit", "IsLocked", 52 | "LastViewedDate", "LastReferencedDate", "ConnectionReceivedId", "ConnectionSentId"}; 53 | public static Set EXCLUDE_FIELDS = new HashSet(Arrays.asList(exclude)); 54 | 55 | private static String[] excludeQuery = new String[] {"IsDeleted", "CreatedDate", "CreatedById", "LastModifiedDate", 56 | "LastModifiedById", "SystemModstamp", "MayEdit", "IsLocked", "LastViewedDate", "LastReferencedDate", 57 | "ConnectionReceivedId", "ConnectionSentId"}; 58 | public static Set EXCLUDE_QUERY_FIELDS = new HashSet(Arrays.asList(excludeQuery)); 59 | 60 | private static String[] excludeChildRelationships = new String[] {"ActivityHistories", "Tags", 61 | "AttachedContentDocuments", "AttachedContentNotes", "Attachments", "RecordAssociatedGroups", 62 | "CombinedAttachments", "ContentDocumentLinks", "DuplicateRecordItems", "FeedSubscriptionsForEntity", 63 | "Events", "GoogleDocs", "ParentEntities", "Notes", "NotesAndAttachments", "OpenActivities", 64 | "ProcessInstances", "ProcessSteps", "Tasks", "TopicAssignments", "Histories"}; 65 | public static Set EXCLUDE_CHILD_RELATIONSHIPS = new HashSet( 66 | Arrays.asList(excludeChildRelationships)); 67 | 68 | public static SforceObjectPair getSObjectParent(String parentId, List sObjectRecords) { 69 | 70 | for (SforceObjectPair source : sObjectRecords) { 71 | if (source.getSourceId().equalsIgnoreCase(parentId)) { 72 | return source; 73 | } 74 | } 75 | return null; 76 | } 77 | 78 | @SuppressWarnings({"unchecked", "rawtypes"}) 79 | public static String getKey(String sObjectAPIName, SObject sObject, List compositeKey) { 80 | 81 | StringBuffer sbKey = new StringBuffer(""); 82 | 83 | try { 84 | for (String key : compositeKey) { 85 | Object fieldValue = sObject.getField(key); 86 | sbKey.append(fieldValue); 87 | } 88 | } catch (Exception e) { 89 | System.out.println("Utils.getKey failed: sObjectAPIName" + sObjectAPIName); 90 | e.printStackTrace(); 91 | } 92 | // System.out.println("Composite Key:****" + sbKey.toString()); 93 | return PREFIX_COMPOSITE_KEY + sbKey.toString(); 94 | } 95 | 96 | public static void updateBlackListedUrls(String url) { 97 | BLACK_LISTED_TARGET_ENDPOINTS.add(url.toLowerCase()); 98 | } 99 | 100 | public static boolean isBlackListedTarget(PartnerConnection connection) { 101 | return isBlackListedTarget(connection.getConfig().getServiceEndpoint()); 102 | } 103 | 104 | public static boolean isBlackListedTarget(String url) { 105 | if (url != null && url.toLowerCase().contains(".com")) { 106 | url = url.toLowerCase().substring(0, url.toLowerCase().indexOf(".com")); 107 | if (BLACK_LISTED_TARGET_ENDPOINTS.toString().toLowerCase().contains(url.toLowerCase())) { 108 | return true; 109 | } 110 | } 111 | 112 | return false; 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /datamigrator-core/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Root logger option 2 | log4j.rootLogger=DEBUG, stdout, debugfile, errorfile 3 | 4 | log4j.logger.stdout=DEBUG, stdout 5 | 6 | log4j.logger.errorfile=ERROR, errorfile 7 | 8 | log4j.additivity.debugfile=false 9 | log4j.additivity.errorfile=false 10 | 11 | # Redirect log messages to console 12 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 13 | log4j.appender.stdout.Target=System.out 14 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 15 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n 16 | 17 | # Redirect log messages to a log file, support file rolling. 18 | log4j.appender.debugfile=org.apache.log4j.RollingFileAppender 19 | log4j.appender.debugfile.File=./migrator_logs_${current.date}.log 20 | log4j.appender.debugfile.MaxFileSize=10MB 21 | log4j.appender.debugfile.MaxBackupIndex=20 22 | log4j.appender.debugfile.layout=org.apache.log4j.PatternLayout 23 | log4j.appender.debugfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n 24 | log4j.appender.debugfile.threshold=DEBUG 25 | log4j.appender.debugfile.append=false 26 | 27 | 28 | # Redirect log messages to a log file, support file rolling. 29 | log4j.appender.errorfile=org.apache.log4j.RollingFileAppender 30 | log4j.appender.errorfile.File=../migrator_error_logs_${current.date}.log 31 | log4j.appender.errorfile.MaxFileSize=10MB 32 | log4j.appender.errorfile.MaxBackupIndex=20 33 | log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout 34 | log4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n 35 | log4j.appender.errorfile.threshold=ERROR 36 | log4j.appender.errorfile.append=false 37 | 38 | 39 | log4j.appender.LOGFILE.RollingPolicy=org.apache.log4j.rolling.TimeBasedRollingPolicy 40 | log4j.appender.LOGFILE.RollingPolicy.FileNamePattern=migrator_logs_%d{yyyy-MM-dd}.log 41 | 42 | 43 | -------------------------------------------------------------------------------- /datamigrator-module/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /datamigrator-module/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 4.0.0 7 | 8 | datamigrator.main 9 | datamigrator 10 | 0.0.1-SNAPSHOT 11 | 12 | 13 | datamigrator-module 14 | jar 15 | datamigrator Module 16 | 17 | 18 | 19 | datamigrator.main 20 | datamigrator-core 21 | ${project.version} 22 | 23 | 24 | 25 | 26 | src/main/java 27 | src/test/java 28 | 29 | 30 | src/main/resources 31 | true 32 | 33 | 34 | 35 | 36 | src/test/resources 37 | 38 | 39 | 40 | 41 | 42 | org.apache.maven.plugins 43 | maven-compiler-plugin 44 | 45 | 1.8 46 | 1.8 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/DeleteAccounts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | import migrator.core.sobject.MigrableObjectFactory; 37 | import migrator.core.utils.CommandVO; 38 | 39 | /** 40 | * Main class to delete accounts/assets and opportunities from target org 41 | * 42 | * @author anoop.singh 43 | */ 44 | public class DeleteAccounts { 45 | 46 | public void process() { 47 | 48 | List list = new ArrayList(); 49 | 50 | list.add(new CommandVO("delete", "AccountwithAssetsAndOppties.json")); 51 | 52 | MigrableObjectFactory.migrate(list); 53 | } 54 | 55 | static public void main(String[] args) { 56 | DeleteAccounts migrate = new DeleteAccounts(); 57 | migrate.process(); 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/DeleteAll.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | import migrator.core.sobject.MigrableObjectFactory; 37 | import migrator.core.utils.CommandVO; 38 | 39 | /** 40 | * Main class to kick-off deletion of data from target org 41 | * 42 | * @author anoop.singh 43 | */ 44 | public class DeleteAll { 45 | 46 | public void process() { 47 | 48 | List list = new ArrayList(); 49 | 50 | list.add(new CommandVO("delete", "AccountwithAssetsAndOppties.json")); 51 | list.add(new CommandVO("delete", "PricebookEntry_nonstandard.json")); 52 | list.add(new CommandVO("delete", "PricebookEntry_standard.json")); 53 | list.add(new CommandVO("delete", "Products.json")); 54 | 55 | MigrableObjectFactory.migrate(list); 56 | } 57 | 58 | static public void main(String[] args) { 59 | DeleteAll migrate = new DeleteAll(); 60 | migrate.process(); 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/DeleteProducts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | import migrator.core.sobject.MigrableObjectFactory; 37 | import migrator.core.utils.CommandVO; 38 | 39 | /** 40 | * Main class to kick-off deletion of products and pricebooks data from target org 41 | * 42 | * @author anoop.singh 43 | */ 44 | public class DeleteProducts { 45 | 46 | public void process() { 47 | 48 | List list = new ArrayList(); 49 | 50 | list.add(new CommandVO("delete", "PricebookEntry_nonstandard.json")); 51 | list.add(new CommandVO("delete", "PricebookEntry_standard.json")); 52 | list.add(new CommandVO("delete", "Products.json")); 53 | 54 | MigrableObjectFactory.migrate(list); 55 | } 56 | 57 | static public void main(String[] args) { 58 | DeleteProducts migrate = new DeleteProducts(); 59 | migrate.process(); 60 | } 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/GenerateMappingExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import migrator.core.service.impl.MappingGeneratorService; 34 | 35 | /** 36 | * GenerateMappingExample : 37 | * 38 | * @author anoop.singh 39 | */ 40 | public class GenerateMappingExample { 41 | 42 | /** 43 | * @args: List of comma separated object api names 44 | * -Dexec.args="object1,object2 45 | */ 46 | public static void main(String[] args) { 47 | MappingGeneratorService generator = new MappingGeneratorService(); 48 | generator.generate(args[0]); 49 | } 50 | 51 | } 52 | 53 | 54 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/MetadataCompareExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import migrator.core.service.impl.MetadataCompareService; 34 | 35 | /** 36 | * MetadataCompareService : Spit out different fields 37 | * 38 | * @author anoop.singh 39 | */ 40 | 41 | public class MetadataCompareExample { 42 | 43 | /** 44 | * @args: List of comma separated object api names 45 | * -Dexec.args="Product2,Pricebook2" 46 | */ 47 | static public void main(String[] args) { 48 | MetadataCompareExample connector = new MetadataCompareExample(); 49 | System.out.println("objects::: " + args[0]); 50 | connector.process(args[0]); 51 | } 52 | 53 | // Constructor 54 | public MetadataCompareExample() { 55 | } 56 | 57 | public void process(String objects) { 58 | MetadataCompareService compare = new MetadataCompareService(); 59 | compare.compare(objects); 60 | 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/MigrateAccounts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | import migrator.core.sobject.MigrableObjectFactory; 37 | import migrator.core.utils.CommandVO; 38 | 39 | /** 40 | * Main class to kick-off migrations of accounts/assets and opportunities 41 | * 42 | * @author anoop.singh 43 | */ 44 | public class MigrateAccounts { 45 | 46 | public void process() { 47 | 48 | List list = new ArrayList(); 49 | 50 | list.add(new CommandVO("create", "AccountwithAssetsAndOppties.json")); 51 | 52 | MigrableObjectFactory.migrate(list); 53 | } 54 | 55 | static public void main(String[] args) { 56 | MigrateAccounts migrate = new MigrateAccounts(); 57 | migrate.process(); 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/MigrateAccountsHierarchical.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | import migrator.core.sobject.MigrableObjectFactory; 37 | import migrator.core.utils.CommandVO; 38 | 39 | /** 40 | * Main class to kick-off migrations of accounts/assets and opportunities using external ids 41 | * Make sure to set "ExternalIdField" field in json mapping file. 42 | * 43 | * @author anoop.singh 44 | */ 45 | public class MigrateAccountsHierarchical { 46 | 47 | public void process() { 48 | 49 | List list = new ArrayList(); 50 | 51 | list.add(new CommandVO("create", "AccountwithAssetsAndOppties_hierarchical.json")); 52 | 53 | MigrableObjectFactory.migrate(list); 54 | } 55 | 56 | static public void main(String[] args) { 57 | MigrateAccountsHierarchical migrate = new MigrateAccountsHierarchical(); 58 | migrate.process(); 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/MigrateAll.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | import migrator.core.sobject.MigrableObjectFactory; 37 | import migrator.core.utils.CommandVO; 38 | 39 | /** 40 | * Main class to kick-off migrations 41 | * 42 | * @author anoop.singh 43 | */ 44 | public class MigrateAll { 45 | 46 | public void process() { 47 | 48 | List list = new ArrayList(); 49 | 50 | list.add(new CommandVO("create", "Products.json")); 51 | list.add(new CommandVO("create", "PricebookEntry_standard.json")); 52 | list.add(new CommandVO("create", "PricebookEntry_nonstandard.json")); 53 | list.add(new CommandVO("create", "AccountwithAssetsAndOppties.json")); 54 | 55 | MigrableObjectFactory.migrate(list); 56 | } 57 | 58 | static public void main(String[] args) { 59 | MigrateAll migrate = new MigrateAll(); 60 | migrate.process(); 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/MigrateOnlyProducts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | import migrator.core.sobject.MigrableObjectFactory; 37 | import migrator.core.utils.CommandVO; 38 | 39 | /** 40 | * Main class to kick-off migration of products 41 | * 42 | * @author anoop.singh 43 | */ 44 | public class MigrateOnlyProducts { 45 | 46 | public void process() { 47 | 48 | List list = new ArrayList(); 49 | 50 | list.add(new CommandVO("create", "Products.json")); 51 | 52 | MigrableObjectFactory.migrate(list); 53 | } 54 | 55 | static public void main(String[] args) { 56 | MigrateOnlyProducts migrate = new MigrateOnlyProducts(); 57 | migrate.process(); 58 | } 59 | } 60 | 61 | 62 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/MigrateProducts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | import migrator.core.sobject.MigrableObjectFactory; 37 | import migrator.core.utils.CommandVO; 38 | 39 | /** 40 | * Main class to kick-off migration of products, pricebooks and pricebookEntries data 41 | * 42 | * @author anoop.singh 43 | */ 44 | public class MigrateProducts { 45 | 46 | public void process() { 47 | 48 | List list = new ArrayList(); 49 | 50 | list.add(new CommandVO("create", "Products.json")); 51 | list.add(new CommandVO("create", "PricebookEntry_standard.json")); 52 | list.add(new CommandVO("create", "PricebookEntry_nonstandard.json")); 53 | 54 | MigrableObjectFactory.migrate(list); 55 | } 56 | 57 | static public void main(String[] args) { 58 | MigrateProducts migrate = new MigrateProducts(); 59 | migrate.process(); 60 | } 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/MigrateProductsDelete.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | import migrator.core.sobject.MigrableObjectFactory; 37 | import migrator.core.utils.CommandVO; 38 | 39 | /** 40 | * Main class to delete products, pricebooks and pricebookEntries data 41 | * 42 | * @author anoop.singh 43 | */ 44 | public class MigrateProductsDelete { 45 | 46 | public void process() { 47 | 48 | List list = new ArrayList(); 49 | 50 | list.add(new CommandVO("delete", "PricebookEntry_nonstandard.json")); 51 | list.add(new CommandVO("delete", "Products.json")); 52 | 53 | MigrableObjectFactory.migrate(list); 54 | } 55 | 56 | static public void main(String[] args) { 57 | MigrateProductsDelete migrate = new MigrateProductsDelete(); 58 | migrate.process(); 59 | } 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/MigrateProductsWithExternalId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | import migrator.core.sobject.MigrableObjectFactory; 37 | import migrator.core.utils.CommandVO; 38 | 39 | /** 40 | * Main class to kick-off migration of products, pricebooks and pricebookEntries data using 41 | * external id 42 | * 43 | * @author anoop.singh 44 | */ 45 | public class MigrateProductsWithExternalId { 46 | 47 | public void process() { 48 | 49 | List list = new ArrayList(); 50 | 51 | list.add(new CommandVO("create", "Products_extId.json")); 52 | list.add(new CommandVO("create", "PricebookEntry_standard_extId.json")); 53 | list.add(new CommandVO("create", "PricebookEntry_nonstandard_extId.json")); 54 | 55 | MigrableObjectFactory.migrate(list); 56 | } 57 | 58 | static public void main(String[] args) { 59 | MigrateProductsWithExternalId migrate = new MigrateProductsWithExternalId(); 60 | migrate.process(); 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/SfdcSerializeExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import migrator.core.service.impl.SfdcSerializerService; 34 | 35 | /** 36 | * Main class to serialize the data into JSON. 37 | * 1. Make sure to set the source.type=org to download data in .json 38 | * 2. Make sure to set the source.type=json to migrate from .json to target org 39 | * 40 | * @author anoop.singh 41 | */ 42 | public class SfdcSerializeExample { 43 | 44 | static public void main(String[] args) { 45 | new SfdcSerializerService("Products.json").serialize(); 46 | } 47 | } 48 | 49 | 50 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/java/migrator/module/client/ValidateExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Salesforce.com, Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Salesforce.com nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | package migrator.module.client; 32 | 33 | import migrator.core.service.impl.ValidatorService; 34 | 35 | /** 36 | * ValidatorExample : Count the number of records in source and target orgs 37 | * 38 | * @author anoop.singh 39 | */ 40 | 41 | public class ValidateExample { 42 | 43 | /** 44 | * @args: List of comma separated object api names 45 | * -Dexec.args="object1,object2 46 | */ 47 | public static void main(String[] args) { 48 | ValidatorService validator = new ValidatorService(); 49 | validator.validateCounts(args[0]); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/resources/build.properties: -------------------------------------------------------------------------------- 1 | # SOURCE 2 | source.sfdc.login=username@salesforce.com.sourceorg 3 | source.sfdc.password=****** 4 | source.env.endpoint=https://test.salesforce.com/services/Soap/u/44.0/ 5 | 6 | # TARGET 7 | target.sfdc.login=username@salesforce.com.targetorg 8 | target.sfdc.password=****** 9 | target.env.endpoint=https://test.salesforce.com/services/Soap/u/44.0/ 10 | 11 | # Optional proxy 12 | env.proxy.host= 13 | env.proxy.port= 14 | 15 | target.threads.count=1 16 | 17 | source.type=org 18 | 19 | object.mapping.dir=/object-mappings/ 20 | data.mapping.dir=/data-mappings/ 21 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/resources/object-mappings/AccountwithAssetsAndOppties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "parent": "Account", 4 | "unmappedFields": [ 5 | "PhotoUrl", 6 | "IsPartner", 7 | "IsCustomerPortal", 8 | "IsPersonAccount" 9 | ], 10 | "children": [ 11 | { 12 | "parentMappedField": "AccountId", 13 | "childObject": "Opportunity", 14 | "unmappedFields": [ 15 | "IsClosed", 16 | "IsWon", 17 | "ForecastCategory", 18 | "HasOpportunityLineItem", 19 | "FiscalQuarter", 20 | "FiscalYear", 21 | "Fiscal", 22 | "HasOpenActivity", 23 | "HasOverdueTask" 24 | ], 25 | "sequence": 1 26 | }, 27 | { 28 | "parentMappedField": "AccountId", 29 | "childObject": "Asset", 30 | "sequence": 2, 31 | "lookups": [ 32 | { 33 | "lookupMappedField": "Product2Id", 34 | "lookupObject": "Product2", 35 | "keys": [ 36 | "Name" 37 | ] 38 | } 39 | ] 40 | } 41 | ], 42 | "lookups": [ 43 | { 44 | "lookupMappedField": "ParentId", 45 | "lookupObject": "Account", 46 | "keys": [ 47 | "Name", 48 | ] 49 | } 50 | ] 51 | } 52 | ] -------------------------------------------------------------------------------- /datamigrator-module/src/main/resources/object-mappings/AccountwithAssetsAndOppties_hierarchical.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "parent": "Account", 4 | "ExternalIdField": "ExternalKey__c", 5 | "where": " ExternalKey__c != null", 6 | "refresh": true, 7 | "unmappedFields": [ 8 | "PhotoUrl", 9 | "IsPartner", 10 | "IsCustomerPortal", 11 | "IsPersonAccount" 12 | ], 13 | "children": [ 14 | { 15 | "parentMappedField": "AccountId", 16 | "childObject": "Opportunity", 17 | "ExternalIdField": "ExternalKey__c", 18 | "where": " ExternalKey__c != null", 19 | "unmappedFields": [ 20 | "IsClosed", 21 | "IsWon", 22 | "ForecastCategory", 23 | "HasOpportunityLineItem", 24 | "FiscalQuarter", 25 | "FiscalYear", 26 | "Fiscal", 27 | "HasOpenActivity", 28 | "HasOverdueTask" 29 | ], 30 | "sequence": 1 31 | }, 32 | { 33 | "parentMappedField": "AccountId", 34 | "childObject": "Asset", 35 | "ExternalIdField": "ExternalKey__c", 36 | "where": " ExternalKey__c != null", 37 | "sequence": 2 38 | } 39 | ], 40 | "lookups": [ 41 | { 42 | "lookupMappedField": "ParentId", 43 | "lookupObject": "Account", 44 | "where": " ExternalKey__c != null", 45 | "keys": [ 46 | "Name", 47 | "ExternalKey__c" 48 | ] 49 | } 50 | ] 51 | } 52 | ] -------------------------------------------------------------------------------- /datamigrator-module/src/main/resources/object-mappings/PricebookEntry_nonstandard.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "parent": "Pricebook2", 4 | "where": " IsStandard = false ", 5 | "unmappedFields": ["IsStandard", "IsArchived"], 6 | "children": [ 7 | { 8 | "parentMappedField": "Pricebook2Id", 9 | "childObject": "PricebookEntry", 10 | "where": " Pricebook2.IsActive=true And Pricebook2.IsStandard = false AND Pricebook2Id != null And Product2Id != null ", 11 | "sequence": 1, 12 | "unmappedFields": ["ProductCode", "Name"], 13 | "lookups": [ 14 | { 15 | "lookupMappedField": "Product2Id", 16 | "lookupObject": "Product2", 17 | "where": " Name != null ", 18 | "keys": [ 19 | "Name" 20 | ] 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/resources/object-mappings/PricebookEntry_nonstandard_extId.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "parent": "Pricebook2", 4 | "where": " IsStandard = false ", 5 | "unmappedFields": ["IsStandard", "IsArchived"], 6 | "externalIdField": "ExternalKey__c", 7 | "children": [ 8 | { 9 | "parentMappedField": "Pricebook2Id", 10 | "childObject": "PricebookEntry", 11 | "externalIdField": "ExternalKey__c", 12 | "where": " Pricebook2.IsActive=true And Pricebook2.IsStandard = false AND Pricebook2Id != null And Product2Id != null ", 13 | "sequence": 1, 14 | "unmappedFields": ["ProductCode", "Name"], 15 | "lookups": [ 16 | { 17 | "lookupMappedField": "Product2Id", 18 | "lookupObject": "Product2", 19 | "where": " Name != null ", 20 | "keys": [ 21 | "Name" 22 | ] 23 | } 24 | ] 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /datamigrator-module/src/main/resources/object-mappings/PricebookEntry_standard.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "parent": "PricebookEntry", 4 | "where": " IsActive = true And Pricebook2.IsStandard = true AND Pricebook2Id != null ", 5 | "unmappedFields": ["ProductCode", "Name"], 6 | "lookups": [ 7 | { 8 | "lookupMappedField": "Pricebook2Id", 9 | "lookupObject": "Pricebook2", 10 | "where":" IsStandard = true ", 11 | "keys": [ 12 | "Name", 13 | "IsActive", 14 | "IsStandard" 15 | ] 16 | }, 17 | { 18 | "lookupMappedField": "Product2Id", 19 | "lookupObject": "Product2", 20 | "keys": [ 21 | "Name" 22 | ] 23 | } 24 | ] 25 | } 26 | ] -------------------------------------------------------------------------------- /datamigrator-module/src/main/resources/object-mappings/PricebookEntry_standard_extId.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "parent": "PricebookEntry", 4 | "where": " IsActive = true And Pricebook2.IsStandard = true AND Pricebook2Id != null ", 5 | "externalIdField": "ExternalKey__c", 6 | "unmappedFields": ["ProductCode", "Name"], 7 | "lookups": [ 8 | { 9 | "lookupMappedField": "Pricebook2Id", 10 | "lookupObject": "Pricebook2", 11 | "where":" IsStandard = true ", 12 | "keys": [ 13 | "Name", 14 | "IsActive", 15 | "IsStandard" 16 | ] 17 | }, 18 | { 19 | "lookupMappedField": "Product2Id", 20 | "lookupObject": "Product2", 21 | "keys": [ 22 | "Name" 23 | ] 24 | } 25 | ] 26 | } 27 | ] -------------------------------------------------------------------------------- /datamigrator-module/src/main/resources/object-mappings/Products.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "parent": "Product2" 4 | } 5 | ] -------------------------------------------------------------------------------- /datamigrator-module/src/main/resources/object-mappings/Products2_extId.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "parent": "Product2", 4 | "externalIdField": "ExternalKey__c" 5 | } 6 | ] -------------------------------------------------------------------------------- /images/design.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcedotcom/Data-Migration-Tool/da4eaff59581d0464c2ffd88e735eb19f89b3343/images/design.jpeg -------------------------------------------------------------------------------- /images/json-mapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcedotcom/Data-Migration-Tool/da4eaff59581d0464c2ffd88e735eb19f89b3343/images/json-mapping.png -------------------------------------------------------------------------------- /images/objects-relationships.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcedotcom/Data-Migration-Tool/da4eaff59581d0464c2ffd88e735eb19f89b3343/images/objects-relationships.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 4.0.0 7 | datamigrator.main 8 | datamigrator 9 | 0.0.1-SNAPSHOT 10 | pom 11 | migrator 12 | 13 | 14 | datamigrator-core 15 | datamigrator-module 16 | 17 | 18 | 19 | 20 | 21 | --------------------------------------------------------------------------------