← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 22081: wip, improved/unified error reporting for preheater/object bundle

 

------------------------------------------------------------
revno: 22081
committer: Morten Olav Hansen <morten@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2016-03-01 14:51:42 +0700
message:
  wip, improved/unified error reporting for preheater/object bundle
removed:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/InvalidObject.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/InvalidReference.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatValidation.java
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorCode.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorMessage.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorReport.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorReports.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatErrorReport.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/feedback/
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/feedback/ImportReport.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/feedback/ImportStats.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatIdentifier.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/preheat/DefaultPreheatService.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/preheat/PreheatServiceTest.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/DefaultMetadataImportService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/MetadataImportService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/DefaultObjectBundleService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleValidation.java
  dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleServiceTest.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
=== added directory 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback'
=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorCode.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorCode.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorCode.java	2016-03-01 07:51:42 +0000
@@ -0,0 +1,53 @@
+package org.hisp.dhis.feedback;
+
+/*
+ * Copyright (c) 2004-2016, 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.
+ */
+
+/**
+ * E5000 - E5999: Preheat Errors
+ * E6000 - E6999: DXF2 Import Errors
+ *
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public enum ErrorCode
+{
+    E5000( "No matching object for given reference. Identifier was {0}, and object was {1}." ),
+    E5001( "Invalid reference {0} on object {1} for association \"{2}\"." );
+
+    private String message;
+
+    ErrorCode( String message )
+    {
+        this.message = message;
+    }
+
+    public String getMessage()
+    {
+        return message;
+    }
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorMessage.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorMessage.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorMessage.java	2016-03-01 07:51:42 +0000
@@ -0,0 +1,57 @@
+package org.hisp.dhis.feedback;
+
+/*
+ * Copyright (c) 2004-2016, 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.
+ */
+
+import java.text.MessageFormat;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public class ErrorMessage
+{
+    private final ErrorCode errorCode;
+
+    private final Object[] args;
+
+    public ErrorMessage( ErrorCode errorCode, Object... args )
+    {
+        this.errorCode = errorCode;
+        this.args = args;
+    }
+
+    public ErrorCode getErrorCode()
+    {
+        return errorCode;
+    }
+
+    public String getMessage()
+    {
+        return MessageFormat.format( errorCode.getMessage(), args );
+    }
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorReport.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorReport.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorReport.java	2016-03-01 07:51:42 +0000
@@ -0,0 +1,106 @@
+package org.hisp.dhis.feedback;
+
+/*
+ * Copyright (c) 2004-2016, 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.
+ */
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public class ErrorReport
+{
+    protected final ErrorMessage message;
+
+    protected final Class<?> mainKlass;
+
+    protected Class<?> errorKlass;
+
+    protected Object value;
+
+    public ErrorReport( Class<?> mainKlass, ErrorCode errorCode, Object... args )
+    {
+        this.mainKlass = mainKlass;
+        this.message = new ErrorMessage( errorCode, args );
+    }
+
+    public ErrorReport( Class<?> mainKlass, ErrorMessage message )
+    {
+        this.mainKlass = mainKlass;
+        this.message = message;
+    }
+
+    public ErrorCode getErrorCode()
+    {
+        return message.getErrorCode();
+    }
+
+    public String getMessage()
+    {
+        return message.getMessage();
+    }
+
+    public Class<?> getMainKlass()
+    {
+        return mainKlass;
+    }
+
+    public Class<?> getErrorKlass()
+    {
+        return errorKlass;
+    }
+
+    public ErrorReport setErrorKlass( Class<?> errorKlass )
+    {
+        this.errorKlass = errorKlass;
+        return this;
+    }
+
+    public Object getValue()
+    {
+        return value;
+    }
+
+    public ErrorReport setValue( Object value )
+    {
+        this.value = value;
+        return this;
+    }
+
+
+    @Override
+    public String toString()
+    {
+        return MoreObjects.toStringHelper( this )
+            .add( "message", getMessage() )
+            .add( "mainKlass", mainKlass )
+            .add( "errorKlass", errorKlass )
+            .add( "value", value )
+            .toString();
+    }
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorReports.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorReports.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/feedback/ErrorReports.java	2016-03-01 07:51:42 +0000
@@ -0,0 +1,49 @@
+package org.hisp.dhis.feedback;
+
+/*
+ * Copyright (c) 2004-2016, 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.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public class ErrorReports
+{
+    private List<ErrorReport> errorReports = new ArrayList<>();
+
+    public ErrorReports()
+    {
+    }
+
+    public List<ErrorReport> getErrorReports()
+    {
+        return errorReports;
+    }
+}

=== removed file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/InvalidObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/InvalidObject.java	2016-02-16 04:53:44 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/InvalidObject.java	1970-01-01 00:00:00 +0000
@@ -1,97 +0,0 @@
-package org.hisp.dhis.preheat;
-
-/*
- * Copyright (c) 2004-2016, 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.
- */
-
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
-import com.google.common.base.MoreObjects;
-import org.hisp.dhis.common.DxfNamespaces;
-import org.hisp.dhis.common.IdentifiableObjectUtils;
-import org.springframework.util.Assert;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-@JacksonXmlRootElement( localName = "invalidObject", namespace = DxfNamespaces.DXF_2_0 )
-public class InvalidObject
-{
-    private String name;
-
-    private PreheatIdentifier identifier;
-
-    private Object object;
-
-    public InvalidObject( Object object, PreheatIdentifier identifier )
-    {
-        Assert.notNull( object );
-        Assert.notNull( identifier );
-
-        this.object = object;
-        this.identifier = identifier;
-        this.name = IdentifiableObjectUtils.getDisplayName( object );
-    }
-
-    public String getName()
-    {
-        return name;
-    }
-
-    public void setName( String name )
-    {
-        this.name = name;
-    }
-
-    public PreheatIdentifier getIdentifier()
-    {
-        return identifier;
-    }
-
-    public void setIdentifier( PreheatIdentifier identifier )
-    {
-        this.identifier = identifier;
-    }
-
-    public Object getObject()
-    {
-        return object;
-    }
-
-    public void setObject( Object object )
-    {
-        this.object = object;
-    }
-
-    @Override
-    public String toString()
-    {
-        return MoreObjects.toStringHelper( this )
-            .add( "name", name )
-            .add( "identifier", identifier )
-            .toString();
-    }
-}

=== removed file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/InvalidReference.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/InvalidReference.java	2016-02-11 05:40:52 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/InvalidReference.java	1970-01-01 00:00:00 +0000
@@ -1,128 +0,0 @@
-package org.hisp.dhis.preheat;
-
-/*
- * Copyright (c) 2004-2016, 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.
- */
-
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
-import com.google.common.base.MoreObjects;
-import org.hisp.dhis.common.DxfNamespaces;
-import org.hisp.dhis.common.IdentifiableObject;
-import org.hisp.dhis.common.IdentifiableObjectUtils;
-import org.hisp.dhis.schema.Property;
-import org.springframework.util.Assert;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-@JacksonXmlRootElement( localName = "invalidReference", namespace = DxfNamespaces.DXF_2_0 )
-public class InvalidReference
-{
-    private String name;
-
-    private PreheatIdentifier identifier;
-
-    private Object object;
-
-    private IdentifiableObject refObject;
-
-    private Property property;
-
-    public InvalidReference( Object object, PreheatIdentifier identifier, IdentifiableObject refObject, Property property )
-    {
-        Assert.notNull( object );
-        Assert.notNull( identifier );
-        Assert.notNull( refObject );
-        Assert.notNull( property );
-
-        this.object = object;
-        this.identifier = identifier;
-        this.refObject = refObject;
-        this.property = property;
-        this.name = IdentifiableObjectUtils.getDisplayName( object );
-    }
-
-    public String getName()
-    {
-        return name;
-    }
-
-    public void setName( String name )
-    {
-        this.name = name;
-    }
-
-    public PreheatIdentifier getIdentifier()
-    {
-        return identifier;
-    }
-
-    public void setIdentifier( PreheatIdentifier identifier )
-    {
-        this.identifier = identifier;
-    }
-
-    public Object getObject()
-    {
-        return object;
-    }
-
-    public void setObject( Object object )
-    {
-        this.object = object;
-    }
-
-    public IdentifiableObject getRefObject()
-    {
-        return refObject;
-    }
-
-    public void setRefObject( IdentifiableObject refObject )
-    {
-        this.refObject = refObject;
-    }
-
-    public Property getProperty()
-    {
-        return property;
-    }
-
-    public void setProperty( Property property )
-    {
-        this.property = property;
-    }
-
-    @Override
-    public String toString()
-    {
-        return MoreObjects.toStringHelper( this )
-            .add( "name", name )
-            .add( "identifier", identifier )
-            .add( "refObject", refObject )
-            .toString();
-    }
-}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatErrorReport.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatErrorReport.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatErrorReport.java	2016-03-01 07:51:42 +0000
@@ -0,0 +1,57 @@
+package org.hisp.dhis.preheat;
+
+/*
+ * Copyright (c) 2004-2016, 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.
+ */
+
+import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.feedback.ErrorCode;
+import org.hisp.dhis.feedback.ErrorReport;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public class PreheatErrorReport extends ErrorReport
+{
+    private final PreheatIdentifier preheatIdentifier;
+
+    public PreheatErrorReport( PreheatIdentifier preheatIdentifier, Class<?> mainKlass, ErrorCode errorCode, Object... args )
+    {
+        super( mainKlass, errorCode, args );
+        this.preheatIdentifier = preheatIdentifier;
+    }
+
+    public PreheatIdentifier getPreheatIdentifier()
+    {
+        return preheatIdentifier;
+    }
+
+    public IdentifiableObject getObjectReference()
+    {
+        return value != null ? (IdentifiableObject) value : null;
+    }
+}

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatIdentifier.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatIdentifier.java	2016-02-16 04:53:44 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatIdentifier.java	2016-03-01 07:51:42 +0000
@@ -28,8 +28,12 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import com.google.common.collect.Lists;
 import org.hisp.dhis.common.IdentifiableObject;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
  */
@@ -50,7 +54,7 @@
      */
     AUTO;
 
-    @SuppressWarnings("incomplete-switch")
+    @SuppressWarnings( "incomplete-switch" )
     public <T extends IdentifiableObject> String getIdentifier( T object )
     {
         switch ( this )
@@ -63,4 +67,25 @@
 
         throw new RuntimeException( "Unhandled identifier type." );
     }
+
+    public <T extends IdentifiableObject> List<String> getIdentifiers( T object )
+    {
+        switch ( this )
+        {
+            case UID:
+            {
+                return Lists.newArrayList( object.getUid() );
+            }
+            case CODE:
+            {
+                return Lists.newArrayList( object.getCode() );
+            }
+            case AUTO:
+            {
+                return Lists.newArrayList( object.getUid(), object.getCode() );
+            }
+        }
+
+        return new ArrayList<>();
+    }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatService.java	2016-02-26 09:07:23 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatService.java	2016-03-01 07:51:42 +0000
@@ -29,6 +29,7 @@
  */
 
 import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.feedback.ErrorReports;
 
 import java.util.Collection;
 import java.util.List;
@@ -82,21 +83,19 @@
 
     /**
      * Checks but does not connect any references, returns check report
-     *
-     * @param objects    Object to check
+     *  @param objects    Object to check
      * @param preheat    Preheat Cache to use
      * @param identifier Use this identifier type to check references
      */
-    List<PreheatValidation> checkReferences( List<IdentifiableObject> objects, Preheat preheat, PreheatIdentifier identifier );
+    List<List<PreheatErrorReport>> checkReferences( List<IdentifiableObject> objects, Preheat preheat, PreheatIdentifier identifier );
 
     /**
      * Checks but does not connect any references, returns check report
-     *
      * @param object     Object to check
      * @param preheat    Preheat Cache to use
      * @param identifier Use this identifier type to check references
      */
-    PreheatValidation checkReferences( IdentifiableObject object, Preheat preheat, PreheatIdentifier identifier );
+    List<PreheatErrorReport> checkReferences( IdentifiableObject object, Preheat preheat, PreheatIdentifier identifier );
 
     /**
      * Connects id object references on a given object using a given identifier + a preheated Preheat cache.

=== removed file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatValidation.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatValidation.java	2016-02-11 05:40:52 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatValidation.java	1970-01-01 00:00:00 +0000
@@ -1,67 +0,0 @@
-package org.hisp.dhis.preheat;
-
-/*
- * Copyright (c) 2004-2016, 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.
- */
-
-import com.google.common.base.MoreObjects;
-import org.hisp.dhis.common.IdentifiableObject;
-import org.hisp.dhis.schema.Property;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-public class PreheatValidation
-{
-    private List<InvalidReference> invalidReferences = new ArrayList<>();
-
-    public PreheatValidation()
-    {
-    }
-
-    public void addInvalidReference( Object object, PreheatIdentifier identifier, IdentifiableObject refObject, Property property )
-    {
-        invalidReferences.add( new InvalidReference( object, identifier, refObject, property ) );
-    }
-
-    public List<InvalidReference> getInvalidReferences()
-    {
-        return invalidReferences;
-    }
-
-
-    @Override
-    public String toString()
-    {
-        return MoreObjects.toStringHelper( this )
-            .add( "invalidReferences", invalidReferences )
-            .toString();
-    }
-}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/preheat/DefaultPreheatService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/preheat/DefaultPreheatService.java	2016-02-29 05:37:22 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/preheat/DefaultPreheatService.java	2016-03-01 07:51:42 +0000
@@ -34,6 +34,7 @@
 import org.hisp.dhis.common.IdentifiableObjectManager;
 import org.hisp.dhis.common.MergeMode;
 import org.hisp.dhis.dataelement.DataElementOperand;
+import org.hisp.dhis.feedback.ErrorCode;
 import org.hisp.dhis.query.Query;
 import org.hisp.dhis.query.QueryService;
 import org.hisp.dhis.query.Restrictions;
@@ -416,22 +417,22 @@
     }
 
     @Override
-    public List<PreheatValidation> checkReferences( List<IdentifiableObject> objects, Preheat preheat, PreheatIdentifier identifier )
+    public List<List<PreheatErrorReport>> checkReferences( List<IdentifiableObject> objects, Preheat preheat, PreheatIdentifier identifier )
     {
-        List<PreheatValidation> preheatValidations = new ArrayList<>();
-        objects.forEach( object -> preheatValidations.add( checkReferences( object, preheat, identifier ) ) );
+        List<List<PreheatErrorReport>> preheatErrorReports = new ArrayList<>();
+        objects.forEach( object -> preheatErrorReports.add( checkReferences( object, preheat, identifier ) ) );
 
-        return preheatValidations;
+        return preheatErrorReports;
     }
 
     @Override
-    public PreheatValidation checkReferences( IdentifiableObject object, Preheat preheat, PreheatIdentifier identifier )
+    public List<PreheatErrorReport> checkReferences( IdentifiableObject object, Preheat preheat, PreheatIdentifier identifier )
     {
-        PreheatValidation preheatValidation = new PreheatValidation();
+        List<PreheatErrorReport> preheatErrorReports = new ArrayList<>();
 
         if ( object == null )
         {
-            return preheatValidation;
+            return preheatErrorReports;
         }
 
         Schema schema = schemaService.getDynamicSchema( object.getClass() );
@@ -450,7 +451,8 @@
 
                     if ( ref == null && refObject != null && !Preheat.isDefault( refObject ) )
                     {
-                        preheatValidation.addInvalidReference( object, identifier, refObject, p );
+                        preheatErrorReports.add( new PreheatErrorReport( identifier, object.getClass(), ErrorCode.E5001,
+                            identifier.getIdentifiers( refObject ), identifier.getIdentifiers( object ), p.getName() ) );
                     }
                 }
                 else
@@ -466,7 +468,8 @@
 
                         if ( ref == null && refObject != null )
                         {
-                            preheatValidation.addInvalidReference( object, identifier, refObject, p );
+                            preheatErrorReports.add( new PreheatErrorReport( identifier, object.getClass(), ErrorCode.E5001,
+                                identifier.getIdentifiers( refObject ), identifier.getIdentifiers( object ), p.getCollectionName() ) );
                         }
                         else
                         {
@@ -478,7 +481,7 @@
                 }
             } );
 
-        return preheatValidation;
+        return preheatErrorReports;
     }
 
     @Override

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/preheat/PreheatServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/preheat/PreheatServiceTest.java	2016-02-10 07:45:27 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/preheat/PreheatServiceTest.java	2016-03-01 07:51:42 +0000
@@ -501,11 +501,11 @@
 
         preheatService.validate( params );
         Preheat preheat = preheatService.preheat( params );
-        List<InvalidReference> invalidReferences = preheatService.checkReferences( dataElementGroup, preheat, PreheatIdentifier.UID ).getInvalidReferences();
-        assertEquals( 3, invalidReferences.size() );
-        assertEquals( PreheatIdentifier.UID, invalidReferences.get( 0 ).getIdentifier() );
-        assertEquals( PreheatIdentifier.UID, invalidReferences.get( 1 ).getIdentifier() );
-        assertEquals( PreheatIdentifier.UID, invalidReferences.get( 2 ).getIdentifier() );
+        List<PreheatErrorReport> referenceErrors = preheatService.checkReferences( dataElementGroup, preheat, PreheatIdentifier.UID );
+        assertEquals( 3, referenceErrors.size() );
+        assertEquals( PreheatIdentifier.UID, referenceErrors.get( 0 ).getPreheatIdentifier() );
+        assertEquals( PreheatIdentifier.UID, referenceErrors.get( 1 ).getPreheatIdentifier() );
+        assertEquals( PreheatIdentifier.UID, referenceErrors.get( 2 ).getPreheatIdentifier() );
     }
 
     @Test

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/DefaultMetadataImportService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/DefaultMetadataImportService.java	2016-02-04 04:08:38 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/DefaultMetadataImportService.java	2016-03-01 07:51:42 +0000
@@ -32,6 +32,7 @@
 import org.apache.commons.logging.LogFactory;
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObjectManager;
+import org.hisp.dhis.dxf2.metadata2.feedback.ImportReport;
 import org.hisp.dhis.preheat.PreheatService;
 import org.hisp.dhis.schema.SchemaService;
 import org.hisp.dhis.user.CurrentUserService;
@@ -62,8 +63,10 @@
     private IdentifiableObjectManager manager;
 
     @Override
-    public void importMetadata( MetadataImportParams params )
+    public ImportReport importMetadata( MetadataImportParams params )
     {
+        ImportReport report = new ImportReport();
+
         if ( params.getUser() == null )
         {
             params.setUser( currentUserService.getCurrentUser() );
@@ -74,6 +77,8 @@
             List<? extends IdentifiableObject> objects = params.getObjects( klass );
             objects.forEach( this::importObject );
         }
+
+        return report;
     }
 
     @Override

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/MetadataImportService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/MetadataImportService.java	2016-02-04 04:08:38 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/MetadataImportService.java	2016-03-01 07:51:42 +0000
@@ -28,6 +28,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import org.hisp.dhis.dxf2.metadata2.feedback.ImportReport;
+
 import java.util.List;
 import java.util.Map;
 
@@ -36,7 +38,7 @@
  */
 public interface MetadataImportService
 {
-    void importMetadata( MetadataImportParams params );
+    ImportReport importMetadata( MetadataImportParams params );
 
     void validate( MetadataImportParams params );
 

=== added directory 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/feedback'
=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/feedback/ImportReport.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/feedback/ImportReport.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/feedback/ImportReport.java	2016-03-01 07:51:42 +0000
@@ -0,0 +1,93 @@
+package org.hisp.dhis.dxf2.metadata2.feedback;
+
+/*
+ * Copyright (c) 2004-2016, 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.
+ */
+
+import org.hisp.dhis.feedback.ErrorReport;
+import org.hisp.dhis.feedback.ErrorReports;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public class ImportReport
+{
+    private ImportStats stats = new ImportStats();
+
+    private Map<Class<?>, ErrorReports> errorReportMap = new HashMap<>();
+
+    public ImportReport()
+    {
+    }
+
+    public ImportStats getStats()
+    {
+        return stats;
+    }
+
+    public void addErrorReport( ErrorReport errorReport )
+    {
+        if ( !errorReportMap.containsKey( errorReport.getMainKlass() ) )
+        {
+            errorReportMap.put( errorReport.getMainKlass(), new ErrorReports() );
+        }
+
+        errorReportMap.get( errorReport.getMainKlass() ).getErrorReports().add( errorReport );
+    }
+
+    public void addErrorReports( ErrorReports errorReports )
+    {
+        if ( errorReports == null || errorReports.getErrorReports().isEmpty() )
+        {
+            return;
+        }
+
+        Class<?> mainKlass = errorReports.getErrorReports().get( 0 ).getMainKlass();
+
+        if ( !errorReportMap.containsKey( mainKlass ) )
+        {
+            errorReportMap.put( mainKlass, new ErrorReports() );
+        }
+
+        errorReportMap.get( mainKlass ).getErrorReports().addAll( errorReports.getErrorReports() );
+    }
+
+    public Map<Class<?>, ErrorReports> getErrorReportMap()
+    {
+        return errorReportMap;
+    }
+
+    public List<ErrorReports> getErrorReports()
+    {
+        return new ArrayList<>( errorReportMap.values() );
+    }
+}

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/feedback/ImportStats.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/feedback/ImportStats.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/feedback/ImportStats.java	2016-03-01 07:51:42 +0000
@@ -0,0 +1,36 @@
+package org.hisp.dhis.dxf2.metadata2.feedback;
+
+/*
+ * Copyright (c) 2004-2016, 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 class ImportStats
+{
+}

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/DefaultObjectBundleService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/DefaultObjectBundleService.java	2016-02-29 07:35:27 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/DefaultObjectBundleService.java	2016-03-01 07:51:42 +0000
@@ -37,8 +37,9 @@
 import org.hisp.dhis.common.IdentifiableObjectManager;
 import org.hisp.dhis.common.IdentifiableObjectUtils;
 import org.hisp.dhis.dxf2.metadata2.objectbundle.hooks.ObjectBundleHook;
-import org.hisp.dhis.preheat.InvalidObject;
+import org.hisp.dhis.feedback.ErrorCode;
 import org.hisp.dhis.preheat.Preheat;
+import org.hisp.dhis.preheat.PreheatErrorReport;
 import org.hisp.dhis.preheat.PreheatIdentifier;
 import org.hisp.dhis.preheat.PreheatMode;
 import org.hisp.dhis.preheat.PreheatParams;
@@ -182,14 +183,15 @@
 
                     if ( object == null )
                     {
-                        objectBundleValidation.addInvalidObject( klass, new InvalidObject( identifiableObject, bundle.getPreheatIdentifier() ) );
+                        objectBundleValidation.addErrorReport( klass, ErrorCode.E5000, bundle.getPreheatIdentifier(),
+                            bundle.getPreheatIdentifier().getIdentifiers( identifiableObject ) );
                         iterator.remove();
                     }
                 }
             }
 
-            objectBundleValidation.addPreheatValidations( klass, preheatService.checkReferences(
-                bundle.getObjects().get( klass ), bundle.getPreheat(), bundle.getPreheatIdentifier() ) );
+            List<List<PreheatErrorReport>> referenceErrors = preheatService.checkReferences( bundle.getObjects().get( klass ), bundle.getPreheat(), bundle.getPreheatIdentifier() );
+            referenceErrors.forEach( objectBundleValidation::addPreheatErrorReports ); // collapsing for now, we might want to give pr object ref list
 
             List<List<ValidationViolation>> validationViolations = new ArrayList<>();
 

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleValidation.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleValidation.java	2016-02-16 04:53:44 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleValidation.java	2016-03-01 07:51:42 +0000
@@ -28,10 +28,10 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import com.google.common.base.MoreObjects;
 import org.hisp.dhis.common.IdentifiableObject;
-import org.hisp.dhis.preheat.InvalidObject;
-import org.hisp.dhis.preheat.PreheatValidation;
+import org.hisp.dhis.feedback.ErrorCode;
+import org.hisp.dhis.feedback.ErrorReport;
+import org.hisp.dhis.preheat.PreheatErrorReport;
 import org.hisp.dhis.schema.validation.ValidationViolation;
 
 import java.util.ArrayList;
@@ -44,24 +44,67 @@
  */
 public class ObjectBundleValidation
 {
-    private Map<Class<? extends IdentifiableObject>, List<PreheatValidation>> preheatValidations = new HashMap<>();
+    private Map<Class<?>, Map<ErrorCode, List<ErrorReport>>> errorReports = new HashMap<>();
 
     private Map<Class<? extends IdentifiableObject>, List<List<ValidationViolation>>> validationViolations = new HashMap<>();
 
-    private Map<Class<? extends IdentifiableObject>, List<InvalidObject>> invalidObjects = new HashMap<>();
-
     public ObjectBundleValidation()
     {
     }
 
-    public void addPreheatValidations( Class<? extends IdentifiableObject> klass, List<PreheatValidation> preheatValidations )
-    {
-        this.preheatValidations.put( klass, preheatValidations );
-    }
-
-    public Map<Class<? extends IdentifiableObject>, List<PreheatValidation>> getPreheatValidations()
-    {
-        return preheatValidations;
+    public void addPreheatErrorReports( List<PreheatErrorReport> preheatErrorReports )
+    {
+        preheatErrorReports.forEach( this::addErrorReport );
+    }
+
+    public <T extends ErrorReport> void addErrorReport( T errorReport )
+    {
+        if ( !errorReports.containsKey( errorReport.getMainKlass() ) )
+        {
+            errorReports.put( errorReport.getMainKlass(), new HashMap<>() );
+        }
+
+        if ( !errorReports.get( errorReport.getMainKlass() ).containsKey( errorReport.getErrorCode() ) )
+        {
+            errorReports.get( errorReport.getMainKlass() ).put( errorReport.getErrorCode(), new ArrayList<>() );
+        }
+
+        errorReports.get( errorReport.getMainKlass() ).get( errorReport.getErrorCode() ).add( errorReport );
+    }
+
+    public void addErrorReport( Class<?> mainKlass, ErrorCode errorCode, Object... args )
+    {
+        ErrorReport errorReport = new ErrorReport( mainKlass, errorCode, args );
+        addErrorReport( errorReport );
+    }
+
+    public Map<Class<?>, Map<ErrorCode, List<ErrorReport>>> getErrorReports()
+    {
+        return errorReports;
+    }
+
+    public Map<ErrorCode, List<ErrorReport>> getErrorReports( Class<?> klass )
+    {
+        Map<ErrorCode, List<ErrorReport>> map = errorReports.get( klass );
+
+        if ( map == null )
+        {
+            return new HashMap<>();
+        }
+
+        return map;
+    }
+
+    public List<ErrorReport> getErrorReports( Class<?> klass, ErrorCode errorCode )
+    {
+        Map<ErrorCode, List<ErrorReport>> map = errorReports.get( klass );
+
+        if ( !map.containsKey( errorCode ) )
+        {
+            return new ArrayList<>();
+        }
+
+        return map.get( errorCode );
     }
 
     public void addValidationViolation( Class<? extends IdentifiableObject> klass, List<List<ValidationViolation>> validationViolations )
@@ -73,27 +116,4 @@
     {
         return validationViolations;
     }
-
-    public void addInvalidObject( Class<? extends IdentifiableObject> klass, InvalidObject invalidObject )
-    {
-        if ( !invalidObjects.containsKey( klass ) )
-        {
-            invalidObjects.put( klass, new ArrayList<>() );
-        }
-
-        invalidObjects.get( klass ).add( invalidObject );
-    }
-
-    public Map<Class<? extends IdentifiableObject>, List<InvalidObject>> getInvalidObjects()
-    {
-        return invalidObjects;
-    }
-
-    @Override
-    public String toString()
-    {
-        return MoreObjects.toStringHelper( this )
-            .add( "preheatValidations", preheatValidations )
-            .toString();
-    }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleServiceTest.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleServiceTest.java	2016-02-29 08:22:45 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleServiceTest.java	2016-03-01 07:51:42 +0000
@@ -37,15 +37,16 @@
 import org.hisp.dhis.dataelement.DataElementCategoryCombo;
 import org.hisp.dhis.dataelement.DataElementGroup;
 import org.hisp.dhis.dataset.DataSet;
+import org.hisp.dhis.feedback.ErrorCode;
+import org.hisp.dhis.feedback.ErrorReport;
 import org.hisp.dhis.importexport.ImportStrategy;
 import org.hisp.dhis.option.Option;
 import org.hisp.dhis.option.OptionSet;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.period.PeriodType;
-import org.hisp.dhis.preheat.InvalidReference;
+import org.hisp.dhis.preheat.PreheatErrorReport;
 import org.hisp.dhis.preheat.PreheatIdentifier;
 import org.hisp.dhis.preheat.PreheatMode;
-import org.hisp.dhis.preheat.PreheatValidation;
 import org.hisp.dhis.render.RenderFormat;
 import org.hisp.dhis.render.RenderService;
 import org.hisp.dhis.user.User;
@@ -139,29 +140,33 @@
 
         ObjectBundle bundle = objectBundleService.create( params );
         ObjectBundleValidation validate = objectBundleService.validate( bundle );
-        assertFalse( validate.getPreheatValidations().isEmpty() );
-        List<PreheatValidation> dataElementValidations = validate.getPreheatValidations().get( DataElement.class );
-        assertFalse( dataElementValidations.isEmpty() );
-
-        for ( PreheatValidation preheatValidation : dataElementValidations )
+        assertFalse( validate.getErrorReports().isEmpty() );
+
+        Map<ErrorCode, List<ErrorReport>> dataElementErrorReport = validate.getErrorReports().get( DataElement.class );
+        assertFalse( dataElementErrorReport.isEmpty() );
+
+        for ( ErrorCode errorCode : dataElementErrorReport.keySet() )
         {
-            assertFalse( preheatValidation.getInvalidReferences().isEmpty() );
+            List<ErrorReport> errorReports = dataElementErrorReport.get( errorCode );
+            assertFalse( errorReports.isEmpty() );
 
-            for ( InvalidReference invalidReference : preheatValidation.getInvalidReferences() )
+            for ( ErrorReport errorReport : errorReports )
             {
-                assertEquals( PreheatIdentifier.UID, invalidReference.getIdentifier() );
+                assertTrue( PreheatErrorReport.class.isInstance( errorReport ) );
+                PreheatErrorReport preheatErrorReport = (PreheatErrorReport) errorReport;
+                assertEquals( PreheatIdentifier.UID, preheatErrorReport.getPreheatIdentifier() );
 
-                if ( DataElementCategoryCombo.class.isInstance( invalidReference.getRefObject() ) )
-                {
-                    assertEquals( "p0KPaWEg3cf", invalidReference.getRefObject().getUid() );
-                }
-                else if ( User.class.isInstance( invalidReference.getRefObject() ) )
-                {
-                    assertEquals( "GOLswS44mh8", invalidReference.getRefObject().getUid() );
-                }
-                else if ( OptionSet.class.isInstance( invalidReference.getRefObject() ) )
-                {
-                    assertEquals( "pQYCiuosBnZ", invalidReference.getRefObject().getUid() );
+                if ( DataElementCategoryCombo.class.isInstance( preheatErrorReport.getValue() ) )
+                {
+                    assertEquals( "p0KPaWEg3cf", preheatErrorReport.getObjectReference().getUid() );
+                }
+                else if ( User.class.isInstance( preheatErrorReport.getValue() ) )
+                {
+                    assertEquals( "GOLswS44mh8", preheatErrorReport.getObjectReference().getUid() );
+                }
+                else if ( OptionSet.class.isInstance( preheatErrorReport.getValue() ) )
+                {
+                    assertEquals( "pQYCiuosBnZ", preheatErrorReport.getObjectReference().getUid() );
                 }
             }
         }
@@ -188,27 +193,31 @@
 
         ObjectBundle bundle = objectBundleService.create( params );
         ObjectBundleValidation validate = objectBundleService.validate( bundle );
-        assertFalse( validate.getPreheatValidations().isEmpty() );
-        List<PreheatValidation> dataElementValidations = validate.getPreheatValidations().get( DataElement.class );
-        assertFalse( dataElementValidations.isEmpty() );
-
-        for ( PreheatValidation preheatValidation : dataElementValidations )
+        assertFalse( validate.getErrorReports().isEmpty() );
+
+        Map<ErrorCode, List<ErrorReport>> dataElementErrorReport = validate.getErrorReports().get( DataElement.class );
+        assertFalse( dataElementErrorReport.isEmpty() );
+
+        for ( ErrorCode errorCode : dataElementErrorReport.keySet() )
         {
-            assertFalse( preheatValidation.getInvalidReferences().isEmpty() );
+            List<ErrorReport> errorReports = dataElementErrorReport.get( errorCode );
+            assertFalse( errorReports.isEmpty() );
 
-            for ( InvalidReference invalidReference : preheatValidation.getInvalidReferences() )
+            for ( ErrorReport errorReport : errorReports )
             {
-                assertEquals( PreheatIdentifier.UID, invalidReference.getIdentifier() );
+                assertTrue( PreheatErrorReport.class.isInstance( errorReport ) );
+                PreheatErrorReport preheatErrorReport = (PreheatErrorReport) errorReport;
+                assertEquals( PreheatIdentifier.UID, preheatErrorReport.getPreheatIdentifier() );
 
-                if ( DataElementCategoryCombo.class.isInstance( invalidReference.getRefObject() ) )
+                if ( DataElementCategoryCombo.class.isInstance( preheatErrorReport.getValue() ) )
                 {
                     assertFalse( true );
                 }
-                else if ( User.class.isInstance( invalidReference.getRefObject() ) )
+                else if ( User.class.isInstance( preheatErrorReport.getValue() ) )
                 {
-                    assertEquals( "GOLswS44mh8", invalidReference.getRefObject().getUid() );
+                    assertEquals( "GOLswS44mh8", preheatErrorReport.getObjectReference().getUid() );
                 }
-                else if ( OptionSet.class.isInstance( invalidReference.getRefObject() ) )
+                else if ( OptionSet.class.isInstance( preheatErrorReport.getValue() ) )
                 {
                     assertFalse( true );
                 }
@@ -248,8 +257,7 @@
         ObjectBundle bundle = objectBundleService.create( params );
         ObjectBundleValidation validate = objectBundleService.validate( bundle );
 
-        assertTrue( validate.getInvalidObjects().containsKey( DataElement.class ) );
-        assertEquals( 3, validate.getInvalidObjects().get( DataElement.class ).size() );
+        assertEquals( 3, validate.getErrorReports( DataElement.class, ErrorCode.E5000 ).size() );
     }
 
     @Test
@@ -268,8 +276,7 @@
         ObjectBundle bundle = objectBundleService.create( params );
         ObjectBundleValidation validate = objectBundleService.validate( bundle );
 
-        assertTrue( validate.getInvalidObjects().containsKey( DataElement.class ) );
-        assertEquals( 1, validate.getInvalidObjects().get( DataElement.class ).size() );
+        assertEquals( 1, validate.getErrorReports( DataElement.class ).size() );
         assertEquals( 2, bundle.getObjects().get( DataElement.class ).size() );
     }
 
@@ -288,8 +295,8 @@
         ObjectBundle bundle = objectBundleService.create( params );
         ObjectBundleValidation validate = objectBundleService.validate( bundle );
 
-        assertTrue( validate.getInvalidObjects().containsKey( DataElement.class ) );
-        assertEquals( 3, validate.getInvalidObjects().get( DataElement.class ).size() );
+        assertFalse( validate.getErrorReports( DataElement.class ).isEmpty() );
+        assertEquals( 3, validate.getErrorReports( DataElement.class, ErrorCode.E5000 ).size() );
     }
 
     @Test
@@ -307,8 +314,8 @@
         ObjectBundle bundle = objectBundleService.create( params );
         ObjectBundleValidation validate = objectBundleService.validate( bundle );
 
-        assertTrue( validate.getInvalidObjects().containsKey( DataElement.class ) );
-        assertEquals( 3, validate.getInvalidObjects().get( DataElement.class ).size() );
+        assertFalse( validate.getErrorReports( DataElement.class ).isEmpty() );
+        assertEquals( 3, validate.getErrorReports( DataElement.class, ErrorCode.E5000 ).size() );
     }
 
     @Test
@@ -326,8 +333,8 @@
         ObjectBundle bundle = objectBundleService.create( params );
         ObjectBundleValidation validate = objectBundleService.validate( bundle );
 
-        assertTrue( validate.getInvalidObjects().containsKey( DataElement.class ) );
-        assertEquals( 3, validate.getInvalidObjects().get( DataElement.class ).size() );
+        assertFalse( validate.getErrorReports( DataElement.class ).isEmpty() );
+        assertEquals( 3, validate.getErrorReports( DataElement.class, ErrorCode.E5000 ).size() );
     }
 
     @Test
@@ -345,8 +352,8 @@
         ObjectBundle bundle = objectBundleService.create( params );
         ObjectBundleValidation validate = objectBundleService.validate( bundle );
 
-        assertTrue( validate.getInvalidObjects().containsKey( DataElement.class ) );
-        assertEquals( 3, validate.getInvalidObjects().get( DataElement.class ).size() );
+        assertFalse( validate.getErrorReports( DataElement.class ).isEmpty() );
+        assertEquals( 3, validate.getErrorReports( DataElement.class, ErrorCode.E5000 ).size() );
     }
 
     @Test
@@ -364,8 +371,8 @@
         ObjectBundle bundle = objectBundleService.create( params );
         ObjectBundleValidation validate = objectBundleService.validate( bundle );
 
-        assertTrue( validate.getInvalidObjects().containsKey( DataElement.class ) );
-        assertEquals( 3, validate.getInvalidObjects().get( DataElement.class ).size() );
+        assertFalse( validate.getErrorReports( DataElement.class ).isEmpty() );
+        assertEquals( 3, validate.getErrorReports( DataElement.class, ErrorCode.E5000 ).size() );
     }
 
     @Test