← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 18176: merge strategy support, wip

 

------------------------------------------------------------
revno: 18176
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2015-02-05 13:53:38 +0700
message:
  merge strategy support, wip
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/MergeStrategy.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/attribute/Attribute.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/chart/BaseChart.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/chart/Chart.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseDimensionalObject.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseIdentifiableObject.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseNameableObject.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/Mergeable.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/constant/Constant.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dashboard/Dashboard.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dashboard/DashboardItem.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroup.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroupSet.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElement.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategory.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryCombo.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOption.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionCombo.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementGroup.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementGroupSet.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/DataSet.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/Section.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/document/Document.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventreport/EventReport.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/Indicator.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorGroup.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorGroupSet.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorType.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/Map.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLayer.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLegend.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLegendSet.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapView.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageConversation.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSet.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnit.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitGroup.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitGroupSet.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitLevel.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramIndicator.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStage.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStageSection.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramValidation.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/relationship/RelationshipType.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/report/Report.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/sqlview/SqlView.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttribute.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeGroup.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityForm.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceReminder.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/User.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserAuthorityGroup.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserCredentials.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserGroup.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRule.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRuleGroup.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/dimension/DefaultDimensionService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/gml/DefaultGmlImportService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/importers/DefaultIdentifiableObjectImporter.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/ChartController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/ReportTableController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventChartController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventReportController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/MapController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/MapLegendSetController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/user/UserController.java


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/attribute/Attribute.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/attribute/Attribute.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/attribute/Attribute.java	2015-02-05 06:53:38 +0000
@@ -35,6 +35,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 
@@ -287,15 +288,14 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             Attribute attribute = (Attribute) other;
 
-            valueType = attribute.getValueType() == null ? valueType : attribute.getValueType();
             dataElementAttribute = attribute.isDataElementAttribute();
             dataElementGroupAttribute = attribute.isDataElementGroupAttribute();
             indicatorAttribute = attribute.isIndicatorAttribute();
@@ -308,7 +308,17 @@
             userGroupAttribute = attribute.isUserGroupAttribute();
             programAttribute = attribute.isProgramAttribute();
             mandatory = attribute.isMandatory();
-            sortOrder = attribute.getSortOrder() == null ? sortOrder : attribute.getSortOrder();
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                valueType = attribute.getValueType();
+                sortOrder = attribute.getSortOrder();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                valueType = attribute.getValueType() == null ? valueType : attribute.getValueType();
+                sortOrder = attribute.getSortOrder() == null ? sortOrder : attribute.getSortOrder();
+            }
 
             attributeValues.clear();
             attributeValues.addAll( attribute.getAttributeValues() );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/chart/BaseChart.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/chart/BaseChart.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/chart/BaseChart.java	2015-02-05 06:53:38 +0000
@@ -42,6 +42,7 @@
 import org.hisp.dhis.common.Grid;
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObjectUtils;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.DimensionalView;
@@ -505,32 +506,51 @@
     // -------------------------------------------------------------------------
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             BaseChart chart = (BaseChart) other;
 
-            domainAxisLabel = chart.getDomainAxisLabel();
-            rangeAxisLabel = chart.getRangeAxisLabel();
-            type = chart.getType();
             hideLegend = chart.isHideLegend();
             regression = chart.isRegression();
             hideTitle = chart.isHideTitle();
             hideSubtitle = chart.isHideSubtitle();
-            title = chart.getTitle();
-            targetLineValue = chart.getTargetLineValue();
-            targetLineLabel = chart.getTargetLineLabel();
-            baseLineValue = chart.getBaseLineValue();
-            baseLineLabel = chart.getBaseLineLabel();
             showData = chart.isShowData();
             hideEmptyRows = chart.isHideEmptyRows();
-            rangeAxisMaxValue = chart.getRangeAxisMaxValue();
-            rangeAxisMinValue = chart.getRangeAxisMinValue();
-            rangeAxisSteps = chart.getRangeAxisSteps();
-            rangeAxisDecimals = chart.getRangeAxisDecimals();
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                domainAxisLabel = chart.getDomainAxisLabel();
+                rangeAxisLabel = chart.getRangeAxisLabel();
+                type = chart.getType();
+                title = chart.getTitle();
+                targetLineValue = chart.getTargetLineValue();
+                targetLineLabel = chart.getTargetLineLabel();
+                baseLineValue = chart.getBaseLineValue();
+                baseLineLabel = chart.getBaseLineLabel();
+                rangeAxisMaxValue = chart.getRangeAxisMaxValue();
+                rangeAxisMinValue = chart.getRangeAxisMinValue();
+                rangeAxisSteps = chart.getRangeAxisSteps();
+                rangeAxisDecimals = chart.getRangeAxisDecimals();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                domainAxisLabel = chart.getDomainAxisLabel() == null ? domainAxisLabel : chart.getDomainAxisLabel();
+                rangeAxisLabel = chart.getRangeAxisLabel() == null ? rangeAxisLabel : chart.getRangeAxisLabel();
+                type = chart.getType() == null ? type : chart.getType();
+                title = chart.getTitle() == null ? title : chart.getTitle();
+                targetLineValue = chart.getTargetLineValue() == null ? targetLineValue : chart.getTargetLineValue();
+                targetLineLabel = chart.getTargetLineLabel() == null ? targetLineLabel : chart.getTargetLineLabel();
+                baseLineValue = chart.getBaseLineValue() == null ? baseLineValue : chart.getBaseLineValue();
+                baseLineLabel = chart.getBaseLineLabel() == null ? baseLineLabel : chart.getBaseLineLabel();
+                rangeAxisMaxValue = chart.getRangeAxisMaxValue() == null ? rangeAxisMaxValue : chart.getRangeAxisMaxValue();
+                rangeAxisMinValue = chart.getRangeAxisMinValue() == null ? rangeAxisMinValue : chart.getRangeAxisMinValue();
+                rangeAxisSteps = chart.getRangeAxisSteps() == null ? rangeAxisSteps : chart.getRangeAxisSteps();
+                rangeAxisDecimals = chart.getRangeAxisDecimals() == null ? rangeAxisDecimals : chart.getRangeAxisDecimals();
+            }
 
             filterDimensions.clear();
             filterDimensions.addAll( chart.getFilterDimensions() );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/chart/Chart.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/chart/Chart.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/chart/Chart.java	2015-02-05 06:53:38 +0000
@@ -28,14 +28,15 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
 import org.hisp.dhis.common.AnalyticsType;
 import org.hisp.dhis.common.DimensionalObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.DimensionalView;
@@ -45,10 +46,9 @@
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.user.User;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonView;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
 
 /**
  * @author Lars Helge Overland
@@ -166,10 +166,10 @@
 
     /**
      * Sets all dimensions for this chart.
-     * 
-     * @param series the series dimension.
+     *
+     * @param series   the series dimension.
      * @param category the category dimension.
-     * @param filter the filter dimension.
+     * @param filter   the filter dimension.
      */
     public void setDimensions( String series, String category, String filter )
     {
@@ -245,17 +245,26 @@
     // -------------------------------------------------------------------------
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             Chart chart = (Chart) other;
 
-            series = chart.getSeries();
-            category = chart.getCategory();
             rewindRelativePeriods = chart.isRewindRelativePeriods();
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                series = chart.getSeries();
+                category = chart.getCategory();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                series = chart.getSeries() == null ? series : chart.getSeries();
+                category = chart.getCategory() == null ? category : chart.getCategory();
+            }
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java	2015-02-05 06:53:38 +0000
@@ -753,9 +753,9 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
@@ -763,12 +763,20 @@
 
             this.clear();
 
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                relatives = object.getRelatives();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                relatives = object.getRelatives() == null ? relatives : object.getRelatives();
+            }
+
             indicators.addAll( object.getIndicators() );
             dataElements.addAll( object.getDataElements() );
             dataElementOperands.addAll( object.getDataElementOperands() );
             dataSets.addAll( object.getDataSets() );
             periods.addAll( object.getPeriods() );
-            relatives = object.getRelatives() == null ? relatives : object.getRelatives();
             organisationUnits.addAll( object.getOrganisationUnits() );
             dataElementGroups.addAll( object.getDataElementGroups() );
             organisationUnitGroups.addAll( object.getOrganisationUnitGroups() );
@@ -777,12 +785,12 @@
             categoryOptionGroups.addAll( object.getCategoryOptionGroups() );
             attributeDimensions.addAll( object.getAttributeDimensions() );
             dataElementDimensions.addAll( object.getDataElementDimensions() );
-            userOrganisationUnit = object.isUserOrganisationUnit();
             userOrganisationUnitChildren = object.isUserOrganisationUnitChildren();
             userOrganisationUnitGrandChildren = object.isUserOrganisationUnitGrandChildren();
             itemOrganisationUnitGroups = object.getItemOrganisationUnitGroups();
             rewindRelativePeriods = object.isRewindRelativePeriods();
             digitGroupSeparator = object.getDigitGroupSeparator();
+            userOrganisationUnit = object.isUserOrganisationUnit();
             sortOrder = object.getSortOrder();
             topLimit = object.getTopLimit();
         }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseDimensionalObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseDimensionalObject.java	2015-02-03 14:33:39 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseDimensionalObject.java	2015-02-05 06:53:38 +0000
@@ -28,12 +28,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.hisp.dhis.common.view.DimensionalView;
-
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonView;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
@@ -41,6 +35,11 @@
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import org.hisp.dhis.common.view.DimensionalView;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 @JacksonXmlRootElement( localName = "dimension", namespace = DxfNamespaces.DXF_2_0 )
 public class BaseDimensionalObject
@@ -139,16 +138,16 @@
     {
         return dimensionName != null ? dimensionName : uid;
     }
-    
+
     @Override
     public AnalyticsType getAnalyticsType()
     {
-        return 
+        return
             DimensionType.TRACKED_ENTITY_ATTRIBUTE.equals( dimensionType ) ||
-            DimensionType.TRACKED_ENTITY_DATAELEMENT.equals( dimensionType ) ?
-            AnalyticsType.EVENT : AnalyticsType.AGGREGATE;
+                DimensionType.TRACKED_ENTITY_DATAELEMENT.equals( dimensionType ) ?
+                AnalyticsType.EVENT : AnalyticsType.AGGREGATE;
     }
-    
+
     /**
      * Returns the items in the filter as a list. Order of items are preserved.
      * Requires that the filter has the IN operator and that at least one item
@@ -158,17 +157,17 @@
     {
         final String inOp = QueryOperator.IN.getValue().toLowerCase();
         final int opLen = inOp.length() + 1;
-        
+
         if ( filter == null || !filter.toLowerCase().startsWith( inOp ) || filter.length() < opLen )
         {
             return null;
         }
-        
+
         String filterItems = filter.substring( opLen, filter.length() );
-        
+
         return new ArrayList<>( Arrays.asList( filterItems.split( DimensionalObjectUtils.OPTION_SEP ) ) );
     }
-    
+
     //--------------------------------------------------------------------------
     // Getters and setters
     //--------------------------------------------------------------------------
@@ -231,29 +230,38 @@
     {
         this.filter = filter;
     }
-    
+
     //--------------------------------------------------------------------------
     // Supportive methods
     //--------------------------------------------------------------------------
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             DimensionalObject dimensionalObject = (DimensionalObject) other;
-            
-            dimensionType = dimensionalObject.getDimensionType() == null ? dimensionType : dimensionalObject.getDimensionType();
-            dimensionName = dimensionalObject.getDimensionName() == null ? dimensionName : dimensionalObject.getDimensionName();
-            filter = dimensionalObject.getFilter() == null ? filter : dimensionalObject.getFilter();
-            
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                dimensionType = dimensionalObject.getDimensionType();
+                dimensionName = dimensionalObject.getDimensionName();
+                filter = dimensionalObject.getFilter();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                dimensionType = dimensionalObject.getDimensionType() == null ? dimensionType : dimensionalObject.getDimensionType();
+                dimensionName = dimensionalObject.getDimensionName() == null ? dimensionName : dimensionalObject.getDimensionName();
+                filter = dimensionalObject.getFilter() == null ? filter : dimensionalObject.getFilter();
+            }
+
             items.clear();
             items.addAll( dimensionalObject.getItems() );
         }
     }
-    
+
     @Override
     public String toString()
     {

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseIdentifiableObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseIdentifiableObject.java	2015-01-23 15:29:20 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseIdentifiableObject.java	2015-02-05 06:53:38 +0000
@@ -540,18 +540,28 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
         Validate.notNull( other );
 
-        uid = other.getUid() == null ? uid : other.getUid();
-        name = other.getName() == null ? name : other.getName();
-        code = other.getCode() == null ? code : other.getCode();
-        lastUpdated = other.getLastUpdated() == null ? lastUpdated : other.getLastUpdated();
-        created = other.getCreated() == null ? created : other.getCreated();
-
-        // TODO leave this in? we might have sub-classes that have user which is not sharing related
-        user = other.getUser() == null ? user : other.getUser();
+        if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+        {
+            uid = other.getUid();
+            name = other.getName();
+            code = other.getCode();
+            lastUpdated = other.getLastUpdated();
+            created = other.getCreated();
+            user = other.getUser();
+        }
+        else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+        {
+            uid = other.getUid() == null ? uid : other.getUid();
+            name = other.getName() == null ? name : other.getName();
+            code = other.getCode() == null ? code : other.getCode();
+            lastUpdated = other.getLastUpdated() == null ? lastUpdated : other.getLastUpdated();
+            created = other.getCreated() == null ? created : other.getCreated();
+            user = other.getUser() == null ? user : other.getUser();
+        }
     }
 
     @Override

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseNameableObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseNameableObject.java	2015-01-23 15:29:20 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseNameableObject.java	2015-02-05 06:53:38 +0000
@@ -28,14 +28,13 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import org.hisp.dhis.common.view.DetailedView;
-import org.hisp.dhis.common.view.ExportView;
-import org.hisp.dhis.common.view.ShortNameView;
-
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonView;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import org.hisp.dhis.common.view.DetailedView;
+import org.hisp.dhis.common.view.ExportView;
+import org.hisp.dhis.common.view.ShortNameView;
 import org.hisp.dhis.schema.annotation.PropertyRange;
 
 /**
@@ -93,7 +92,7 @@
         this.code = code;
         this.description = description;
     }
-    
+
     public BaseNameableObject( NameableObject object )
     {
         super( object.getId(), object.getUid(), object.getName() );
@@ -214,16 +213,25 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             NameableObject nameableObject = (NameableObject) other;
 
-            this.shortName = nameableObject.getShortName() == null ? this.shortName : nameableObject.getShortName();
-            this.description = nameableObject.getDescription() == null ? this.description : nameableObject.getDescription();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                this.shortName = nameableObject.getShortName();
+                this.description = nameableObject.getDescription();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                this.shortName = nameableObject.getShortName() == null ? this.shortName : nameableObject.getShortName();
+                this.description = nameableObject.getDescription() == null ? this.description : nameableObject.getDescription();
+            }
+
         }
     }
 }

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/MergeStrategy.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/MergeStrategy.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/MergeStrategy.java	2015-02-05 06:53:38 +0000
@@ -0,0 +1,37 @@
+package org.hisp.dhis.common;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 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.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * 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 OWNER 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.
+ */
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public enum MergeStrategy
+{
+    MERGE_ALWAYS, MERGE_IF_NOT_NULL
+}

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/Mergeable.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/Mergeable.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/Mergeable.java	2015-02-05 06:53:38 +0000
@@ -36,7 +36,7 @@
  */
 public interface Mergeable<T>
 {
-    void mergeWith( T other );
+    void mergeWith( T other, MergeStrategy strategy );
 
     void mergeSharingWith( T other );
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/constant/Constant.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/constant/Constant.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/constant/Constant.java	2015-02-05 06:53:38 +0000
@@ -35,6 +35,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 
@@ -80,7 +81,7 @@
     // -------------------------------------------------------------------------
 
     @JsonProperty
-    @JsonView( {DetailedView.class, ExportView.class} )
+    @JsonView( { DetailedView.class, ExportView.class } )
     @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public double getValue()
     {
@@ -93,15 +94,14 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
-        if(other.getClass().isInstance( this ))
+        if ( other.getClass().isInstance( this ) )
         {
             Constant constant = (Constant) other;
-
-            this.value = constant.getValue();
+            value = constant.getValue();
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dashboard/Dashboard.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dashboard/Dashboard.java	2015-01-22 11:23:36 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dashboard/Dashboard.java	2015-02-05 06:53:38 +0000
@@ -28,22 +28,22 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.ArrayList;
-import java.util.List;
-
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonView;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author Lars Helge Overland
@@ -142,7 +142,7 @@
 
         return null;
     }
-    
+
     /**
      * Indicates whether this dashboard has at least one item.
      */
@@ -178,9 +178,9 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dashboard/DashboardItem.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dashboard/DashboardItem.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dashboard/DashboardItem.java	2015-02-05 06:53:38 +0000
@@ -34,11 +34,11 @@
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
-
 import org.hisp.dhis.chart.Chart;
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -80,7 +80,7 @@
     public static final String SHAPE_NORMAL = "normal";
     public static final String SHAPE_DOUBLE_WIDTH = "double_width";
     public static final String SHAPE_FULL_WIDTH = "full_width";
-    
+
     private Chart chart;
 
     private EventChart eventChart;
@@ -88,9 +88,9 @@
     private Map map;
 
     private ReportTable reportTable;
-    
+
     private EventReport eventReport;
-    
+
     @Scanned
     private List<User> users = new ArrayList<>();
 
@@ -424,22 +424,36 @@
     // -------------------------------------------------------------------------
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
-            DashboardItem item = (DashboardItem) other;
+            DashboardItem dashboardItem = (DashboardItem) other;
 
-            chart = item.getChart() == null ? chart : item.getChart();
-            map = item.getMap() == null ? map : item.getMap();
-            reportTable = item.getReportTable() == null ? reportTable : item.getReportTable();
-            users = item.getUsers() == null ? users : item.getUsers();
-            reports = item.getReports() == null ? reports : item.getReports();
-            resources = item.getResources() == null ? resources : item.getResources();
-            messages = item.getMessages() == null ? messages : item.getMessages();
-            shape = item.getShape() == null ? shape : item.getShape();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                chart = dashboardItem.getChart();
+                map = dashboardItem.getMap();
+                reportTable = dashboardItem.getReportTable();
+                users = dashboardItem.getUsers();
+                reports = dashboardItem.getReports();
+                resources = dashboardItem.getResources();
+                messages = dashboardItem.getMessages();
+                shape = dashboardItem.getShape();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                chart = dashboardItem.getChart() == null ? chart : dashboardItem.getChart();
+                map = dashboardItem.getMap() == null ? map : dashboardItem.getMap();
+                reportTable = dashboardItem.getReportTable() == null ? reportTable : dashboardItem.getReportTable();
+                users = dashboardItem.getUsers() == null ? users : dashboardItem.getUsers();
+                reports = dashboardItem.getReports() == null ? reports : dashboardItem.getReports();
+                resources = dashboardItem.getResources() == null ? resources : dashboardItem.getResources();
+                messages = dashboardItem.getMessages() == null ? messages : dashboardItem.getMessages();
+                shape = dashboardItem.getShape() == null ? shape : dashboardItem.getShape();
+            }
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroup.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroup.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroup.java	2015-02-05 06:53:38 +0000
@@ -38,6 +38,7 @@
 import org.hisp.dhis.common.BaseNameableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -122,14 +123,23 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             CategoryOptionGroup categoryOptionGroup = (CategoryOptionGroup) other;
 
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                groupSet = categoryOptionGroup.getGroupSet() == null ? groupSet : categoryOptionGroup.getGroupSet();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                groupSet = categoryOptionGroup.getGroupSet();
+            }
+
             members.clear();
 
             for ( DataElementCategoryOption categoryOption : categoryOptionGroup.getMembers() )

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroupSet.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroupSet.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroupSet.java	2015-02-05 06:53:38 +0000
@@ -39,6 +39,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
@@ -162,9 +163,9 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElement.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElement.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElement.java	2015-02-05 06:53:38 +0000
@@ -39,6 +39,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.dataset.DataSet;
@@ -363,6 +364,7 @@
     /**
      * Indicates whether collecting data for future periods should be allowed for
      * this data element.
+     *
      * @return true if all the associated data sets allow future periods, false otherwise.
      */
     public boolean isAllowFuturePeriods()
@@ -727,25 +729,40 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             DataElement dataElement = (DataElement) other;
 
-            formName = dataElement.getFormName() == null ? formName : dataElement.getFormName();
             zeroIsSignificant = dataElement.isZeroIsSignificant();
-            domainType = dataElement.getDomainType() == null ? domainType : dataElement.getDomainType();
-            type = dataElement.getType() == null ? type : dataElement.getType();
-            numberType = dataElement.getNumberType() == null ? numberType : dataElement.getNumberType();
-            textType = dataElement.getTextType() == null ? textType : dataElement.getTextType();
-            aggregationOperator = dataElement.getAggregationOperator() == null ? aggregationOperator : dataElement
-                .getAggregationOperator();
-            categoryCombo = dataElement.getCategoryCombo() == null ? categoryCombo : dataElement.getCategoryCombo();
-            url = dataElement.getUrl() == null ? url : dataElement.getUrl();
-            optionSet = dataElement.getOptionSet() == null ? optionSet : dataElement.getOptionSet();
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                formName = dataElement.getFormName();
+                domainType = dataElement.getDomainType();
+                type = dataElement.getType();
+                numberType = dataElement.getNumberType();
+                textType = dataElement.getTextType();
+                aggregationOperator = dataElement.getAggregationOperator();
+                categoryCombo = dataElement.getCategoryCombo();
+                url = dataElement.getUrl();
+                optionSet = dataElement.getOptionSet();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                formName = dataElement.getFormName() == null ? formName : dataElement.getFormName();
+                domainType = dataElement.getDomainType() == null ? domainType : dataElement.getDomainType();
+                type = dataElement.getType() == null ? type : dataElement.getType();
+                numberType = dataElement.getNumberType() == null ? numberType : dataElement.getNumberType();
+                textType = dataElement.getTextType() == null ? textType : dataElement.getTextType();
+                aggregationOperator = dataElement.getAggregationOperator() == null ? aggregationOperator : dataElement.getAggregationOperator();
+                categoryCombo = dataElement.getCategoryCombo() == null ? categoryCombo : dataElement.getCategoryCombo();
+                url = dataElement.getUrl() == null ? url : dataElement.getUrl();
+                optionSet = dataElement.getOptionSet() == null ? optionSet : dataElement.getOptionSet();
+            }
 
             groups.clear();
             dataSets.clear();

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategory.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategory.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategory.java	2015-02-05 06:53:38 +0000
@@ -28,25 +28,25 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.ArrayList;
-import java.util.List;
-
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
 import org.hisp.dhis.common.BaseDimensionalObject;
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.DimensionalView;
 import org.hisp.dhis.common.view.ExportView;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonView;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * A Category is a dimension of a data element. DataElements can have sets of
@@ -110,7 +110,7 @@
         categoryOptions.remove( dataElementCategoryOption );
         dataElementCategoryOption.getCategories().remove( this );
     }
-    
+
     public void removeAllCategoryOptions()
     {
         for ( DataElementCategoryOption categoryOption : categoryOptions )
@@ -223,17 +223,26 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
-            DataElementCategory dataElementCategory = (DataElementCategory) other;
+            DataElementCategory category = (DataElementCategory) other;
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                dataDimensionType = category.getDataDimensionType();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                dataDimensionType = category.getDataDimensionType() == null ? dataDimensionType : category.getDataDimensionType();
+            }
 
             removeAllCategoryOptions();
 
-            for ( DataElementCategoryOption dataElementCategoryOption : dataElementCategory.getCategoryOptions() )
+            for ( DataElementCategoryOption dataElementCategoryOption : category.getCategoryOptions() )
             {
                 addDataElementCategoryOption( dataElementCategoryOption );
             }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryCombo.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryCombo.java	2015-02-03 11:35:42 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryCombo.java	2015-02-05 06:53:38 +0000
@@ -38,6 +38,7 @@
 import org.hisp.dhis.common.CombinationGenerator;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -147,7 +148,7 @@
 
         return arrays;
     }
-    
+
     public List<DataElementCategoryOptionCombo> generateOptionCombosList()
     {
         List<DataElementCategoryOptionCombo> list = new ArrayList<>();
@@ -323,9 +324,9 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOption.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOption.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOption.java	2015-02-05 06:53:38 +0000
@@ -38,6 +38,7 @@
 import org.hisp.dhis.common.BaseNameableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -260,26 +261,34 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
-            DataElementCategoryOption dataElementCategoryOption = (DataElementCategoryOption) other;
+            DataElementCategoryOption categoryOption = (DataElementCategoryOption) other;
 
-            startDate = dataElementCategoryOption.getStartDate();
-            endDate = dataElementCategoryOption.getEndDate();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                startDate = categoryOption.getStartDate();
+                endDate = categoryOption.getEndDate();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                startDate = categoryOption.getStartDate() == null ? startDate : categoryOption.getStartDate();
+                endDate = categoryOption.getEndDate() == null ? endDate : categoryOption.getEndDate();
+            }
 
             organisationUnits.clear();
             categories.clear();
             groups.clear();
             categoryOptionCombos.clear();
 
-            organisationUnits.addAll( dataElementCategoryOption.getOrganisationUnits() );
-            categories.addAll( dataElementCategoryOption.getCategories() );
-            groups.addAll( dataElementCategoryOption.getGroups() );
-            categoryOptionCombos.addAll( dataElementCategoryOption.getCategoryOptionCombos() );
+            organisationUnits.addAll( categoryOption.getOrganisationUnits() );
+            categories.addAll( categoryOption.getCategories() );
+            groups.addAll( categoryOption.getGroups() );
+            categoryOptionCombos.addAll( categoryOption.getCategoryOptionCombos() );
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionCombo.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionCombo.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionCombo.java	2015-02-05 06:53:38 +0000
@@ -39,6 +39,7 @@
 import org.hisp.dhis.common.BaseNameableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -393,22 +394,28 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
-            DataElementCategoryOptionCombo dataElementCategoryOptionCombo = (DataElementCategoryOptionCombo) other;
+            DataElementCategoryOptionCombo categoryOptionCombo = (DataElementCategoryOptionCombo) other;
 
-            categoryCombo = dataElementCategoryOptionCombo.getCategoryCombo() == null ? categoryCombo : dataElementCategoryOptionCombo
-                .getCategoryCombo();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                categoryCombo = categoryOptionCombo.getCategoryCombo();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                categoryCombo = categoryOptionCombo.getCategoryCombo() == null ? categoryCombo : categoryOptionCombo.getCategoryCombo();
+            }
 
             removeAllCategoryOptions();
 
-            for ( DataElementCategoryOption dataElementCategoryOption : dataElementCategoryOptionCombo.getCategoryOptions() )
+            for ( DataElementCategoryOption categoryOption : categoryOptionCombo.getCategoryOptions() )
             {
-                addDataElementCategoryOption( dataElementCategoryOption );
+                addDataElementCategoryOption( categoryOption );
             }
         }
     }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementGroup.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementGroup.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementGroup.java	2015-02-05 06:53:38 +0000
@@ -39,6 +39,7 @@
 import org.hisp.dhis.common.BaseNameableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -125,7 +126,7 @@
             addDataElement( dataElement );
         }
     }
-    
+
     /**
      * Returns the value type of the data elements in this group. Uses an arbitrary
      * member to determine the value type.
@@ -134,7 +135,7 @@
     {
         return members != null && !members.isEmpty() ? members.iterator().next().getType() : null;
     }
-    
+
     /**
      * Returns the aggregation operator of the data elements in this group. Uses
      * an arbitrary member to determine the aggregation operator.
@@ -145,7 +146,7 @@
     }
 
     /**
-     * Returns the period type of the data elements in this group. Uses an 
+     * Returns the period type of the data elements in this group. Uses an
      * arbitrary member to determine the period type.
      */
     public PeriodType getPeriodType()
@@ -160,8 +161,8 @@
     @JsonProperty( "dataElements" )
     @JsonSerialize( contentAs = BaseIdentifiableObject.class )
     @JsonView( { DetailedView.class, ExportView.class } )
-    @JacksonXmlElementWrapper( localName = "dataElements", namespace = DxfNamespaces.DXF_2_0)
-    @JacksonXmlProperty( localName = "dataElement", namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlElementWrapper( localName = "dataElements", namespace = DxfNamespaces.DXF_2_0 )
+    @JacksonXmlProperty( localName = "dataElement", namespace = DxfNamespaces.DXF_2_0 )
     public Set<DataElement> getMembers()
     {
         return members;
@@ -175,7 +176,7 @@
     @JsonProperty( "dataElementGroupSet" )
     @JsonSerialize( as = BaseIdentifiableObject.class )
     @JsonView( { DetailedView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public DataElementGroupSet getGroupSet()
     {
         return groupSet;
@@ -188,8 +189,8 @@
 
     @JsonProperty( "attributeValues" )
     @JsonView( { DetailedView.class, ExportView.class } )
-    @JacksonXmlElementWrapper( localName = "attributeValues", namespace = DxfNamespaces.DXF_2_0)
-    @JacksonXmlProperty( localName = "attributeValue", namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlElementWrapper( localName = "attributeValues", namespace = DxfNamespaces.DXF_2_0 )
+    @JacksonXmlProperty( localName = "attributeValue", namespace = DxfNamespaces.DXF_2_0 )
     public Set<AttributeValue> getAttributeValues()
     {
         return attributeValues;
@@ -201,15 +202,22 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             DataElementGroup dataElementGroup = (DataElementGroup) other;
 
-            groupSet = null;
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                groupSet = dataElementGroup.getGroupSet();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                groupSet = dataElementGroup.getGroupSet() == null ? groupSet : dataElementGroup.getGroupSet();
+            }
 
             removeAllDataElements();
 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementGroupSet.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementGroupSet.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementGroupSet.java	2015-02-05 06:53:38 +0000
@@ -38,6 +38,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.comparator.IdentifiableObjectNameComparator;
@@ -268,18 +269,27 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             DataElementGroupSet dataElementGroupSet = (DataElementGroupSet) other;
 
-            description = dataElementGroupSet.getDescription() == null ? description : dataElementGroupSet.getDescription();
-            compulsory = dataElementGroupSet.isCompulsory() == null ? compulsory : dataElementGroupSet.isCompulsory();
             dataDimension = dataElementGroupSet.isDataDimension();
 
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                description = dataElementGroupSet.getDescription();
+                compulsory = dataElementGroupSet.isCompulsory();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                description = dataElementGroupSet.getDescription() == null ? description : dataElementGroupSet.getDescription();
+                compulsory = dataElementGroupSet.isCompulsory() == null ? compulsory : dataElementGroupSet.isCompulsory();
+            }
+
             removeAllDataElementGroups();
 
             for ( DataElementGroup dataElementGroup : dataElementGroupSet.getMembers() )

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/DataSet.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/DataSet.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/DataSet.java	2015-02-05 06:53:38 +0000
@@ -40,6 +40,7 @@
 import org.hisp.dhis.common.BaseNameableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.adapter.JacksonPeriodTypeDeserializer;
 import org.hisp.dhis.common.adapter.JacksonPeriodTypeSerializer;
 import org.hisp.dhis.common.annotation.Scanned;
@@ -796,30 +797,41 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             DataSet dataSet = (DataSet) other;
 
-            periodType = dataSet.getPeriodType() == null ? periodType : dataSet.getPeriodType();
-            mobile = dataSet.isMobile();
-            dataEntryForm = dataSet.getDataEntryForm() == null ? dataEntryForm : dataSet.getDataEntryForm();
-            version = dataSet.getVersion() == null ? version : dataSet.getVersion();
+            dataElementDecoration = dataSet.isDataElementDecoration();
+            skipOffline = dataSet.isSkipOffline();
+            renderAsTabs = dataSet.isRenderAsTabs();
+            renderHorizontally = dataSet.isRenderHorizontally();
             expiryDays = dataSet.getExpiryDays();
             skipAggregation = dataSet.isSkipAggregation();
             allowFuturePeriods = dataSet.isAllowFuturePeriods();
             fieldCombinationRequired = dataSet.isFieldCombinationRequired();
+            mobile = dataSet.isMobile();
             validCompleteOnly = dataSet.isValidCompleteOnly();
-            skipOffline = dataSet.isSkipOffline();
-            renderAsTabs = dataSet.isRenderAsTabs();
-            renderHorizontally = dataSet.isRenderHorizontally();
-            legendSet = dataSet.getLegendSet() == null ? legendSet : dataSet.getLegendSet();
 
-            dataElementDecoration = dataSet.isDataElementDecoration();
-            notificationRecipients = dataSet.getNotificationRecipients();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                periodType = dataSet.getPeriodType();
+                dataEntryForm = dataSet.getDataEntryForm();
+                version = dataSet.getVersion();
+                legendSet = dataSet.getLegendSet();
+                notificationRecipients = dataSet.getNotificationRecipients();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                periodType = dataSet.getPeriodType() == null ? periodType : dataSet.getPeriodType();
+                dataEntryForm = dataSet.getDataEntryForm() == null ? dataEntryForm : dataSet.getDataEntryForm();
+                version = dataSet.getVersion() == null ? version : dataSet.getVersion();
+                legendSet = dataSet.getLegendSet() == null ? legendSet : dataSet.getLegendSet();
+                notificationRecipients = dataSet.getNotificationRecipients() == null ? notificationRecipients : dataSet.getNotificationRecipients();
+            }
 
             dataElements.clear();
 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/Section.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/Section.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/Section.java	2015-02-05 06:53:38 +0000
@@ -37,6 +37,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -263,15 +264,22 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             Section section = (Section) other;
 
-            dataSet = section.getDataSet() == null ? dataSet : section.getDataSet();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                dataSet = section.getDataSet();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                dataSet = section.getDataSet() == null ? dataSet : section.getDataSet();
+            }
 
             removeAllDataElements();
 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/document/Document.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/document/Document.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/document/Document.java	2015-02-05 06:53:38 +0000
@@ -35,6 +35,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.schema.PropertyType;
@@ -127,17 +128,26 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             Document document = (Document) other;
 
-            url = document.getUrl() == null ? url : document.getUrl();
-            contentType = document.getContentType() == null ? contentType : document.getContentType();
             external = document.isExternal();
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                url = document.getUrl();
+                contentType = document.getContentType();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                url = document.getUrl() == null ? url : document.getUrl();
+                contentType = document.getContentType() == null ? contentType : document.getContentType();
+            }
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java	2015-02-05 06:53:38 +0000
@@ -28,10 +28,12 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
 import org.hisp.dhis.chart.BaseChart;
 import org.hisp.dhis.common.AnalyticsType;
 import org.hisp.dhis.common.BaseIdentifiableObject;
@@ -40,6 +42,7 @@
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.EventAnalyticalObject;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.DimensionalView;
@@ -50,12 +53,9 @@
 import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.user.User;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonView;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
 
 /**
  * @author Jan Henrik Overland
@@ -131,12 +131,12 @@
     public List<NameableObject> series()
     {
         String series = columnDimensions.get( 0 );
-        
+
         DimensionalObject object = getDimensionalObject( series, relativePeriodDate, user, true,
             organisationUnitsAtLevel, organisationUnitsInGroups, format );
 
         DimensionalObjectUtils.setDimensionItemsForFilters( object, dataItemGrid, true );
-        
+
         return object != null ? object.getItems() : null;
     }
 
@@ -144,15 +144,15 @@
     public List<NameableObject> category()
     {
         String category = rowDimensions.get( 0 );
-        
+
         DimensionalObject object = getDimensionalObject( category, relativePeriodDate, user, true,
             organisationUnitsAtLevel, organisationUnitsInGroups, format );
 
         DimensionalObjectUtils.setDimensionItemsForFilters( object, dataItemGrid, true );
-        
+
         return object != null ? object.getItems() : null;
     }
-    
+
     @Override
     public AnalyticsType getAnalyticsType()
     {
@@ -267,26 +267,36 @@
     // -------------------------------------------------------------------------
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             EventChart eventChart = (EventChart) other;
 
-            program = eventChart.getProgram();
-            programStage = eventChart.getProgramStage();
-            startDate = eventChart.getStartDate();
-            endDate = eventChart.getEndDate();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                program = eventChart.getProgram();
+                programStage = eventChart.getProgramStage();
+                startDate = eventChart.getStartDate();
+                endDate = eventChart.getEndDate();
+                countType = eventChart.getCountType();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                program = eventChart.getProgram() == null ? program : eventChart.getProgram();
+                programStage = eventChart.getProgramStage() == null ? programStage : eventChart.getProgramStage();
+                startDate = eventChart.getStartDate() == null ? startDate : eventChart.getStartDate();
+                endDate = eventChart.getEndDate() == null ? endDate : eventChart.getEndDate();
+                countType = eventChart.getCountType() == null ? countType : eventChart.getCountType();
+            }
 
             columnDimensions.clear();
             columnDimensions.addAll( eventChart.getColumnDimensions() );
 
             rowDimensions.clear();
             rowDimensions.addAll( eventChart.getRowDimensions() );
-
-            countType = eventChart.getCountType();
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventreport/EventReport.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventreport/EventReport.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventreport/EventReport.java	2015-02-05 06:53:38 +0000
@@ -34,12 +34,12 @@
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
-
 import org.hisp.dhis.common.BaseAnalyticalObject;
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.EventAnalyticalObject;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.DimensionalView;
 import org.hisp.dhis.common.view.ExportView;
@@ -320,8 +320,8 @@
     }
 
     @JsonProperty
-    @JsonView( {DetailedView.class, ExportView.class, DimensionalView.class} )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public boolean isRowTotals()
     {
         return rowTotals;
@@ -333,8 +333,8 @@
     }
 
     @JsonProperty
-    @JsonView( {DetailedView.class, ExportView.class, DimensionalView.class} )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public boolean isColTotals()
     {
         return colTotals;
@@ -346,8 +346,8 @@
     }
 
     @JsonProperty
-    @JsonView( {DetailedView.class, ExportView.class, DimensionalView.class} )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public boolean isRowSubTotals()
     {
         return rowSubTotals;
@@ -356,11 +356,11 @@
     public void setRowSubTotals( boolean rowSubTotals )
     {
         this.rowSubTotals = rowSubTotals;
-    }    
+    }
 
     @JsonProperty
-    @JsonView( {DetailedView.class, ExportView.class, DimensionalView.class} )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public boolean isColSubTotals()
     {
         return colSubTotals;
@@ -435,7 +435,7 @@
     {
         this.fontSize = fontSize;
     }
-    
+
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
     @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
@@ -447,32 +447,47 @@
     public void setShowDimensionLabels( boolean showDimensionLabels )
     {
         this.showDimensionLabels = showDimensionLabels;
-    }    
+    }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             EventReport eventReport = (EventReport) other;
 
-            dataType = eventReport.getDataType();
-            program = eventReport.getProgram();
-            programStage = eventReport.getProgramStage();
-            startDate = eventReport.getStartDate();
-            endDate = eventReport.getEndDate();
-            rowTotals = eventReport.isRowTotals();
-            colTotals = eventReport.isColTotals();
             rowSubTotals = eventReport.isRowSubTotals();
             colSubTotals = eventReport.isColSubTotals();
             hideEmptyRows = eventReport.isHideEmptyRows();
-            countType = eventReport.getCountType();
+            rowTotals = eventReport.isRowTotals();
+            colTotals = eventReport.isColTotals();
             showHierarchy = eventReport.isShowHierarchy();
             showDimensionLabels = eventReport.isShowDimensionLabels();
-            displayDensity = eventReport.getDisplayDensity();
-            fontSize = eventReport.getFontSize();
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                dataType = eventReport.getDataType();
+                program = eventReport.getProgram();
+                programStage = eventReport.getProgramStage();
+                startDate = eventReport.getStartDate();
+                endDate = eventReport.getEndDate();
+                countType = eventReport.getCountType();
+                displayDensity = eventReport.getDisplayDensity();
+                fontSize = eventReport.getFontSize();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                dataType = eventReport.getDataType() == null ? dataType : eventReport.getDataType();
+                program = eventReport.getProgram() == null ? program : eventReport.getProgram();
+                programStage = eventReport.getProgramStage() == null ? programStage : eventReport.getProgramStage();
+                startDate = eventReport.getStartDate() == null ? startDate : eventReport.getStartDate();
+                endDate = eventReport.getEndDate() == null ? endDate : eventReport.getEndDate();
+                countType = eventReport.getCountType() == null ? countType : eventReport.getCountType();
+                displayDensity = eventReport.getDisplayDensity() == null ? displayDensity : eventReport.getDisplayDensity();
+                fontSize = eventReport.getFontSize() == null ? fontSize : eventReport.getFontSize();
+            }
 
             columnDimensions.clear();
             columnDimensions.addAll( eventReport.getColumnDimensions() );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/Indicator.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/Indicator.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/Indicator.java	2015-02-05 06:53:38 +0000
@@ -40,6 +40,7 @@
 import org.hisp.dhis.common.BaseNameableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.dataset.DataSet;
@@ -366,23 +367,38 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             Indicator indicator = (Indicator) other;
 
             annualized = indicator.isAnnualized();
-            denominator = indicator.getDenominator() == null ? denominator : indicator.getDenominator();
-            denominatorDescription = indicator.getDenominatorDescription() == null ? denominatorDescription : indicator.getDenominatorDescription();
-            numerator = indicator.getNumerator() == null ? numerator : indicator.getNumerator();
-            numeratorDescription = indicator.getNumeratorDescription() == null ? numeratorDescription : indicator.getNumeratorDescription();
-            explodedNumerator = indicator.getExplodedNumerator() == null ? explodedNumerator : indicator.getExplodedNumerator();
-            explodedDenominator = indicator.getExplodedDenominator() == null ? explodedDenominator : indicator.getExplodedDenominator();
-            indicatorType = indicator.getIndicatorType() == null ? indicatorType : indicator.getIndicatorType();
-            legendSet = indicator.getLegendSet() == null ? legendSet : indicator.getLegendSet();
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                denominator = indicator.getDenominator();
+                denominatorDescription = indicator.getDenominatorDescription();
+                numerator = indicator.getNumerator();
+                numeratorDescription = indicator.getNumeratorDescription();
+                explodedNumerator = indicator.getExplodedNumerator();
+                explodedDenominator = indicator.getExplodedDenominator();
+                indicatorType = indicator.getIndicatorType();
+                legendSet = indicator.getLegendSet();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                denominator = indicator.getDenominator() == null ? denominator : indicator.getDenominator();
+                denominatorDescription = indicator.getDenominatorDescription() == null ? denominatorDescription : indicator.getDenominatorDescription();
+                numerator = indicator.getNumerator() == null ? numerator : indicator.getNumerator();
+                numeratorDescription = indicator.getNumeratorDescription() == null ? numeratorDescription : indicator.getNumeratorDescription();
+                explodedNumerator = indicator.getExplodedNumerator() == null ? explodedNumerator : indicator.getExplodedNumerator();
+                explodedDenominator = indicator.getExplodedDenominator() == null ? explodedDenominator : indicator.getExplodedDenominator();
+                indicatorType = indicator.getIndicatorType() == null ? indicatorType : indicator.getIndicatorType();
+                legendSet = indicator.getLegendSet() == null ? legendSet : indicator.getLegendSet();
+            }
 
             dataSets.clear();
             groups.clear();

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorGroup.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorGroup.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorGroup.java	2015-02-05 06:53:38 +0000
@@ -38,6 +38,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -178,15 +179,22 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             IndicatorGroup indicatorGroup = (IndicatorGroup) other;
 
-            groupSet = null;
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                groupSet = indicatorGroup.getGroupSet();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                groupSet = indicatorGroup.getGroupSet() == null ? groupSet : indicatorGroup.getGroupSet();
+            }
 
             removeAllIndicators();
 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorGroupSet.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorGroupSet.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorGroupSet.java	2015-02-05 06:53:38 +0000
@@ -37,6 +37,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.comparator.IdentifiableObjectNameComparator;
 import org.hisp.dhis.common.view.DetailedView;
@@ -234,16 +235,24 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             IndicatorGroupSet indicatorGroupSet = (IndicatorGroupSet) other;
 
-            compulsory = indicatorGroupSet.isCompulsory() == null ? compulsory : indicatorGroupSet.isCompulsory();
-            description = indicatorGroupSet.getDescription() == null ? description : indicatorGroupSet.getDescription();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                compulsory = indicatorGroupSet.isCompulsory();
+                description = indicatorGroupSet.getDescription();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                compulsory = indicatorGroupSet.isCompulsory() == null ? compulsory : indicatorGroupSet.isCompulsory();
+                description = indicatorGroupSet.getDescription() == null ? description : indicatorGroupSet.getDescription();
+            }
 
             removeAllIndicatorGroups();
 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorType.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorType.java	2015-01-21 09:30:45 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/indicator/IndicatorType.java	2015-02-05 06:53:38 +0000
@@ -31,6 +31,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 
@@ -103,14 +104,13 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             IndicatorType indicatorType = (IndicatorType) other;
-
             factor = indicatorType.getFactor();
             number = indicatorType.isNumber();
         }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/Map.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/Map.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/Map.java	2015-02-05 06:53:38 +0000
@@ -36,6 +36,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.DimensionalView;
@@ -139,18 +140,28 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             Map map = (Map) other;
 
-            user = map.getUser();
-            longitude = map.getLongitude();
-            latitude = map.getLatitude();
-            zoom = map.getZoom();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                user = map.getUser();
+                longitude = map.getLongitude();
+                latitude = map.getLatitude();
+                zoom = map.getZoom();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                user = map.getUser() == null ? user : map.getUser();
+                longitude = map.getLongitude() == null ? longitude : map.getLongitude();
+                latitude = map.getLatitude() == null ? latitude : map.getLatitude();
+                zoom = map.getZoom() == null ? zoom : map.getZoom();
+            }
 
             mapViews.clear();
             mapViews.addAll( map.getMapViews() );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLayer.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLayer.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLayer.java	2015-02-05 06:53:38 +0000
@@ -35,6 +35,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.schema.PropertyType;
@@ -193,22 +194,35 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             MapLayer mapLayer = (MapLayer) other;
 
-            type = mapLayer.getType() == null ? type : mapLayer.getType();
-            url = mapLayer.getUrl() == null ? url : mapLayer.getUrl();
-            layers = mapLayer.getLayers() == null ? layers : mapLayer.getLayers();
-            time = mapLayer.getTime() == null ? time : mapLayer.getTime();
-            fillColor = mapLayer.getFillColor() == null ? fillColor : mapLayer.getFillColor();
+            strokeWidth = mapLayer.getStrokeWidth();
             fillOpacity = mapLayer.getFillOpacity();
-            strokeColor = mapLayer.getStrokeColor() == null ? strokeColor : mapLayer.getStrokeColor();
-            strokeWidth = mapLayer.getStrokeWidth();
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                type = mapLayer.getType();
+                url = mapLayer.getUrl();
+                layers = mapLayer.getLayers();
+                time = mapLayer.getTime();
+                fillColor = mapLayer.getFillColor();
+                strokeColor = mapLayer.getStrokeColor();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                type = mapLayer.getType() == null ? type : mapLayer.getType();
+                url = mapLayer.getUrl() == null ? url : mapLayer.getUrl();
+                layers = mapLayer.getLayers() == null ? layers : mapLayer.getLayers();
+                time = mapLayer.getTime() == null ? time : mapLayer.getTime();
+                fillColor = mapLayer.getFillColor() == null ? fillColor : mapLayer.getFillColor();
+                strokeColor = mapLayer.getStrokeColor() == null ? strokeColor : mapLayer.getStrokeColor();
+            }
         }
     }
 }
\ No newline at end of file

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLegend.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLegend.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLegend.java	2015-02-05 06:53:38 +0000
@@ -35,6 +35,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 
@@ -129,18 +130,28 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             MapLegend mapLegend = (MapLegend) other;
 
-            startValue = mapLegend.getStartValue() == null ? startValue : mapLegend.getStartValue();
-            endValue = mapLegend.getEndValue() == null ? endValue : mapLegend.getEndValue();
-            color = mapLegend.getColor() == null ? color : mapLegend.getColor();
-            image = mapLegend.getImage() == null ? image : mapLegend.getImage();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                startValue = mapLegend.getStartValue();
+                endValue = mapLegend.getEndValue();
+                color = mapLegend.getColor();
+                image = mapLegend.getImage();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                startValue = mapLegend.getStartValue() == null ? startValue : mapLegend.getStartValue();
+                endValue = mapLegend.getEndValue() == null ? endValue : mapLegend.getEndValue();
+                color = mapLegend.getColor() == null ? color : mapLegend.getColor();
+                image = mapLegend.getImage() == null ? image : mapLegend.getImage();
+            }
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLegendSet.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLegendSet.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapLegendSet.java	2015-02-05 06:53:38 +0000
@@ -36,6 +36,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -110,15 +111,22 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             MapLegendSet mapLegendSet = (MapLegendSet) other;
 
-            symbolizer = mapLegendSet.getSymbolizer() == null ? symbolizer : mapLegendSet.getSymbolizer();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                symbolizer = mapLegendSet.getSymbolizer();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                symbolizer = mapLegendSet.getSymbolizer() == null ? symbolizer : mapLegendSet.getSymbolizer();
+            }
 
             removeAllMapLegends();
             mapLegends.addAll( mapLegendSet.getMapLegends() );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapView.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapView.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/mapping/MapView.java	2015-02-05 06:53:38 +0000
@@ -28,18 +28,17 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import static org.hisp.dhis.common.DimensionalObject.ORGUNIT_DIM_ID;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
 import org.hisp.dhis.common.BaseAnalyticalObject;
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DimensionalObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.NameableObjectUtils;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.DimensionalView;
@@ -51,19 +50,20 @@
 import org.hisp.dhis.schema.annotation.Property;
 import org.hisp.dhis.user.User;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonView;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import static org.hisp.dhis.common.DimensionalObject.ORGUNIT_DIM_ID;
 
 /**
  * For analytical data, organisation units and indicators/data elements are
  * dimensions, and period is filter.
- * 
+ *
  * @author Jan Henrik Overland
  */
-@JacksonXmlRootElement( localName = "mapView", namespace = DxfNamespaces.DXF_2_0)
+@JacksonXmlRootElement( localName = "mapView", namespace = DxfNamespaces.DXF_2_0 )
 public class MapView
     extends BaseAnalyticalObject
 {
@@ -74,13 +74,13 @@
     public static final String LAYER_THEMATIC2 = "thematic2";
     public static final String LAYER_THEMATIC3 = "thematic3";
     public static final String LAYER_THEMATIC4 = "thematic4";
-    
+
     public static final Integer METHOD_EQUAL_INTERVALS = 2;
     public static final Integer METHOD_EQUAL_COUNTS = 3;
 
-    public static final List<String> DATA_LAYERS = Arrays.asList( 
+    public static final List<String> DATA_LAYERS = Arrays.asList(
         LAYER_THEMATIC1, LAYER_THEMATIC2, LAYER_THEMATIC3, LAYER_THEMATIC4 );
-    
+
     private String layer;
 
     private Integer method;
@@ -102,17 +102,17 @@
     private OrganisationUnitGroupSet organisationUnitGroupSet;
 
     private Integer areaRadius;
-    
+
     private Boolean hidden;
-    
+
     private Boolean labels;
-    
+
     private String labelFontSize;
-    
+
     private String labelFontWeight;
-    
+
     private String labelFontStyle;
-    
+
     private String labelFontColor;
 
     // -------------------------------------------------------------------------
@@ -147,7 +147,7 @@
         this.organisationUnitsAtLevel = organisationUnitsAtLevel;
         this.organisationUnitsInGroups = organisationUnitsInGroups;
     }
-    
+
     @Override
     public void populateAnalyticalProperties()
     {
@@ -155,24 +155,24 @@
         rows.addAll( getDimensionalObjectList( DimensionalObject.ORGUNIT_DIM_ID ) );
         filters.addAll( getDimensionalObjectList( DimensionalObject.PERIOD_DIM_ID ) );
     }
-    
+
     public List<OrganisationUnit> getAllOrganisationUnits()
     {
         DimensionalObject object = getDimensionalObject( ORGUNIT_DIM_ID, relativePeriodDate, user, true, organisationUnitsAtLevel, organisationUnitsInGroups, format );
 
         return object != null ? NameableObjectUtils.asTypedList( object.getItems(), OrganisationUnit.class ) : null;
     }
-    
+
     public boolean hasLegendSet()
     {
         return legendSet != null;
     }
-    
+
     public boolean hasColors()
     {
         return colorLow != null && !colorLow.trim().isEmpty() && colorHigh != null && !colorHigh.trim().isEmpty();
     }
-    
+
     public boolean isDataLayer()
     {
         return DATA_LAYERS.contains( layer );
@@ -203,17 +203,17 @@
         {
             return dataSets.get( 0 ).getName();
         }
-        
+
         return uid;
     }
-    
+
     // -------------------------------------------------------------------------
     // Getters and setters
     // -------------------------------------------------------------------------
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public String getLayer()
     {
         return layer;
@@ -226,7 +226,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public Integer getMethod()
     {
         return method;
@@ -239,7 +239,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public Integer getClasses()
     {
         return classes;
@@ -252,7 +252,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     @Property( PropertyType.COLOR )
     public String getColorLow()
     {
@@ -266,7 +266,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     @Property( PropertyType.COLOR )
     public String getColorHigh()
     {
@@ -281,7 +281,7 @@
     @JsonProperty
     @JsonSerialize( as = BaseIdentifiableObject.class )
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public MapLegendSet getLegendSet()
     {
         return legendSet;
@@ -294,7 +294,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public Integer getRadiusLow()
     {
         return radiusLow;
@@ -307,7 +307,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public Integer getRadiusHigh()
     {
         return radiusHigh;
@@ -320,7 +320,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public Double getOpacity()
     {
         return opacity;
@@ -334,7 +334,7 @@
     @JsonProperty
     @JsonSerialize( as = BaseIdentifiableObject.class )
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public OrganisationUnitGroupSet getOrganisationUnitGroupSet()
     {
         return organisationUnitGroupSet;
@@ -347,7 +347,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public Integer getAreaRadius()
     {
         return areaRadius;
@@ -360,7 +360,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public Boolean getHidden()
     {
         return hidden;
@@ -373,7 +373,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public Boolean getLabels()
     {
         return labels;
@@ -386,7 +386,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public String getLabelFontSize()
     {
         return labelFontSize;
@@ -399,7 +399,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public String getLabelFontWeight()
     {
         return labelFontWeight;
@@ -412,7 +412,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public String getLabelFontStyle()
     {
         return labelFontStyle;
@@ -425,7 +425,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public String getLabelFontColor()
     {
         return labelFontColor;
@@ -438,7 +438,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public String getParentGraph()
     {
         return parentGraph;
@@ -451,7 +451,7 @@
 
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class } )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public int getParentLevel()
     {
         return parentLevel;
@@ -463,31 +463,54 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             MapView mapView = (MapView) other;
 
-            layer = mapView.getLayer();
-            method = mapView.getMethod();
-            classes = mapView.getClasses();
-            colorLow = mapView.getColorLow();
-            colorHigh = mapView.getColorHigh();
-            legendSet = mapView.getLegendSet();
-            radiusLow = mapView.getRadiusLow();
-            radiusHigh = mapView.getRadiusHigh();
-            opacity = mapView.getOpacity();
-            organisationUnitGroupSet = mapView.getOrganisationUnitGroupSet();
-            areaRadius = mapView.getAreaRadius();
-            hidden = mapView.getHidden();
-            labels = mapView.getLabels();
-            labelFontSize = mapView.getLabelFontSize();
-            labelFontWeight = mapView.getLabelFontWeight();
-            labelFontStyle = mapView.getLabelFontStyle();
-            labelFontColor = mapView.getLabelFontColor();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                layer = mapView.getLayer();
+                method = mapView.getMethod();
+                classes = mapView.getClasses();
+                colorLow = mapView.getColorLow();
+                colorHigh = mapView.getColorHigh();
+                legendSet = mapView.getLegendSet();
+                radiusLow = mapView.getRadiusLow();
+                radiusHigh = mapView.getRadiusHigh();
+                opacity = mapView.getOpacity();
+                organisationUnitGroupSet = mapView.getOrganisationUnitGroupSet();
+                areaRadius = mapView.getAreaRadius();
+                hidden = mapView.getHidden();
+                labels = mapView.getLabels();
+                labelFontSize = mapView.getLabelFontSize();
+                labelFontWeight = mapView.getLabelFontWeight();
+                labelFontStyle = mapView.getLabelFontStyle();
+                labelFontColor = mapView.getLabelFontColor();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                layer = mapView.getLayer() == null ? layer : mapView.getLayer();
+                method = mapView.getMethod() == null ? method : mapView.getMethod();
+                classes = mapView.getClasses() == null ? classes : mapView.getClasses();
+                colorLow = mapView.getColorLow() == null ? colorLow : mapView.getColorLow();
+                colorHigh = mapView.getColorHigh() == null ? colorHigh : mapView.getColorHigh();
+                legendSet = mapView.getLegendSet() == null ? legendSet : mapView.getLegendSet();
+                radiusLow = mapView.getRadiusLow() == null ? radiusLow : mapView.getRadiusLow();
+                radiusHigh = mapView.getRadiusHigh() == null ? radiusHigh : mapView.getRadiusHigh();
+                opacity = mapView.getOpacity() == null ? opacity : mapView.getOpacity();
+                organisationUnitGroupSet = mapView.getOrganisationUnitGroupSet() == null ? organisationUnitGroupSet : mapView.getOrganisationUnitGroupSet();
+                areaRadius = mapView.getAreaRadius() == null ? areaRadius : mapView.getAreaRadius();
+                hidden = mapView.getHidden() == null ? hidden : mapView.getHidden();
+                labels = mapView.getLabels() == null ? labels : mapView.getLabels();
+                labelFontSize = mapView.getLabelFontSize() == null ? labelFontSize : mapView.getLabelFontSize();
+                labelFontWeight = mapView.getLabelFontWeight() == null ? labelFontWeight : mapView.getLabelFontWeight();
+                labelFontStyle = mapView.getLabelFontStyle() == null ? labelFontStyle : mapView.getLabelFontStyle();
+                labelFontColor = mapView.getLabelFontColor() == null ? labelFontColor : mapView.getLabelFontColor();
+            }
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageConversation.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageConversation.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageConversation.java	2015-02-05 06:53:38 +0000
@@ -28,28 +28,28 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.schema.annotation.PropertyRange;
 import org.hisp.dhis.user.User;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonView;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
 
 /**
  * @author Lars Helge Overland
@@ -446,17 +446,26 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             MessageConversation messageConversation = (MessageConversation) other;
 
-            subject = messageConversation.getSubject() == null ? subject : messageConversation.getSubject();
-            lastSender = messageConversation.getLastSender() == null ? lastSender : messageConversation.getLastSender();
-            lastMessage = messageConversation.getLastMessage() == null ? lastMessage : messageConversation.getLastMessage();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                subject = messageConversation.getSubject();
+                lastSender = messageConversation.getLastSender();
+                lastMessage = messageConversation.getLastMessage();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                subject = messageConversation.getSubject() == null ? subject : messageConversation.getSubject();
+                lastSender = messageConversation.getLastSender() == null ? lastSender : messageConversation.getLastSender();
+                lastMessage = messageConversation.getLastMessage() == null ? lastMessage : messageConversation.getLastMessage();
+            }
 
             removeAllUserMessages();
             userMessages.addAll( messageConversation.getUserMessages() );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSet.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSet.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSet.java	2015-02-05 06:53:38 +0000
@@ -37,6 +37,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -115,29 +116,38 @@
         return matcher.find() && matcher.groupCount() > 0 ? matcher.group( 1 ).replaceAll( "_", " " ) : null;
     }
 
+    public List<String> getOptionValues()
+    {
+        List<String> result = new ArrayList<>();
+
+        for ( Option option : options )
+        {
+            result.add( option.getName() );
+        }
+
+        return result;
+    }
+
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             OptionSet optionSet = (OptionSet) other;
 
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                version = optionSet.getVersion();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                version = optionSet.getVersion() == null ? version : optionSet.getVersion();
+            }
+
             removeAllOptions();
             options.addAll( optionSet.getOptions() );
         }
     }
-
-    public List<String> getOptionValues()
-    {
-        List<String> result = new ArrayList<>();
-
-        for ( Option option : options )
-        {
-            result.add( option.getName() );
-        }
-
-        return result;
-    }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnit.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnit.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnit.java	2015-02-05 06:53:38 +0000
@@ -40,6 +40,7 @@
 import org.hisp.dhis.common.BaseNameableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.adapter.JacksonOrganisationUnitChildrenSerializer;
 import org.hisp.dhis.common.comparator.IdentifiableObjectNameComparator;
 import org.hisp.dhis.common.view.DetailedView;
@@ -1095,25 +1096,42 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             OrganisationUnit organisationUnit = (OrganisationUnit) other;
 
-            openingDate = organisationUnit.getOpeningDate() == null ? openingDate : organisationUnit.getOpeningDate();
-            closedDate = organisationUnit.getClosedDate() == null ? closedDate : organisationUnit.getClosedDate();
-            comment = organisationUnit.getComment() == null ? comment : organisationUnit.getComment();
-            featureType = organisationUnit.getFeatureType() == null ? featureType : organisationUnit.getFeatureType();
-            coordinates = organisationUnit.getCoordinates() == null ? coordinates : organisationUnit.getCoordinates();
-            url = organisationUnit.getUrl() == null ? url : organisationUnit.getUrl();
-            contactPerson = organisationUnit.getContactPerson() == null ? contactPerson : organisationUnit.getContactPerson();
-            address = organisationUnit.getAddress() == null ? address : organisationUnit.getAddress();
-            email = organisationUnit.getEmail() == null ? email : organisationUnit.getEmail();
-            phoneNumber = organisationUnit.getPhoneNumber() == null ? phoneNumber : organisationUnit.getPhoneNumber();
-            parent = organisationUnit.getParent();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                openingDate = organisationUnit.getOpeningDate();
+                closedDate = organisationUnit.getClosedDate();
+                comment = organisationUnit.getComment();
+                featureType = organisationUnit.getFeatureType();
+                coordinates = organisationUnit.getCoordinates();
+                url = organisationUnit.getUrl();
+                contactPerson = organisationUnit.getContactPerson();
+                address = organisationUnit.getAddress();
+                email = organisationUnit.getEmail();
+                phoneNumber = organisationUnit.getPhoneNumber();
+                parent = organisationUnit.getParent();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                openingDate = organisationUnit.getOpeningDate() == null ? openingDate : organisationUnit.getOpeningDate();
+                closedDate = organisationUnit.getClosedDate() == null ? closedDate : organisationUnit.getClosedDate();
+                comment = organisationUnit.getComment() == null ? comment : organisationUnit.getComment();
+                featureType = organisationUnit.getFeatureType() == null ? featureType : organisationUnit.getFeatureType();
+                coordinates = organisationUnit.getCoordinates() == null ? coordinates : organisationUnit.getCoordinates();
+                url = organisationUnit.getUrl() == null ? url : organisationUnit.getUrl();
+                contactPerson = organisationUnit.getContactPerson() == null ? contactPerson : organisationUnit.getContactPerson();
+                address = organisationUnit.getAddress() == null ? address : organisationUnit.getAddress();
+                email = organisationUnit.getEmail() == null ? email : organisationUnit.getEmail();
+                phoneNumber = organisationUnit.getPhoneNumber() == null ? phoneNumber : organisationUnit.getPhoneNumber();
+                parent = organisationUnit.getParent();
+            }
 
             groups.clear();
             users.clear();

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitGroup.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitGroup.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitGroup.java	2015-02-05 06:53:38 +0000
@@ -39,6 +39,7 @@
 import org.hisp.dhis.common.BaseNameableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -194,16 +195,24 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             OrganisationUnitGroup organisationUnitGroup = (OrganisationUnitGroup) other;
 
-            groupSet = null;
-            symbol = organisationUnitGroup.getSymbol();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                groupSet = organisationUnitGroup.getGroupSet();
+                symbol = organisationUnitGroup.getSymbol();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                groupSet = organisationUnitGroup.getGroupSet() == null ? groupSet : organisationUnitGroup.getGroupSet();
+                symbol = organisationUnitGroup.getSymbol() == null ? symbol : organisationUnitGroup.getSymbol();
+            }
 
             removeAllOrganisationUnits();
 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitGroupSet.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitGroupSet.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitGroupSet.java	2015-02-05 06:53:38 +0000
@@ -39,6 +39,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.adapter.JacksonOrganisationUnitGroupSymbolSerializer;
 import org.hisp.dhis.common.annotation.Scanned;
@@ -274,18 +275,26 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             OrganisationUnitGroupSet organisationUnitGroupSet = (OrganisationUnitGroupSet) other;
 
             compulsory = organisationUnitGroupSet.isCompulsory();
-            description = organisationUnitGroupSet.getDescription() == null ? description : organisationUnitGroupSet.getDescription();
             dataDimension = organisationUnitGroupSet.isDataDimension();
 
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                description = organisationUnitGroupSet.getDescription();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                description = organisationUnitGroupSet.getDescription() == null ? description : organisationUnitGroupSet.getDescription();
+            }
+
             removeAllOrganisationUnitGroups();
 
             for ( OrganisationUnitGroup organisationUnitGroup : organisationUnitGroupSet.getOrganisationUnitGroups() )

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitLevel.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitLevel.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitLevel.java	2015-02-05 06:53:38 +0000
@@ -34,6 +34,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.schema.annotation.PropertyRange;
 
 /**
@@ -128,14 +129,13 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             OrganisationUnitLevel organisationUnitLevel = (OrganisationUnitLevel) other;
-
             level = organisationUnitLevel.getLevel();
         }
     }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java	2015-02-05 06:53:38 +0000
@@ -38,6 +38,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -561,30 +562,52 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             Program program = (Program) other;
 
-            description = program.getDescription();
-            version = program.getVersion();
-            dateOfEnrollmentDescription = program.getDateOfEnrollmentDescription();
-            dateOfIncidentDescription = program.getDateOfIncidentDescription();
-            type = program.getType();
-            displayIncidentDate = program.getDisplayIncidentDate();
-            ignoreOverdueEvents = program.getIgnoreOverdueEvents();
-            onlyEnrollOnce = program.getOnlyEnrollOnce();
-            selectEnrollmentDatesInFuture = program.getSelectEnrollmentDatesInFuture();
-            selectIncidentDatesInFuture = program.getSelectIncidentDatesInFuture();
-            relationshipText = program.getRelationshipText();
-            relationshipType = program.getRelationshipType();
-            relationshipFromA = program.getRelationshipFromA();
-            relatedProgram = program.getRelatedProgram();
-            dataEntryMethod = program.getDataEntryMethod();
-            trackedEntity = program.getTrackedEntity();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                description = program.getDescription();
+                version = program.getVersion();
+                dateOfEnrollmentDescription = program.getDateOfEnrollmentDescription();
+                dateOfIncidentDescription = program.getDateOfIncidentDescription();
+                type = program.getType();
+                displayIncidentDate = program.getDisplayIncidentDate();
+                ignoreOverdueEvents = program.getIgnoreOverdueEvents();
+                onlyEnrollOnce = program.getOnlyEnrollOnce();
+                selectEnrollmentDatesInFuture = program.getSelectEnrollmentDatesInFuture();
+                selectIncidentDatesInFuture = program.getSelectIncidentDatesInFuture();
+                relationshipText = program.getRelationshipText();
+                relationshipType = program.getRelationshipType();
+                relationshipFromA = program.getRelationshipFromA();
+                relatedProgram = program.getRelatedProgram();
+                dataEntryMethod = program.getDataEntryMethod();
+                trackedEntity = program.getTrackedEntity();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                description = program.getDescription() == null ? description : program.getDescription();
+                version = program.getVersion() == null ? version : program.getVersion();
+                dateOfEnrollmentDescription = program.getDateOfEnrollmentDescription() == null ? dateOfEnrollmentDescription : program.getDateOfEnrollmentDescription();
+                dateOfIncidentDescription = program.getDateOfIncidentDescription() == null ? dateOfIncidentDescription : program.getDateOfIncidentDescription();
+                type = program.getType() == null ? type : program.getType();
+                displayIncidentDate = program.getDisplayIncidentDate() == null ? displayIncidentDate : program.getDisplayIncidentDate();
+                ignoreOverdueEvents = program.getIgnoreOverdueEvents() == null ? ignoreOverdueEvents : program.getIgnoreOverdueEvents();
+                onlyEnrollOnce = program.getOnlyEnrollOnce() == null ? onlyEnrollOnce : program.getOnlyEnrollOnce();
+                selectEnrollmentDatesInFuture = program.getSelectEnrollmentDatesInFuture() == null ? selectEnrollmentDatesInFuture : program.getSelectEnrollmentDatesInFuture();
+                selectIncidentDatesInFuture = program.getSelectIncidentDatesInFuture() == null ? selectIncidentDatesInFuture : program.getSelectIncidentDatesInFuture();
+                relationshipText = program.getRelationshipText() == null ? relationshipText : program.getRelationshipText();
+                relationshipType = program.getRelationshipType() == null ? relationshipType : program.getRelationshipType();
+                relationshipFromA = program.getRelationshipFromA() == null ? relationshipFromA : program.getRelationshipFromA();
+                relatedProgram = program.getRelatedProgram() == null ? relatedProgram : program.getRelatedProgram();
+                dataEntryMethod = program.getDataEntryMethod() == null ? dataEntryMethod : program.getDataEntryMethod();
+                trackedEntity = program.getTrackedEntity() == null ? trackedEntity : program.getTrackedEntity();
+            }
 
             organisationUnits.clear();
             organisationUnits.addAll( program.getOrganisationUnits() );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramIndicator.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramIndicator.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramIndicator.java	2015-02-05 06:53:38 +0000
@@ -36,6 +36,8 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.BaseNameableObject;
 import org.hisp.dhis.common.DxfNamespaces;
+import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 
@@ -140,4 +142,30 @@
     {
         this.program = program;
     }
+
+    @Override
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
+    {
+        super.mergeWith( other, strategy );
+
+        if ( other.getClass().isInstance( this ) )
+        {
+            ProgramIndicator programIndicator = (ProgramIndicator) other;
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                valueType = programIndicator.getValueType();
+                expression = programIndicator.getExpression();
+                rootDate = programIndicator.getRootDate();
+                program = programIndicator.getProgram();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                valueType = programIndicator.getValueType() == null ? valueType : programIndicator.getValueType();
+                expression = programIndicator.getExpression() == null ? expression : programIndicator.getExpression();
+                rootDate = programIndicator.getRootDate() == null ? rootDate : programIndicator.getRootDate();
+                program = programIndicator.getProgram() == null ? program : programIndicator.getProgram();
+            }
+        }
+    }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStage.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStage.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStage.java	2015-02-05 06:53:38 +0000
@@ -34,10 +34,10 @@
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
-
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -77,7 +77,7 @@
     private Program program;
 
     private Set<ProgramStageDataElement> programStageDataElements = new HashSet<>();
-    
+
     private List<ProgramIndicator> programIndicators = new ArrayList<>();
 
     @Scanned
@@ -100,7 +100,7 @@
     private Boolean captureCoordinates = false;
 
     private Boolean blockEntryForm = false;
-    
+
     private Boolean preGenerateUID = false;
 
     /**
@@ -116,7 +116,7 @@
     private Boolean openAfterEnrollment = false;
 
     private String reportDateToUse;
-    
+
     private Integer sortOrder;
 
     // -------------------------------------------------------------------------
@@ -435,7 +435,7 @@
     @JsonView( { DetailedView.class, ExportView.class } )
     @JacksonXmlElementWrapper( localName = "programIndicators", namespace = DxfNamespaces.DXF_2_0 )
     @JacksonXmlProperty( localName = "programIndicator", namespace = DxfNamespaces.DXF_2_0 )
-     public List<ProgramIndicator> getProgramIndicators()
+    public List<ProgramIndicator> getProgramIndicators()
     {
         return programIndicators;
     }
@@ -457,7 +457,7 @@
     {
         this.preGenerateUID = preGenerateUID;
     }
-    
+
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class } )
     @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
@@ -472,32 +472,55 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             ProgramStage programStage = (ProgramStage) other;
 
-            description = programStage.getDescription();
             minDaysFromStart = programStage.getMinDaysFromStart();
-            irregular = programStage.getIrregular();
-            program = programStage.getProgram();
-            dataEntryForm = programStage.getDataEntryForm();
-            standardInterval = programStage.getStandardInterval();
-            reportDateDescription = programStage.getReportDateDescription();
             autoGenerateEvent = programStage.isAutoGenerated();
-            validCompleteOnly = programStage.getValidCompleteOnly();
-            displayGenerateEventBox = programStage.getDisplayGenerateEventBox();
-            captureCoordinates = programStage.getCaptureCoordinates();
-            blockEntryForm = programStage.getBlockEntryForm();
-            remindCompleted = programStage.getRemindCompleted();
-            generatedByEnrollmentDate = programStage.getGeneratedByEnrollmentDate();
-            allowGenerateNextVisit = programStage.getAllowGenerateNextVisit();
-            openAfterEnrollment = programStage.getOpenAfterEnrollment();
-            reportDateToUse = programStage.getReportDateToUse();
-            preGenerateUID = programStage.getPreGenerateUID();
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                description = programStage.getDescription();
+                irregular = programStage.getIrregular();
+                program = programStage.getProgram();
+                dataEntryForm = programStage.getDataEntryForm();
+                standardInterval = programStage.getStandardInterval();
+                reportDateDescription = programStage.getReportDateDescription();
+                validCompleteOnly = programStage.getValidCompleteOnly();
+                displayGenerateEventBox = programStage.getDisplayGenerateEventBox();
+                captureCoordinates = programStage.getCaptureCoordinates();
+                blockEntryForm = programStage.getBlockEntryForm();
+                remindCompleted = programStage.getRemindCompleted();
+                generatedByEnrollmentDate = programStage.getGeneratedByEnrollmentDate();
+                allowGenerateNextVisit = programStage.getAllowGenerateNextVisit();
+                openAfterEnrollment = programStage.getOpenAfterEnrollment();
+                reportDateToUse = programStage.getReportDateToUse();
+                preGenerateUID = programStage.getPreGenerateUID();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                description = programStage.getDescription() == null ? description : programStage.getDescription();
+                irregular = programStage.getIrregular() == null ? irregular : programStage.getIrregular();
+                program = programStage.getProgram() == null ? program : programStage.getProgram();
+                dataEntryForm = programStage.getDataEntryForm() == null ? dataEntryForm : programStage.getDataEntryForm();
+                standardInterval = programStage.getStandardInterval() == null ? standardInterval : programStage.getStandardInterval();
+                reportDateDescription = programStage.getReportDateDescription() == null ? reportDateDescription : programStage.getReportDateDescription();
+                validCompleteOnly = programStage.getValidCompleteOnly() == null ? validCompleteOnly : programStage.getValidCompleteOnly();
+                displayGenerateEventBox = programStage.getDisplayGenerateEventBox() == null ? displayGenerateEventBox : programStage.getDisplayGenerateEventBox();
+                captureCoordinates = programStage.getCaptureCoordinates() == null ? captureCoordinates : programStage.getCaptureCoordinates();
+                blockEntryForm = programStage.getBlockEntryForm() == null ? blockEntryForm : programStage.getBlockEntryForm();
+                remindCompleted = programStage.getRemindCompleted() == null ? remindCompleted : programStage.getRemindCompleted();
+                generatedByEnrollmentDate = programStage.getGeneratedByEnrollmentDate() == null ? generatedByEnrollmentDate : programStage.getGeneratedByEnrollmentDate();
+                allowGenerateNextVisit = programStage.getAllowGenerateNextVisit() == null ? allowGenerateNextVisit : programStage.getAllowGenerateNextVisit();
+                openAfterEnrollment = programStage.getOpenAfterEnrollment() == null ? openAfterEnrollment : programStage.getOpenAfterEnrollment();
+                reportDateToUse = programStage.getReportDateToUse() == null ? reportDateToUse : programStage.getReportDateToUse();
+                preGenerateUID = programStage.getPreGenerateUID() == null ? preGenerateUID : programStage.getPreGenerateUID();
+            }
 
             programStageDataElements.clear();
             programStageDataElements.addAll( programStage.getProgramStageDataElements() );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStageSection.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStageSection.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStageSection.java	2015-02-05 06:53:38 +0000
@@ -37,6 +37,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 
@@ -46,7 +47,7 @@
 /**
  * @author Chau Thu Tran
  */
-@JacksonXmlRootElement(localName = "programStageSection", namespace = DxfNamespaces.DXF_2_0)
+@JacksonXmlRootElement( localName = "programStageSection", namespace = DxfNamespaces.DXF_2_0 )
 public class ProgramStageSection
     extends BaseIdentifiableObject
 {
@@ -128,16 +129,24 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             ProgramStageSection programStageSection = (ProgramStageSection) other;
 
-            programStage = programStageSection.getProgramStage();
-            sortOrder = programStageSection.getSortOrder();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                programStage = programStageSection.getProgramStage();
+                sortOrder = programStageSection.getSortOrder();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                programStage = programStageSection.getProgramStage() == null ? programStage : programStageSection.getProgramStage();
+                sortOrder = programStageSection.getSortOrder() == null ? sortOrder : programStageSection.getSortOrder();
+            }
 
             programStageDataElements.clear();
             programStageDataElements.addAll( programStageSection.getProgramStageDataElements() );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramValidation.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramValidation.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramValidation.java	2015-02-05 06:53:38 +0000
@@ -36,6 +36,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.expression.Operator;
@@ -144,18 +145,28 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             ProgramValidation programValidation = (ProgramValidation) other;
 
-            leftSide = programValidation.getLeftSide();
-            operator = programValidation.getOperator();
-            rightSide = programValidation.getRightSide();
-            program = programValidation.getProgram();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                leftSide = programValidation.getLeftSide();
+                operator = programValidation.getOperator();
+                rightSide = programValidation.getRightSide();
+                program = programValidation.getProgram();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                leftSide = programValidation.getLeftSide() == null ? leftSide : programValidation.getLeftSide();
+                rightSide = programValidation.getRightSide() == null ? rightSide : programValidation.getRightSide();
+                operator = programValidation.getOperator() == null ? operator : programValidation.getOperator();
+                program = programValidation.getProgram() == null ? program : programValidation.getProgram();
+            }
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/relationship/RelationshipType.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/relationship/RelationshipType.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/relationship/RelationshipType.java	2015-02-05 06:53:38 +0000
@@ -35,6 +35,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.schema.annotation.PropertyRange;
@@ -42,7 +43,7 @@
 /**
  * @author Abyot Asalefew
  */
-@JacksonXmlRootElement(localName = "relationshipType", namespace = DxfNamespaces.DXF_2_0)
+@JacksonXmlRootElement( localName = "relationshipType", namespace = DxfNamespaces.DXF_2_0 )
 public class RelationshipType
     extends BaseIdentifiableObject
 {
@@ -76,8 +77,8 @@
     // -------------------------------------------------------------------------
 
     @JsonProperty
-    @JsonView({ DetailedView.class, ExportView.class })
-    @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0)
+    @JsonView( { DetailedView.class, ExportView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     @PropertyRange( min = 2 )
     public String getaIsToB()
     {
@@ -90,8 +91,8 @@
     }
 
     @JsonProperty
-    @JsonView({ DetailedView.class, ExportView.class })
-    @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0)
+    @JsonView( { DetailedView.class, ExportView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     @PropertyRange( min = 2 )
     public String getbIsToA()
     {
@@ -113,16 +114,24 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             RelationshipType relationshipType = (RelationshipType) other;
 
-            this.aIsToB = relationshipType.getaIsToB();
-            this.bIsToA = relationshipType.getbIsToA();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                aIsToB = relationshipType.getaIsToB();
+                bIsToA = relationshipType.getbIsToA();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                aIsToB = relationshipType.getaIsToB() == null ? aIsToB : relationshipType.getaIsToB();
+                bIsToA = relationshipType.getbIsToA() == null ? bIsToA : relationshipType.getbIsToA();
+            }
         }
     }
 }
\ No newline at end of file

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/report/Report.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/report/Report.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/report/Report.java	2015-02-05 06:53:38 +0000
@@ -36,6 +36,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.period.RelativePeriods;
@@ -207,16 +208,24 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             Report report = (Report) other;
 
-            designContent = report.getDesignContent() == null ? designContent : report.getDesignContent();
-            reportTable = report.getReportTable() == null ? reportTable : report.getReportTable();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                designContent = report.getDesignContent();
+                reportTable = report.getReportTable();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                designContent = report.getDesignContent() == null ? designContent : report.getDesignContent();
+                reportTable = report.getReportTable() == null ? reportTable : report.getReportTable();
+            }
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java	2015-02-05 06:53:38 +0000
@@ -44,6 +44,7 @@
 import org.hisp.dhis.common.GridHeader;
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObjectUtils;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.DimensionalView;
@@ -1078,9 +1079,9 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
@@ -1088,21 +1089,33 @@
 
             regression = reportTable.isRegression();
             cumulative = reportTable.isCumulative();
-            reportParams = reportTable.getReportParams() == null ? reportParams : reportTable.getReportParams();
-            sortOrder = reportTable.getSortOrder();
-            topLimit = reportTable.getTopLimit();
             rowTotals = reportTable.isRowTotals();
             colTotals = reportTable.isColTotals();
             rowSubTotals = reportTable.isRowSubTotals();
             colSubTotals = reportTable.isColSubTotals();
             hideEmptyRows = reportTable.isHideEmptyRows();
             showHierarchy = reportTable.isShowHierarchy();
-            aggregationType = reportTable.getAggregationType();
-            displayDensity = reportTable.getDisplayDensity();
-            fontSize = reportTable.getFontSize();
-            legendSet = reportTable.getLegendSet();
             showDimensionLabels = reportTable.isShowDimensionLabels();
             hideEmptyRows = reportTable.isHideEmptyRows();
+            topLimit = reportTable.getTopLimit();
+            sortOrder = reportTable.getSortOrder();
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                reportParams = reportTable.getReportParams();
+                aggregationType = reportTable.getAggregationType();
+                displayDensity = reportTable.getDisplayDensity();
+                fontSize = reportTable.getFontSize();
+                legendSet = reportTable.getLegendSet();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                reportParams = reportTable.getReportParams() == null ? reportParams : reportTable.getReportParams();
+                aggregationType = reportTable.getAggregationType() == null ? aggregationType : reportTable.getAggregationType();
+                displayDensity = reportTable.getDisplayDensity() == null ? displayDensity : reportTable.getDisplayDensity();
+                fontSize = reportTable.getFontSize() == null ? fontSize : reportTable.getFontSize();
+                legendSet = reportTable.getLegendSet() == null ? legendSet : reportTable.getLegendSet();
+            }
 
             columnDimensions.clear();
             columnDimensions.addAll( reportTable.getColumnDimensions() );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/sqlview/SqlView.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/sqlview/SqlView.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/sqlview/SqlView.java	2015-02-05 06:53:38 +0000
@@ -36,6 +36,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.schema.annotation.PropertyRange;
@@ -158,16 +159,24 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             SqlView sqlView = (SqlView) other;
 
-            description = sqlView.getDescription() == null ? description : sqlView.getDescription();
-            sqlQuery = sqlView.getSqlQuery() == null ? sqlQuery : sqlView.getSqlQuery();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                description = sqlView.getDescription();
+                sqlQuery = sqlView.getSqlQuery();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                description = sqlView.getDescription() == null ? description : sqlView.getDescription();
+                sqlQuery = sqlView.getSqlQuery() == null ? sqlQuery : sqlView.getSqlQuery();
+            }
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttribute.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttribute.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttribute.java	2015-02-05 06:53:38 +0000
@@ -37,6 +37,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.common.view.WithoutOrganisationUnitsView;
@@ -340,36 +341,6 @@
         this.confidential = confidential;
     }
 
-    // -------------------------------------------------------------------------
-    // Static methods
-    // -------------------------------------------------------------------------
-
-    @Override
-    public void mergeWith( IdentifiableObject other )
-    {
-        super.mergeWith( other );
-
-        if ( other.getClass().isInstance( this ) )
-        {
-            TrackedEntityAttribute trackedEntityAttribute = (TrackedEntityAttribute) other;
-
-            description = trackedEntityAttribute.getDescription();
-            valueType = trackedEntityAttribute.getValueType();
-            inherit = trackedEntityAttribute.getInherit();
-            attributeGroup = trackedEntityAttribute.getAttributeGroup();
-
-            expression = trackedEntityAttribute.getExpression();
-            displayOnVisitSchedule = trackedEntityAttribute.getDisplayOnVisitSchedule();
-            sortOrderInVisitSchedule = trackedEntityAttribute.getSortOrderInVisitSchedule();
-            displayInListNoProgram = trackedEntityAttribute.getDisplayInListNoProgram();
-            sortOrderInListNoProgram = trackedEntityAttribute.getSortOrderInListNoProgram();
-            unique = trackedEntityAttribute.isUnique();
-            orgunitScope = trackedEntityAttribute.getOrgunitScope();
-            programScope = trackedEntityAttribute.getProgramScope();
-            confidential = trackedEntityAttribute.getConfidential();
-        }
-    }
-
     public Boolean isValidOptionValue( String value )
     {
         for ( Option option : this.getOptionSet().getOptions() )
@@ -382,4 +353,48 @@
 
         return false;
     }
+
+    @Override
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
+    {
+        super.mergeWith( other, strategy );
+
+        if ( other.getClass().isInstance( this ) )
+        {
+            TrackedEntityAttribute trackedEntityAttribute = (TrackedEntityAttribute) other;
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                description = trackedEntityAttribute.getDescription();
+                valueType = trackedEntityAttribute.getValueType();
+                inherit = trackedEntityAttribute.getInherit();
+                attributeGroup = trackedEntityAttribute.getAttributeGroup();
+                expression = trackedEntityAttribute.getExpression();
+                displayOnVisitSchedule = trackedEntityAttribute.getDisplayOnVisitSchedule();
+                sortOrderInVisitSchedule = trackedEntityAttribute.getSortOrderInVisitSchedule();
+                displayInListNoProgram = trackedEntityAttribute.getDisplayInListNoProgram();
+                sortOrderInListNoProgram = trackedEntityAttribute.getSortOrderInListNoProgram();
+                unique = trackedEntityAttribute.isUnique();
+                orgunitScope = trackedEntityAttribute.getOrgunitScope();
+                programScope = trackedEntityAttribute.getProgramScope();
+                confidential = trackedEntityAttribute.getConfidential();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                description = trackedEntityAttribute.getDescription() == null ? description : trackedEntityAttribute.getDescription();
+                valueType = trackedEntityAttribute.getValueType() == null ? valueType : trackedEntityAttribute.getValueType();
+                inherit = trackedEntityAttribute.getInherit() == null ? inherit : trackedEntityAttribute.getInherit();
+                attributeGroup = trackedEntityAttribute.getAttributeGroup() == null ? attributeGroup : trackedEntityAttribute.getAttributeGroup();
+                expression = trackedEntityAttribute.getExpression() == null ? expression : trackedEntityAttribute.getExpression();
+                displayOnVisitSchedule = trackedEntityAttribute.getDisplayOnVisitSchedule() == null ? displayOnVisitSchedule : trackedEntityAttribute.getDisplayOnVisitSchedule();
+                sortOrderInVisitSchedule = trackedEntityAttribute.getSortOrderInVisitSchedule() == null ? sortOrderInVisitSchedule : trackedEntityAttribute.getSortOrderInVisitSchedule();
+                displayInListNoProgram = trackedEntityAttribute.getDisplayInListNoProgram() == null ? displayInListNoProgram : trackedEntityAttribute.getDisplayInListNoProgram();
+                sortOrderInListNoProgram = trackedEntityAttribute.getSortOrderInListNoProgram() == null ? sortOrderInListNoProgram : trackedEntityAttribute.getSortOrderInListNoProgram();
+                unique = trackedEntityAttribute.isUnique() == null ? unique : trackedEntityAttribute.isUnique();
+                orgunitScope = trackedEntityAttribute.getOrgunitScope() == null ? orgunitScope : trackedEntityAttribute.getOrgunitScope();
+                programScope = trackedEntityAttribute.getProgramScope() == null ? programScope : trackedEntityAttribute.getProgramScope();
+                confidential = trackedEntityAttribute.getConfidential() == null ? confidential : trackedEntityAttribute.getConfidential();
+            }
+        }
+    }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeGroup.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeGroup.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeGroup.java	2015-02-05 06:53:38 +0000
@@ -37,6 +37,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -116,15 +117,22 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             TrackedEntityAttributeGroup trackedEntityAttributeGroup = (TrackedEntityAttributeGroup) other;
 
-            description = trackedEntityAttributeGroup.getDescription();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                description = trackedEntityAttributeGroup.getDescription();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                description = trackedEntityAttributeGroup.getDescription() == null ? description : trackedEntityAttributeGroup.getDescription();
+            }
 
             attributes.clear();
             attributes.addAll( trackedEntityAttributeGroup.getAttributes() );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityForm.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityForm.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityForm.java	2015-02-05 06:53:38 +0000
@@ -35,6 +35,8 @@
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
+import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.dataentryform.DataEntryForm;
@@ -131,4 +133,26 @@
 
         return Objects.equals( this.program, other.program ) && Objects.equals( this.dataEntryForm, other.dataEntryForm );
     }
+
+    @Override
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
+    {
+        super.mergeWith( other, strategy );
+
+        if ( other.getClass().isInstance( this ) )
+        {
+            TrackedEntityForm trackedEntityForm = (TrackedEntityForm) other;
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                program = trackedEntityForm.getProgram();
+                dataEntryForm = trackedEntityForm.getDataEntryForm();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                program = trackedEntityForm.getProgram() == null ? program : trackedEntityForm.getProgram();
+                dataEntryForm = trackedEntityForm.getDataEntryForm() == null ? dataEntryForm : trackedEntityForm.getDataEntryForm();
+            }
+        }
+    }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceReminder.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceReminder.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceReminder.java	2015-02-05 06:53:38 +0000
@@ -28,22 +28,22 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.regex.Pattern;
-
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonView;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
-
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
 import org.hisp.dhis.common.view.WithoutOrganisationUnitsView;
 import org.hisp.dhis.user.UserGroup;
 
+import java.util.regex.Pattern;
+
 /**
  * @author Chau Thu Tran
  */
@@ -54,9 +54,9 @@
     private static final long serialVersionUID = 3101502417481903219L;
 
     public static final String ATTRIBUTE = "attributeid";
-     
+
     public static final Pattern ATTRIBUTE_PATTERN = Pattern.compile( "\\{(" + ATTRIBUTE + ")=(\\w+)\\}" );
-    
+
     public static final String DUE_DATE_TO_COMPARE = "duedate";
 
     public static final String ENROLLEMENT_DATE_TO_COMPARE = "enrollmentdate";
@@ -244,21 +244,34 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             TrackedEntityInstanceReminder trackedEntityInstanceReminder = (TrackedEntityInstanceReminder) other;
 
-            daysAllowedSendMessage = trackedEntityInstanceReminder.getDaysAllowedSendMessage();
-            templateMessage = trackedEntityInstanceReminder.getTemplateMessage();
-            dateToCompare = trackedEntityInstanceReminder.getDateToCompare();
-            sendTo = trackedEntityInstanceReminder.getSendTo();
-            whenToSend = trackedEntityInstanceReminder.getWhenToSend();
-            messageType = trackedEntityInstanceReminder.getMessageType();
-            userGroup = trackedEntityInstanceReminder.getUserGroup();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                daysAllowedSendMessage = trackedEntityInstanceReminder.getDaysAllowedSendMessage();
+                templateMessage = trackedEntityInstanceReminder.getTemplateMessage();
+                dateToCompare = trackedEntityInstanceReminder.getDateToCompare();
+                sendTo = trackedEntityInstanceReminder.getSendTo();
+                whenToSend = trackedEntityInstanceReminder.getWhenToSend();
+                messageType = trackedEntityInstanceReminder.getMessageType();
+                userGroup = trackedEntityInstanceReminder.getUserGroup();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                daysAllowedSendMessage = trackedEntityInstanceReminder.getDaysAllowedSendMessage() == null ? daysAllowedSendMessage : trackedEntityInstanceReminder.getDaysAllowedSendMessage();
+                templateMessage = trackedEntityInstanceReminder.getTemplateMessage() == null ? templateMessage : trackedEntityInstanceReminder.getTemplateMessage();
+                dateToCompare = trackedEntityInstanceReminder.getDateToCompare() == null ? dateToCompare : trackedEntityInstanceReminder.getDateToCompare();
+                sendTo = trackedEntityInstanceReminder.getSendTo() == null ? sendTo : trackedEntityInstanceReminder.getSendTo();
+                whenToSend = trackedEntityInstanceReminder.getWhenToSend() == null ? whenToSend : trackedEntityInstanceReminder.getWhenToSend();
+                messageType = trackedEntityInstanceReminder.getMessageType() == null ? messageType : trackedEntityInstanceReminder.getMessageType();
+                userGroup = trackedEntityInstanceReminder.getUserGroup() == null ? userGroup : trackedEntityInstanceReminder.getUserGroup();
+            }
         }
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/User.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/User.java	2015-01-26 13:32:36 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/User.java	2015-02-05 06:53:38 +0000
@@ -40,6 +40,7 @@
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObjectUtils;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -248,19 +249,19 @@
     {
         return userCredentials != null && userCredentials.isSuper();
     }
-    
+
     public Set<UserGroup> getManagedGroups()
     {
         Set<UserGroup> managedGroups = new HashSet<>();
-        
+
         for ( UserGroup group : groups )
         {
             managedGroups.addAll( group.getManagedGroups() );
         }
-        
+
         return managedGroups;
     }
-    
+
     public boolean hasManagedGroups()
     {
         for ( UserGroup group : groups )
@@ -270,13 +271,13 @@
                 return true;
             }
         }
-        
+
         return false;
     }
-    
+
     /**
      * Indicates whether this user can manage the given user group.
-     * 
+     *
      * @param userGroup the user group to test.
      * @return true if the given user group can be managed by this user, false if not.
      */
@@ -284,10 +285,10 @@
     {
         return userGroup != null && CollectionUtils.containsAny( groups, userGroup.getManagedByGroups() );
     }
-    
+
     /**
      * Indicates whether this user can manage the given user.
-     * 
+     *
      * @param user the user to test.
      * @return true if the given user can be managed by this user, false if not.
      */
@@ -297,7 +298,7 @@
         {
             return false;
         }
-        
+
         for ( UserGroup group : user.getGroups() )
         {
             if ( canManage( group ) )
@@ -305,13 +306,13 @@
                 return true;
             }
         }
-        
+
         return false;
     }
-    
+
     /**
      * Indicates whether this user is managed by the given user group.
-     * 
+     *
      * @param userGroup the user group to test.
      * @return true if the given user group is managed by this user, false if not.
      */
@@ -322,7 +323,7 @@
 
     /**
      * Indicates whether this user is managed by the given user.
-     * 
+     *
      * @param userGroup the user  to test.
      * @return true if the given user is managed by this user, false if not.
      */
@@ -332,7 +333,7 @@
         {
             return false;
         }
-        
+
         for ( UserGroup group : user.getGroups() )
         {
             if ( isManagedBy( group ) )
@@ -340,7 +341,7 @@
                 return true;
             }
         }
-        
+
         return false;
     }
 
@@ -621,37 +622,57 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             User user = (User) other;
 
-            surname = user.getSurname();
-            firstName = user.getFirstName();
-            email = user.getEmail();
-            phoneNumber = user.getPhoneNumber();
-            jobTitle = user.getJobTitle();
-            introduction = user.getIntroduction();
-            gender = user.getGender();
-            birthday = user.getBirthday();
-            nationality = user.getNationality();
-            employer = user.getEmployer();
-            education = user.getEducation();
-            interests = user.getInterests();
-            languages = user.getLanguages();
-            lastCheckedInterpretations = user.getLastCheckedInterpretations();
-
-            userCredentials = user.getUserCredentials() == null ? userCredentials : user.getUserCredentials();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                surname = user.getSurname();
+                firstName = user.getFirstName();
+                email = user.getEmail();
+                phoneNumber = user.getPhoneNumber();
+                jobTitle = user.getJobTitle();
+                introduction = user.getIntroduction();
+                gender = user.getGender();
+                birthday = user.getBirthday();
+                nationality = user.getNationality();
+                employer = user.getEmployer();
+                education = user.getEducation();
+                interests = user.getInterests();
+                languages = user.getLanguages();
+                lastCheckedInterpretations = user.getLastCheckedInterpretations();
+                userCredentials = user.getUserCredentials();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                surname = user.getSurname() == null ? surname : user.getSurname();
+                firstName = user.getFirstName() == null ? firstName : user.getFirstName();
+                email = user.getEmail() == null ? email : user.getEmail();
+                phoneNumber = user.getPhoneNumber() == null ? phoneNumber : user.getPhoneNumber();
+                jobTitle = user.getJobTitle() == null ? jobTitle : user.getJobTitle();
+                introduction = user.getIntroduction() == null ? introduction : user.getIntroduction();
+                gender = user.getGender() == null ? gender : user.getGender();
+                birthday = user.getBirthday() == null ? birthday : user.getBirthday();
+                nationality = user.getNationality() == null ? nationality : user.getNationality();
+                employer = user.getEmployer() == null ? employer : user.getEmployer();
+                education = user.getEducation() == null ? education : user.getEducation();
+                interests = user.getInterests() == null ? interests : user.getInterests();
+                languages = user.getLanguages() == null ? languages : user.getLanguages();
+                lastCheckedInterpretations = user.getLastCheckedInterpretations() == null ? lastCheckedInterpretations : user.getLastCheckedInterpretations();
+                userCredentials = user.getUserCredentials() == null ? userCredentials : user.getUserCredentials();
+            }
 
             attributeValues.clear();
             attributeValues.addAll( user.getAttributeValues() );
 
             organisationUnits.clear();
             organisationUnits.addAll( user.getOrganisationUnits() );
-            
+
             dataViewOrganisationUnits.clear();
             dataViewOrganisationUnits.addAll( user.getDataViewOrganisationUnits() );
         }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserAuthorityGroup.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserAuthorityGroup.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserAuthorityGroup.java	2015-02-05 06:53:38 +0000
@@ -39,6 +39,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -192,16 +193,33 @@
         this.dataSets = dataSets;
     }
 
+    public void removeAllDataSets()
+    {
+        dataSets.clear();
+    }
+
+    private void removeAllAuthorities()
+    {
+        authorities.clear();
+    }
+
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             UserAuthorityGroup userAuthorityGroup = (UserAuthorityGroup) other;
 
-            description = userAuthorityGroup.getDescription() == null ? description : userAuthorityGroup.getDescription();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                description = userAuthorityGroup.getDescription();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                description = userAuthorityGroup.getDescription() == null ? description : userAuthorityGroup.getDescription();
+            }
 
             removeAllAuthorities();
             authorities.addAll( ((UserAuthorityGroup) other).getAuthorities() );
@@ -210,14 +228,4 @@
             dataSets.addAll( userAuthorityGroup.getDataSets() );
         }
     }
-
-    public void removeAllDataSets()
-    {
-        dataSets.clear();
-    }
-
-    private void removeAllAuthorities()
-    {
-        authorities.clear();
-    }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserCredentials.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserCredentials.java	2015-01-26 13:32:36 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserCredentials.java	2015-02-05 06:53:38 +0000
@@ -40,6 +40,7 @@
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObjectUtils;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -188,7 +189,7 @@
 
         return authorities;
     }
-    
+
     /**
      * Indicates whether this user credentials has at least one authority through
      * its user authority groups.
@@ -202,7 +203,7 @@
                 return true;
             }
         }
-        
+
         return false;
     }
 
@@ -424,7 +425,7 @@
     {
         return userAuthorityGroups != null && !userAuthorityGroups.isEmpty();
     }
-    
+
     /**
      * Indicates whether this user credentials has dimension constraints.
      */
@@ -668,19 +669,33 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             UserCredentials userCredentials = (UserCredentials) other;
 
             username = userCredentials.getUsername();
-            openId = userCredentials.getOpenId();
             password = StringUtils.isEmpty( userCredentials.getPassword() ) ? password : userCredentials.getPassword();
             passwordLastUpdated = userCredentials.getPasswordLastUpdated();
 
+            lastLogin = userCredentials.getLastLogin();
+            restoreToken = userCredentials.getRestoreToken();
+            restoreExpiry = userCredentials.getRestoreExpiry();
+            selfRegistered = userCredentials.isSelfRegistered();
+            disabled = userCredentials.isDisabled();
+
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                openId = userCredentials.getOpenId();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                openId = userCredentials.getOpenId() == null ? openId : userCredentials.getOpenId();
+            }
+
             userAuthorityGroups.clear();
             userAuthorityGroups.addAll( userCredentials.getUserAuthorityGroups() );
 
@@ -689,12 +704,6 @@
 
             cogsDimensionConstraints.clear();
             cogsDimensionConstraints.addAll( userCredentials.getCogsDimensionConstraints() );
-
-            lastLogin = userCredentials.getLastLogin();
-            restoreToken = userCredentials.getRestoreToken();
-            restoreExpiry = userCredentials.getRestoreExpiry();
-            selfRegistered = userCredentials.isSelfRegistered();
-            disabled = userCredentials.isDisabled();
         }
     }
 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserGroup.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserGroup.java	2015-02-01 23:02:22 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserGroup.java	2015-02-05 06:53:38 +0000
@@ -39,6 +39,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -253,9 +254,9 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRule.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRule.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRule.java	2015-02-05 06:53:38 +0000
@@ -38,6 +38,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.adapter.JacksonPeriodTypeDeserializer;
 import org.hisp.dhis.common.adapter.JacksonPeriodTypeSerializer;
 import org.hisp.dhis.common.view.DetailedView;
@@ -478,17 +479,26 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             ValidationRule validationRule = (ValidationRule) other;
 
-            description = validationRule.getDescription() == null ? description : validationRule.getDescription();
-            operator = validationRule.getOperator() == null ? operator : validationRule.getOperator();
-            periodType = validationRule.getPeriodType() == null ? periodType : validationRule.getPeriodType();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                description = validationRule.getDescription();
+                operator = validationRule.getOperator();
+                periodType = validationRule.getPeriodType();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                description = validationRule.getDescription() == null ? description : validationRule.getDescription();
+                operator = validationRule.getOperator() == null ? operator : validationRule.getOperator();
+                periodType = validationRule.getPeriodType() == null ? periodType : validationRule.getPeriodType();
+            }
 
             if ( leftSide != null && validationRule.getLeftSide() != null )
             {

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRuleGroup.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRuleGroup.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRuleGroup.java	2015-02-05 06:53:38 +0000
@@ -37,6 +37,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.annotation.Scanned;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -176,15 +177,22 @@
     }
 
     @Override
-    public void mergeWith( IdentifiableObject other )
+    public void mergeWith( IdentifiableObject other, MergeStrategy strategy )
     {
-        super.mergeWith( other );
+        super.mergeWith( other, strategy );
 
         if ( other.getClass().isInstance( this ) )
         {
             ValidationRuleGroup validationRuleGroup = (ValidationRuleGroup) other;
 
-            description = validationRuleGroup.getDescription() == null ? description : validationRuleGroup.getDescription();
+            if ( MergeStrategy.MERGE_ALWAYS.equals( strategy ) )
+            {
+                description = validationRuleGroup.getDescription();
+            }
+            else if ( MergeStrategy.MERGE_IF_NOT_NULL.equals( strategy ) )
+            {
+                description = validationRuleGroup.getDescription() == null ? description : validationRuleGroup.getDescription();
+            }
 
             removeAllValidationRules();
 

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/dimension/DefaultDimensionService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/dimension/DefaultDimensionService.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/dimension/DefaultDimensionService.java	2015-02-05 06:53:38 +0000
@@ -37,6 +37,7 @@
 import org.hisp.dhis.common.DimensionalObjectUtils;
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObjectManager;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.dataelement.CategoryOptionGroup;
 import org.hisp.dhis.dataelement.CategoryOptionGroupSet;
@@ -348,7 +349,7 @@
         DimensionalObject dimension = getDimension( uid );
         
         BaseDimensionalObject copy = new BaseDimensionalObject();
-        copy.mergeWith( dimension );
+        copy.mergeWith( dimension, MergeStrategy.MERGE_IF_NOT_NULL );
         
         if ( filterCanRead )
         {

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/gml/DefaultGmlImportService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/gml/DefaultGmlImportService.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/gml/DefaultGmlImportService.java	2015-02-05 06:53:38 +0000
@@ -30,6 +30,7 @@
 
 import com.google.common.base.Function;
 import com.google.common.collect.Maps;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.dxf2.metadata.ImportOptions;
 import org.hisp.dhis.dxf2.metadata.ImportService;
 import org.hisp.dhis.dxf2.metadata.MetaData;
@@ -113,7 +114,7 @@
             String coordinates = unit.getCoordinates(),
                    featureType = unit.getFeatureType();
 
-            unit.mergeWith( persisted );
+            unit.mergeWith( persisted, MergeStrategy.MERGE_IF_NOT_NULL );
 
             unit.setCoordinates( coordinates );
             unit.setFeatureType( featureType );

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/importers/DefaultIdentifiableObjectImporter.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/importers/DefaultIdentifiableObjectImporter.java	2015-01-23 16:35:50 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/importers/DefaultIdentifiableObjectImporter.java	2015-02-05 06:53:38 +0000
@@ -41,6 +41,7 @@
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObjectManager;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.dashboard.DashboardItem;
 import org.hisp.dhis.dataelement.CategoryOptionGroupSet;
@@ -448,12 +449,12 @@
         if ( !options.isSharing() )
         {
             User persistedObjectUser = persistedObject.getUser();
-            persistedObject.mergeWith( object );
+            persistedObject.mergeWith( object, MergeStrategy.MERGE_IF_NOT_NULL );
             persistedObject.setUser( persistedObjectUser );
         }
         else
         {
-            persistedObject.mergeWith( object );
+            persistedObject.mergeWith( object, MergeStrategy.MERGE_IF_NOT_NULL );
             persistedObject.mergeSharingWith( object );
         }
 
@@ -477,7 +478,7 @@
                     userService.encodeAndSetPassword( userCredentials, userCredentials.getPassword() );
                 }
 
-                ((User) persistedObject).getUserCredentials().mergeWith( userCredentials );
+                ((User) persistedObject).getUserCredentials().mergeWith( userCredentials, MergeStrategy.MERGE_IF_NOT_NULL );
                 reattachCollectionFields( ((User) persistedObject).getUserCredentials(), collectionFieldsUserCredentials, user );
 
                 sessionFactory.getCurrentSession().saveOrUpdate( ((User) persistedObject).getUserCredentials() );

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/ChartController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/ChartController.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/ChartController.java	2015-02-05 06:53:38 +0000
@@ -42,6 +42,7 @@
 import org.hisp.dhis.chart.Chart;
 import org.hisp.dhis.chart.ChartService;
 import org.hisp.dhis.common.DimensionService;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
 import org.hisp.dhis.dataelement.DataElementCategoryService;
@@ -138,7 +139,7 @@
 
         mergeChart( newChart );
 
-        chart.mergeWith( newChart );
+        chart.mergeWith( newChart, MergeStrategy.MERGE_IF_NOT_NULL );
 
         chartService.updateChart( chart );
     }

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/ReportTableController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/ReportTableController.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/ReportTableController.java	2015-02-05 06:53:38 +0000
@@ -40,6 +40,7 @@
 
 import org.hisp.dhis.common.DimensionService;
 import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.dxf2.utils.JacksonUtils;
 import org.hisp.dhis.i18n.I18nFormat;
 import org.hisp.dhis.i18n.I18nManager;
@@ -123,7 +124,7 @@
 
         mergeReportTable( newReportTable );
 
-        reportTable.mergeWith( newReportTable );
+        reportTable.mergeWith( newReportTable, MergeStrategy.MERGE_IF_NOT_NULL );
 
         reportTableService.updateReportTable( reportTable );
     }

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventChartController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventChartController.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventChartController.java	2015-02-05 06:53:38 +0000
@@ -40,6 +40,7 @@
 
 import org.hisp.dhis.chart.ChartService;
 import org.hisp.dhis.common.DimensionService;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.dxf2.utils.JacksonUtils;
 import org.hisp.dhis.eventchart.EventChart;
 import org.hisp.dhis.eventchart.EventChartService;
@@ -130,7 +131,7 @@
 
         mergeEventChart( newEventChart );
 
-        eventChart.mergeWith( newEventChart );
+        eventChart.mergeWith( newEventChart, MergeStrategy.MERGE_IF_NOT_NULL );
 
         eventChartService.updateEventChart( eventChart );
     }

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventReportController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventReportController.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventReportController.java	2015-02-05 06:53:38 +0000
@@ -36,6 +36,7 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.hisp.dhis.common.DimensionService;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.dxf2.utils.JacksonUtils;
 import org.hisp.dhis.eventreport.EventReport;
 import org.hisp.dhis.eventreport.EventReportService;
@@ -110,7 +111,7 @@
 
         mergeEventReport( newReport );
 
-        report.mergeWith( newReport );
+        report.mergeWith( newReport, MergeStrategy.MERGE_IF_NOT_NULL );
 
         eventReportService.updateEventReport( report );
     }

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/MapController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/MapController.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/MapController.java	2015-02-05 06:53:38 +0000
@@ -40,6 +40,7 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.hisp.dhis.common.DimensionService;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.dxf2.utils.JacksonUtils;
 import org.hisp.dhis.i18n.I18nFormat;
 import org.hisp.dhis.i18n.I18nManager;
@@ -160,7 +161,7 @@
             mappingService.addMapView( view );
         }
 
-        map.mergeWith( newMap );
+        map.mergeWith( newMap, MergeStrategy.MERGE_IF_NOT_NULL );
 
         if ( newMap.getUser() == null )
         {

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/MapLegendSetController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/MapLegendSetController.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/MapLegendSetController.java	2015-02-05 06:53:38 +0000
@@ -28,6 +28,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.dxf2.utils.JacksonUtils;
 import org.hisp.dhis.mapping.MapLegend;
 import org.hisp.dhis.mapping.MapLegendSet;
@@ -103,7 +104,7 @@
             mappingService.addMapLegend( legend );
         }
 
-        legendSet.mergeWith( newLegendSet );
+        legendSet.mergeWith( newLegendSet, MergeStrategy.MERGE_IF_NOT_NULL );
 
         mappingService.updateMapLegendSet( legendSet );
     }

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/user/UserController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/user/UserController.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/user/UserController.java	2015-02-05 06:53:38 +0000
@@ -41,6 +41,7 @@
 import org.apache.commons.lang.StringUtils;
 import org.hisp.dhis.common.CodeGenerator;
 import org.hisp.dhis.common.IdentifiableObjectUtils;
+import org.hisp.dhis.common.MergeStrategy;
 import org.hisp.dhis.common.Pager;
 import org.hisp.dhis.dxf2.importsummary.ImportStatus;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
@@ -310,12 +311,12 @@
         }
         
         User userReplica = new User();
-        userReplica.mergeWith( existingUser );
+        userReplica.mergeWith( existingUser, MergeStrategy.MERGE_IF_NOT_NULL );
         userReplica.setUid( CodeGenerator.generateCode() );
         userReplica.setCreated( new Date() );
         
         UserCredentials credentialsReplica = new UserCredentials();
-        credentialsReplica.mergeWith( existingUser.getUserCredentials() );
+        credentialsReplica.mergeWith( existingUser.getUserCredentials(), MergeStrategy.MERGE_IF_NOT_NULL );
         
         credentialsReplica.setUsername( username );
         userService.encodeAndSetPassword( credentialsReplica, password );