← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 14231: tracker web-api refactor, wip

 

------------------------------------------------------------
revno: 14231
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Mon 2014-03-17 09:06:21 +0100
message:
  tracker web-api refactor, wip
removed:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/AbstractPersonService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/JacksonPersonService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/Person.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/PersonService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/Persons.java
  dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/PersonServiceTest.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonAttributeGroupController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonAttributeTypeController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonController.java
added:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/AbstractTrackedEntityInstanceService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/JacksonTrackedEntityInstanceService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstance.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstanceService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstances.java
  dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/TrackedEntityInstanceServiceTest.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityAttributeGroupController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityAttributeTypeController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityInstanceController.java
modified:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/AbstractEnrollmentService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/EnrollmentService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/DefaultEventStore.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventStore.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/EnrollmentServiceTest.java
  dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationMultiEventsServiceTest.java
  dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationSingleEventServiceTest.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EnrollmentController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EventController.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-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/AbstractEnrollmentService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/AbstractEnrollmentService.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/AbstractEnrollmentService.java	2014-03-17 08:06:21 +0000
@@ -32,8 +32,8 @@
 import java.util.Collection;
 import java.util.List;
 
-import org.hisp.dhis.dxf2.events.person.Person;
-import org.hisp.dhis.dxf2.events.person.PersonService;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstanceService;
 import org.hisp.dhis.dxf2.importsummary.ImportStatus;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
 import org.hisp.dhis.i18n.I18nManager;
@@ -42,8 +42,6 @@
 import org.hisp.dhis.program.ProgramInstance;
 import org.hisp.dhis.program.ProgramInstanceService;
 import org.hisp.dhis.program.ProgramService;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
-import org.hisp.dhis.trackedentity.TrackedEntityInstanceService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.Assert;
 
@@ -60,10 +58,10 @@
     private ProgramService programService;
 
     @Autowired
-    private PersonService personService;
+    private TrackedEntityInstanceService trackedEntityInstanceService;
 
     @Autowired
-    private TrackedEntityInstanceService entityInstanceService;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstanceService entityInstanceService;
 
     @Autowired
     private I18nManager i18nManager;
@@ -95,21 +93,21 @@
     }
 
     @Override
-    public Enrollments getEnrollments( Person person )
+    public Enrollments getEnrollments( TrackedEntityInstance trackedEntityInstance )
     {
-        TrackedEntityInstance entityInstance = getTrackedEntityInstance( person.getPerson() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance.getTrackedEntityInstance() );
         return getEnrollments( entityInstance );
     }
 
     @Override
-    public Enrollments getEnrollments( Person person, EnrollmentStatus status )
+    public Enrollments getEnrollments( TrackedEntityInstance trackedEntityInstance, EnrollmentStatus status )
     {
-        TrackedEntityInstance entityInstance = getTrackedEntityInstance( person.getPerson() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance.getTrackedEntityInstance() );
         return getEnrollments( entityInstance, status );
     }
 
     @Override
-    public Enrollments getEnrollments( TrackedEntityInstance entityInstance )
+    public Enrollments getEnrollments( org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance )
     {
         List<ProgramInstance> programInstances = new ArrayList<ProgramInstance>( entityInstance.getProgramInstances() );
 
@@ -117,7 +115,7 @@
     }
 
     @Override
-    public Enrollments getEnrollments( TrackedEntityInstance entityInstance, EnrollmentStatus status )
+    public Enrollments getEnrollments( org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance, EnrollmentStatus status )
     {
         List<ProgramInstance> programInstances = new ArrayList<ProgramInstance>(
             programInstanceService.getProgramInstances( entityInstance, status.getValue() ) );
@@ -169,16 +167,16 @@
     }
 
     @Override
-    public Enrollments getEnrollments( Program program, Person person )
+    public Enrollments getEnrollments( Program program, TrackedEntityInstance trackedEntityInstance )
     {
-        TrackedEntityInstance entityInstance = getTrackedEntityInstance( person.getPerson() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance.getTrackedEntityInstance() );
         return getEnrollments( programInstanceService.getProgramInstances( entityInstance, program ) );
     }
 
     @Override
-    public Enrollments getEnrollments( Program program, Person person, EnrollmentStatus status )
+    public Enrollments getEnrollments( Program program, TrackedEntityInstance trackedEntityInstance, EnrollmentStatus status )
     {
-        TrackedEntityInstance entityInstance = getTrackedEntityInstance( person.getPerson() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance.getTrackedEntityInstance() );
         return getEnrollments( programInstanceService.getProgramInstances( entityInstance, program, status.getValue() ) );
     }
 
@@ -231,15 +229,15 @@
     @Override
     public ImportSummary saveEnrollment( Enrollment enrollment )
     {
-        TrackedEntityInstance entityInstance = getTrackedEntityInstance( enrollment.getPerson() );
-        Person person = personService.getPerson( entityInstance );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( enrollment.getPerson() );
+        TrackedEntityInstance trackedEntityInstance = trackedEntityInstanceService.getPerson( entityInstance );
         Program program = getProgram( enrollment.getProgram() );
 
-        Enrollments enrollments = getEnrollments( program, person, EnrollmentStatus.ACTIVE );
+        Enrollments enrollments = getEnrollments( program, trackedEntityInstance, EnrollmentStatus.ACTIVE );
 
         if ( !enrollments.getEnrollments().isEmpty() )
         {
-            ImportSummary importSummary = new ImportSummary( ImportStatus.ERROR, "Person " + person.getPerson()
+            ImportSummary importSummary = new ImportSummary( ImportStatus.ERROR, "Person " + trackedEntityInstance.getTrackedEntityInstance()
                 + " already have an active enrollment in program " + program.getUid() );
             importSummary.getImportCount().incrementIgnored();
 
@@ -290,7 +288,7 @@
             return importSummary;
         }
 
-        TrackedEntityInstance entityInstance = getTrackedEntityInstance( enrollment.getPerson() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( enrollment.getPerson() );
         Program program = getProgram( enrollment.getProgram() );
 
         programInstance.setProgram( program );
@@ -372,9 +370,9 @@
         return programs;
     }
 
-    private TrackedEntityInstance getTrackedEntityInstance( String person )
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance getTrackedEntityInstance( String person )
     {
-        TrackedEntityInstance entityInstance = entityInstanceService.getTrackedEntityInstance( person );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = entityInstanceService.getTrackedEntityInstance( person );
 
         if ( entityInstance == null )
         {

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/EnrollmentService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/EnrollmentService.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/EnrollmentService.java	2014-03-17 08:06:21 +0000
@@ -32,13 +32,12 @@
 import java.io.InputStream;
 import java.util.Collection;
 
-import org.hisp.dhis.dxf2.events.person.Person;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
 import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramInstance;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
 
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
@@ -53,21 +52,21 @@
 
     Enrollments getEnrollments( EnrollmentStatus status );
 
-    Enrollments getEnrollments( Person person );
-
-    Enrollments getEnrollments( Person person, EnrollmentStatus status );
-
-    Enrollments getEnrollments( TrackedEntityInstance entityInstance );
-
-    Enrollments getEnrollments( TrackedEntityInstance entityInstance, EnrollmentStatus status );
+    Enrollments getEnrollments( TrackedEntityInstance trackedEntityInstance );
+
+    Enrollments getEnrollments( TrackedEntityInstance trackedEntityInstance, EnrollmentStatus status );
+
+    Enrollments getEnrollments( org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance );
+
+    Enrollments getEnrollments( org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance, EnrollmentStatus status );
 
     Enrollments getEnrollments( Program program );
 
     Enrollments getEnrollments( Program program, EnrollmentStatus status );
 
-    Enrollments getEnrollments( Program program, Person person );
+    Enrollments getEnrollments( Program program, TrackedEntityInstance trackedEntityInstance );
 
-    Enrollments getEnrollments( Program program, Person person, EnrollmentStatus status );
+    Enrollments getEnrollments( Program program, TrackedEntityInstance trackedEntityInstance, EnrollmentStatus status );
 
     Enrollments getEnrollments( OrganisationUnit organisationUnit );
 

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java	2014-02-20 10:21:30 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java	2014-03-17 08:06:21 +0000
@@ -38,7 +38,7 @@
 
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementService;
-import org.hisp.dhis.dxf2.events.person.Person;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
 import org.hisp.dhis.dxf2.importsummary.ImportConflict;
 import org.hisp.dhis.dxf2.importsummary.ImportStatus;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
@@ -57,7 +57,6 @@
 import org.hisp.dhis.program.ProgramStageService;
 import org.hisp.dhis.system.util.DateUtils;
 import org.hisp.dhis.system.util.ValidationUtils;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
 import org.hisp.dhis.trackedentity.TrackedEntityInstanceService;
 import org.hisp.dhis.trackedentitycomment.TrackedEntityComment;
 import org.hisp.dhis.trackedentitycomment.TrackedEntityCommentService;
@@ -171,7 +170,7 @@
                     "No Event.person was provided for registration based program." );
             }
 
-            TrackedEntityInstance entityInstance = entityInstanceService.getTrackedEntityInstance( event.getPerson() );
+            org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = entityInstanceService.getTrackedEntityInstance( event.getPerson() );
 
             if ( entityInstance == null )
             {
@@ -308,10 +307,10 @@
     }
 
     @Override
-    public Events getEvents( Program program, OrganisationUnit organisationUnit, Person person, Date startDate,
+    public Events getEvents( Program program, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance, Date startDate,
         Date endDate )
     {
-        List<Event> eventList = eventStore.getAll( program, organisationUnit, person, startDate, endDate );
+        List<Event> eventList = eventStore.getAll( program, organisationUnit, trackedEntityInstance, startDate, endDate );
         Events events = new Events();
         events.setEvents( eventList );
 
@@ -339,10 +338,10 @@
     }
 
     @Override
-    public Events getEvents( ProgramStage programStage, OrganisationUnit organisationUnit, Person person,
+    public Events getEvents( ProgramStage programStage, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance,
         Date startDate, Date endDate )
     {
-        List<Event> eventList = eventStore.getAll( programStage, organisationUnit, person, startDate, endDate );
+        List<Event> eventList = eventStore.getAll( programStage, organisationUnit, trackedEntityInstance, startDate, endDate );
         Events events = new Events();
         events.setEvents( eventList );
 
@@ -361,9 +360,9 @@
 
     @Override
     public Events getEvents( Program program, ProgramStage programStage, OrganisationUnit organisationUnit,
-        Person person )
+        TrackedEntityInstance trackedEntityInstance )
     {
-        List<Event> eventList = eventStore.getAll( program, programStage, organisationUnit, person );
+        List<Event> eventList = eventStore.getAll( program, programStage, organisationUnit, trackedEntityInstance );
         Events events = new Events();
         events.setEvents( eventList );
 
@@ -383,9 +382,9 @@
 
     @Override
     public Events getEvents( Program program, ProgramStage programStage, OrganisationUnit organisationUnit,
-        Person person, Date startDate, Date endDate )
+        TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate )
     {
-        List<Event> eventList = eventStore.getAll( program, programStage, organisationUnit, person, startDate, endDate );
+        List<Event> eventList = eventStore.getAll( program, programStage, organisationUnit, trackedEntityInstance, startDate, endDate );
         Events events = new Events();
         events.setEvents( eventList );
 
@@ -405,9 +404,9 @@
 
     @Override
     public Events getEvents( List<Program> programs, List<ProgramStage> programStages,
-        List<OrganisationUnit> organisationUnits, Person person, Date startDate, Date endDate )
+        List<OrganisationUnit> organisationUnits, TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate )
     {
-        List<Event> eventList = eventStore.getAll( programs, programStages, organisationUnits, person, startDate,
+        List<Event> eventList = eventStore.getAll( programs, programStages, organisationUnits, trackedEntityInstance, startDate,
             endDate );
         Events events = new Events();
         events.setEvents( eventList );

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/DefaultEventStore.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/DefaultEventStore.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/DefaultEventStore.java	2014-03-17 08:06:21 +0000
@@ -31,12 +31,11 @@
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
-import org.hisp.dhis.dxf2.events.person.Person;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.system.util.TextUtils;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
 import org.hisp.dhis.trackedentity.TrackedEntityInstanceService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -81,11 +80,11 @@
     }
 
     @Override
-    public List<Event> getAll( Program program, OrganisationUnit organisationUnit, Person person, Date startDate,
+    public List<Event> getAll( Program program, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance, Date startDate,
         Date endDate )
     {
         return getAll( Arrays.asList( program ), new ArrayList<ProgramStage>(), Arrays.asList( organisationUnit ),
-            person, startDate, endDate );
+            trackedEntityInstance, startDate, endDate );
     }
 
     @Override
@@ -104,11 +103,11 @@
     }
 
     @Override
-    public List<Event> getAll( ProgramStage programStage, OrganisationUnit organisationUnit, Person person,
+    public List<Event> getAll( ProgramStage programStage, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance,
         Date startDate, Date endDate )
     {
         return getAll( new ArrayList<Program>(), Arrays.asList( programStage ), Arrays.asList( organisationUnit ),
-            person, startDate, endDate );
+            trackedEntityInstance, startDate, endDate );
     }
 
     @Override
@@ -120,10 +119,10 @@
 
     @Override
     public List<Event> getAll( Program program, ProgramStage programStage, OrganisationUnit organisationUnit,
-        Person person )
+        TrackedEntityInstance trackedEntityInstance )
     {
         return getAll( Arrays.asList( program ), Arrays.asList( programStage ), Arrays.asList( organisationUnit ),
-            person, null, null );
+            trackedEntityInstance, null, null );
     }
 
     @Override
@@ -136,10 +135,10 @@
 
     @Override
     public List<Event> getAll( Program program, ProgramStage programStage, OrganisationUnit organisationUnit,
-        Person person, Date startDate, Date endDate )
+        TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate )
     {
         return getAll( Arrays.asList( program ), Arrays.asList( programStage ), Arrays.asList( organisationUnit ),
-            person, startDate, endDate );
+            trackedEntityInstance, startDate, endDate );
     }
 
     @Override
@@ -165,15 +164,15 @@
 
     @Override
     public List<Event> getAll( List<Program> programs, List<ProgramStage> programStages,
-        List<OrganisationUnit> organisationUnits, Person person, Date startDate, Date endDate )
+        List<OrganisationUnit> organisationUnits, TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate )
     {
         List<Event> events = new ArrayList<Event>();
 
         Integer personId = null;
 
-        if ( person != null )
+        if ( trackedEntityInstance != null )
         {
-            TrackedEntityInstance entityInstance = entityInstanceService.getTrackedEntityInstance( person.getPerson() );
+            org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = entityInstanceService.getTrackedEntityInstance( trackedEntityInstance.getTrackedEntityInstance() );
 
             if ( entityInstance != null )
             {

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventService.java	2014-02-20 10:21:30 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventService.java	2014-03-17 08:06:21 +0000
@@ -33,7 +33,7 @@
 import java.util.Date;
 import java.util.List;
 
-import org.hisp.dhis.dxf2.events.person.Person;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
 import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
 import org.hisp.dhis.dxf2.metadata.ImportOptions;
@@ -56,25 +56,25 @@
 
     Events getEvents( Program program, OrganisationUnit organisationUnit, Date startDate, Date endDate );
 
-    Events getEvents( Program program, OrganisationUnit organisationUnit, Person person, Date startDate, Date endDate );
+    Events getEvents( Program program, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate );
 
     Events getEvents( ProgramStage programStage, OrganisationUnit organisationUnit );
 
     Events getEvents( ProgramStage programStage, OrganisationUnit organisationUnit, Date startDate, Date endDate );
 
-    Events getEvents( ProgramStage programStage, OrganisationUnit organisationUnit, Person person, Date startDate, Date endDate );
+    Events getEvents( ProgramStage programStage, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate );
 
     Events getEvents( Program program, ProgramStage programStage, OrganisationUnit organisationUnit );
 
-    Events getEvents( Program program, ProgramStage programStage, OrganisationUnit organisationUnit, Person person );
+    Events getEvents( Program program, ProgramStage programStage, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance );
 
     Events getEvents( Program program, ProgramStage programStage, OrganisationUnit organisationUnit, Date startDate, Date endDate );
 
-    Events getEvents( Program program, ProgramStage programStage, OrganisationUnit organisationUnit, Person person, Date startDate, Date endDate );
+    Events getEvents( Program program, ProgramStage programStage, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate );
 
     Events getEvents( List<Program> programs, List<ProgramStage> programStages, List<OrganisationUnit> organisationUnits, Date startDate, Date endDate );
 
-    Events getEvents( List<Program> programs, List<ProgramStage> programStages, List<OrganisationUnit> organisationUnits, Person person, Date startDate, Date endDate );
+    Events getEvents( List<Program> programs, List<ProgramStage> programStages, List<OrganisationUnit> organisationUnits, TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate );
 
     Event getEvent( String uid );
 

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventStore.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventStore.java	2013-11-19 10:02:44 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventStore.java	2014-03-17 08:06:21 +0000
@@ -28,7 +28,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import org.hisp.dhis.dxf2.events.person.Person;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramStage;
@@ -51,7 +51,7 @@
 
     List<Event> getAll( Program program, ProgramStage programStage, OrganisationUnit organisationUnit );
 
-    List<Event> getAll( Program program, ProgramStage programStage, OrganisationUnit organisationUnit, Person person );
+    List<Event> getAll( Program program, ProgramStage programStage, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance );
 
     List<Event> getAll( Program program, ProgramStage programStage, OrganisationUnit organisationUnit, Date startDate, Date endDate );
 
@@ -60,13 +60,13 @@
     List<Event> getAll( Program program, List<ProgramStage> programStages, OrganisationUnit organisationUnit, Date startDate, Date endDate );
 
     List<Event> getAll( List<Program> programs, List<ProgramStage> programStages, List<OrganisationUnit> organisationUnits,
-        Person person, Date startDate, Date endDate );
-
-    List<Event> getAll( Program program, OrganisationUnit organisationUnit, Person person, Date startDate, Date endDate );
-
-    List<Event> getAll( ProgramStage programStage, OrganisationUnit organisationUnit, Person person, Date startDate, Date endDate );
-
-    List<Event> getAll( Program program, ProgramStage programStage, OrganisationUnit organisationUnit, Person person, Date startDate, Date endDate );
+        TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate );
+
+    List<Event> getAll( Program program, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate );
+
+    List<Event> getAll( ProgramStage programStage, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate );
+
+    List<Event> getAll( Program program, ProgramStage programStage, OrganisationUnit organisationUnit, TrackedEntityInstance trackedEntityInstance, Date startDate, Date endDate );
 
     List<Event> getAll( List<Program> programs, List<ProgramStage> programStages, List<OrganisationUnit> organisationUnits, Date startDate, Date endDate );
 }

=== removed file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/AbstractPersonService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/AbstractPersonService.java	2014-02-11 09:48:54 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/AbstractPersonService.java	1970-01-01 00:00:00 +0000
@@ -1,423 +0,0 @@
-package org.hisp.dhis.dxf2.events.person;
-
-/*
- * Copyright (c) 2004-2013, 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.IdentifiableObjectManager;
-import org.hisp.dhis.dxf2.importsummary.ImportConflict;
-import org.hisp.dhis.dxf2.importsummary.ImportStatus;
-import org.hisp.dhis.dxf2.importsummary.ImportSummary;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.program.Program;
-import org.hisp.dhis.relationship.Relationship;
-import org.hisp.dhis.relationship.RelationshipService;
-import org.hisp.dhis.relationship.RelationshipType;
-import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
-import org.hisp.dhis.trackedentity.TrackedEntityInstanceService;
-import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue;
-import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValueService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.Assert;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-public abstract class AbstractPersonService
-    implements PersonService
-{
-    // -------------------------------------------------------------------------
-    // Dependencies
-    // -------------------------------------------------------------------------
-
-    @Autowired
-    private TrackedEntityInstanceService entityInstanceService;
-
-    @Autowired
-    private TrackedEntityAttributeValueService attributeValueService;
-
-    @Autowired
-    private RelationshipService relationshipService;
-
-    @Autowired
-    private IdentifiableObjectManager manager;
-
-    // -------------------------------------------------------------------------
-    // READ
-    // -------------------------------------------------------------------------
-
-    @Override
-    public Persons getPersons()
-    {
-        List<TrackedEntityInstance> entityInstances = new ArrayList<TrackedEntityInstance>(
-            entityInstanceService.getAllTrackedEntityInstances() );
-        return getPersons( entityInstances );
-    }
-
-    @Override
-    public Persons getPersons( OrganisationUnit organisationUnit )
-    {
-        List<TrackedEntityInstance> entityInstances = new ArrayList<TrackedEntityInstance>(
-            entityInstanceService.getTrackedEntityInstances( organisationUnit, null, null ) );
-        return getPersons( entityInstances );
-    }
-
-    @Override
-    public Persons getPersons( Program program )
-    {
-        List<TrackedEntityInstance> entityInstances = new ArrayList<TrackedEntityInstance>(
-            entityInstanceService.getTrackedEntityInstances( program ) );
-        return getPersons( entityInstances );
-    }
-
-    @Override
-    public Persons getPersons( OrganisationUnit organisationUnit, Program program )
-    {
-        List<TrackedEntityInstance> entityInstances = new ArrayList<TrackedEntityInstance>(
-            entityInstanceService.getTrackedEntityInstances( organisationUnit, program ) );
-        return getPersons( entityInstances );
-    }
-
-    @Override
-    public Persons getPersons( Collection<TrackedEntityInstance> entityInstances )
-    {
-        Persons persons = new Persons();
-
-        for ( TrackedEntityInstance entityInstance : entityInstances )
-        {
-            persons.getPersons().add( getPerson( entityInstance ) );
-        }
-
-        return persons;
-    }
-
-    @Override
-    public Person getPerson( String uid )
-    {
-        return getPerson( entityInstanceService.getTrackedEntityInstance( uid ) );
-    }
-
-    @Override
-    public Person getPerson( TrackedEntityInstance entityInstance )
-    {
-        if ( entityInstance == null )
-        {
-            return null;
-        }
-
-        Person person = new Person();
-        person.setPerson( entityInstance.getUid() );
-        person.setOrgUnit( entityInstance.getOrganisationUnit().getUid() );
-
-        Collection<Relationship> relationships = relationshipService
-            .getRelationshipsForTrackedEntityInstance( entityInstance );
-
-        for ( Relationship entityRelationship : relationships )
-        {
-            org.hisp.dhis.dxf2.events.person.Relationship relationship = new org.hisp.dhis.dxf2.events.person.Relationship();
-            relationship.setDisplayName( entityRelationship.getRelationshipType().getDisplayName() );
-            relationship.setPerson( entityRelationship.getEntityInstanceA().getUid() );
-            relationship.setType( entityRelationship.getRelationshipType().getUid() );
-
-            person.getRelationships().add( relationship );
-        }
-
-        Collection<TrackedEntityAttributeValue> attributeValues = attributeValueService
-            .getTrackedEntityAttributeValues( entityInstance );
-
-        for ( TrackedEntityAttributeValue attributeValue : attributeValues )
-        {
-            Attribute attribute = new Attribute();
-
-            attribute.setDisplayName( attributeValue.getAttribute().getDisplayName() );
-            attribute.setAttribute( attributeValue.getAttribute().getUid() );
-            attribute.setType( attributeValue.getAttribute().getValueType() );
-            attribute.setCode( attributeValue.getAttribute().getCode() );
-            attribute.setValue( attributeValue.getValue() );
-
-            person.getAttributes().add( attribute );
-        }
-
-        return person;
-    }
-
-    public TrackedEntityInstance getTrackedEntityInstance( Person person )
-    {
-        Assert.hasText( person.getOrgUnit() );
-
-        TrackedEntityInstance entityInstance = new TrackedEntityInstance();
-
-        OrganisationUnit organisationUnit = manager.get( OrganisationUnit.class, person.getOrgUnit() );
-        Assert.notNull( organisationUnit );
-
-        entityInstance.setOrganisationUnit( organisationUnit );
-
-        return entityInstance;
-    }
-
-    // -------------------------------------------------------------------------
-    // CREATE
-    // -------------------------------------------------------------------------
-
-    @Override
-    public ImportSummary savePerson( Person person )
-    {
-        ImportSummary importSummary = new ImportSummary();
-        importSummary.setDataValueCount( null );
-
-        List<ImportConflict> importConflicts = new ArrayList<ImportConflict>();
-        importConflicts.addAll( checkAttributes( person ) );
-
-        importSummary.setConflicts( importConflicts );
-
-        if ( !importConflicts.isEmpty() )
-        {
-            importSummary.setStatus( ImportStatus.ERROR );
-            importSummary.getImportCount().incrementIgnored();
-            return importSummary;
-        }
-
-        TrackedEntityInstance entityInstance = getTrackedEntityInstance( person );
-        entityInstanceService.saveTrackedEntityInstance( entityInstance );
-
-        updateAttributeValues( person, entityInstance );
-        entityInstanceService.updateTrackedEntityInstance( entityInstance );
-
-        importSummary.setStatus( ImportStatus.SUCCESS );
-        importSummary.setReference( entityInstance.getUid() );
-        importSummary.getImportCount().incrementImported();
-
-        return importSummary;
-    }
-
-    // -------------------------------------------------------------------------
-    // UPDATE
-    // -------------------------------------------------------------------------
-
-    @Override
-    public ImportSummary updatePerson( Person person )
-    {
-        ImportSummary importSummary = new ImportSummary();
-        importSummary.setDataValueCount( null );
-
-        List<ImportConflict> importConflicts = new ArrayList<ImportConflict>();
-        importConflicts.addAll( checkRelationships( person ) );
-        importConflicts.addAll( checkAttributes( person ) );
-
-        TrackedEntityInstance entityInstance = manager.get( TrackedEntityInstance.class, person.getPerson() );
-
-        if ( entityInstance == null )
-        {
-            importConflicts.add( new ImportConflict( "Person", "person " + person.getPerson()
-                + " does not point to valid person" ) );
-        }
-
-        OrganisationUnit organisationUnit = manager.get( OrganisationUnit.class, person.getOrgUnit() );
-
-        if ( organisationUnit == null )
-        {
-            importConflicts.add( new ImportConflict( "OrganisationUnit", "orgUnit " + person.getOrgUnit()
-                + " does not point to valid organisation unit" ) );
-        }
-
-        importSummary.setConflicts( importConflicts );
-
-        if ( !importConflicts.isEmpty() )
-        {
-            importSummary.setStatus( ImportStatus.ERROR );
-            importSummary.getImportCount().incrementIgnored();
-            return importSummary;
-        }
-
-        removeRelationships( entityInstance );
-        removeAttributeValues( entityInstance );
-        entityInstanceService.updateTrackedEntityInstance( entityInstance );
-
-        updateRelationships( person, entityInstance );
-        updateAttributeValues( person, entityInstance );
-        entityInstanceService.updateTrackedEntityInstance( entityInstance );
-
-        importSummary.setStatus( ImportStatus.SUCCESS );
-        importSummary.setReference( entityInstance.getUid() );
-        importSummary.getImportCount().incrementUpdated();
-
-        return importSummary;
-    }
-
-    // -------------------------------------------------------------------------
-    // DELETE
-    // -------------------------------------------------------------------------
-
-    @Override
-    public void deletePerson( Person person )
-    {
-        TrackedEntityInstance entityInstance = entityInstanceService.getTrackedEntityInstance( person.getPerson() );
-
-        if ( entityInstance != null )
-        {
-            entityInstanceService.deleteTrackedEntityInstance( entityInstance );
-        }
-        else
-        {
-            throw new IllegalArgumentException();
-        }
-    }
-
-    // -------------------------------------------------------------------------
-    // HELPERS
-    // -------------------------------------------------------------------------
-
-    private List<ImportConflict> checkAttributes( Person person )
-    {
-        List<ImportConflict> importConflicts = new ArrayList<ImportConflict>();
-        Collection<TrackedEntityAttribute> entityAttributes = manager.getAll( TrackedEntityAttribute.class );
-        Set<String> cache = new HashSet<String>();
-
-        for ( Attribute attribute : person.getAttributes() )
-        {
-            if ( attribute.getValue() != null )
-            {
-                cache.add( attribute.getAttribute() );
-            }
-        }
-
-        for ( TrackedEntityAttribute entityAttribute : entityAttributes )
-        {
-            if ( entityAttribute.isMandatory() )
-            {
-                if ( !cache.contains( entityAttribute.getUid() ) )
-                {
-                    importConflicts.add( new ImportConflict( "Attribute.type", "Missing required attribute type "
-                        + entityAttribute.getUid() ) );
-                }
-            }
-        }
-
-        for ( Attribute attribute : person.getAttributes() )
-        {
-            TrackedEntityAttribute entityAttribute = manager.get( TrackedEntityAttribute.class,
-                attribute.getAttribute() );
-
-            if ( entityAttribute == null )
-            {
-                importConflicts
-                    .add( new ImportConflict( "Attribute.type", "Invalid type " + attribute.getAttribute() ) );
-            }
-        }
-
-        return importConflicts;
-    }
-
-    private List<ImportConflict> checkRelationships( Person person )
-    {
-        List<ImportConflict> importConflicts = new ArrayList<ImportConflict>();
-
-        for ( org.hisp.dhis.dxf2.events.person.Relationship relationship : person.getRelationships() )
-        {
-            RelationshipType relationshipType = manager.get( RelationshipType.class, relationship.getType() );
-
-            if ( relationshipType == null )
-            {
-                importConflicts
-                    .add( new ImportConflict( "Relationship.type", "Invalid type " + relationship.getType() ) );
-            }
-
-            TrackedEntityInstance entityInstance = manager.get( TrackedEntityInstance.class, relationship.getPerson() );
-
-            if ( entityInstance == null )
-            {
-                importConflicts.add( new ImportConflict( "Relationship.person", "Invalid person "
-                    + relationship.getPerson() ) );
-            }
-        }
-
-        return importConflicts;
-    }
-
-    private void updateAttributeValues( Person person, TrackedEntityInstance entityInstance )
-    {
-        for ( Attribute attribute : person.getAttributes() )
-        {
-            TrackedEntityAttribute entityAttribute = manager.get( TrackedEntityAttribute.class,
-                attribute.getAttribute() );
-
-            if ( entityAttribute != null )
-            {
-                TrackedEntityAttributeValue attributeValue = new TrackedEntityAttributeValue();
-                attributeValue.setEntityInstance( entityInstance );
-                attributeValue.setValue( attribute.getValue() );
-                attributeValue.setAttribute( entityAttribute );
-
-                attributeValueService.saveTrackedEntityAttributeValue( attributeValue );
-            }
-        }
-    }
-
-    private void updateRelationships( Person person, TrackedEntityInstance entityInstance )
-    {
-        for ( org.hisp.dhis.dxf2.events.person.Relationship relationship : person.getRelationships() )
-        {
-            TrackedEntityInstance entityInstanceB = manager.get( TrackedEntityInstance.class, relationship.getPerson() );
-            RelationshipType relationshipType = manager.get( RelationshipType.class, relationship.getType() );
-
-            Relationship entityRelationship = new Relationship();
-            entityRelationship.setEntityInstanceA( entityInstance );
-            entityRelationship.setEntityInstanceB( entityInstanceB );
-            entityRelationship.setRelationshipType( relationshipType );
-
-            relationshipService.saveRelationship( entityRelationship );
-        }
-    }
-
-    private void removeRelationships( TrackedEntityInstance entityInstance )
-    {
-        Collection<Relationship> relationships = relationshipService
-            .getRelationshipsForTrackedEntityInstance( entityInstance );
-
-        for ( Relationship relationship : relationships )
-        {
-            relationshipService.deleteRelationship( relationship );
-        }
-    }
-
-    private void removeAttributeValues( TrackedEntityInstance entityInstance )
-    {
-        for ( TrackedEntityAttributeValue trackedEntityAttributeValue : entityInstance.getAttributeValues() )
-        {
-            attributeValueService.deleteTrackedEntityAttributeValue( trackedEntityAttributeValue );
-        }
-
-        entityInstanceService.updateTrackedEntityInstance( entityInstance );
-    }
-}

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/AbstractTrackedEntityInstanceService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/AbstractTrackedEntityInstanceService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/AbstractTrackedEntityInstanceService.java	2014-03-17 08:06:21 +0000
@@ -0,0 +1,421 @@
+package org.hisp.dhis.dxf2.events.person;
+
+/*
+ * Copyright (c) 2004-2013, 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.IdentifiableObjectManager;
+import org.hisp.dhis.dxf2.importsummary.ImportConflict;
+import org.hisp.dhis.dxf2.importsummary.ImportStatus;
+import org.hisp.dhis.dxf2.importsummary.ImportSummary;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.relationship.Relationship;
+import org.hisp.dhis.relationship.RelationshipService;
+import org.hisp.dhis.relationship.RelationshipType;
+import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
+import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue;
+import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValueService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.Assert;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public abstract class AbstractTrackedEntityInstanceService
+    implements TrackedEntityInstanceService
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private org.hisp.dhis.trackedentity.TrackedEntityInstanceService entityInstanceService;
+
+    @Autowired
+    private TrackedEntityAttributeValueService attributeValueService;
+
+    @Autowired
+    private RelationshipService relationshipService;
+
+    @Autowired
+    private IdentifiableObjectManager manager;
+
+    // -------------------------------------------------------------------------
+    // READ
+    // -------------------------------------------------------------------------
+
+    @Override
+    public TrackedEntityInstances getPersons()
+    {
+        List<org.hisp.dhis.trackedentity.TrackedEntityInstance> entityInstances = new ArrayList<org.hisp.dhis.trackedentity.TrackedEntityInstance>(
+            entityInstanceService.getAllTrackedEntityInstances() );
+        return getPersons( entityInstances );
+    }
+
+    @Override
+    public TrackedEntityInstances getPersons( OrganisationUnit organisationUnit )
+    {
+        List<org.hisp.dhis.trackedentity.TrackedEntityInstance> entityInstances = new ArrayList<org.hisp.dhis.trackedentity.TrackedEntityInstance>(
+            entityInstanceService.getTrackedEntityInstances( organisationUnit, null, null ) );
+        return getPersons( entityInstances );
+    }
+
+    @Override
+    public TrackedEntityInstances getPersons( Program program )
+    {
+        List<org.hisp.dhis.trackedentity.TrackedEntityInstance> entityInstances = new ArrayList<org.hisp.dhis.trackedentity.TrackedEntityInstance>(
+            entityInstanceService.getTrackedEntityInstances( program ) );
+        return getPersons( entityInstances );
+    }
+
+    @Override
+    public TrackedEntityInstances getPersons( OrganisationUnit organisationUnit, Program program )
+    {
+        List<org.hisp.dhis.trackedentity.TrackedEntityInstance> entityInstances = new ArrayList<org.hisp.dhis.trackedentity.TrackedEntityInstance>(
+            entityInstanceService.getTrackedEntityInstances( organisationUnit, program ) );
+        return getPersons( entityInstances );
+    }
+
+    @Override
+    public TrackedEntityInstances getPersons( Collection<org.hisp.dhis.trackedentity.TrackedEntityInstance> entityInstances )
+    {
+        TrackedEntityInstances trackedEntityInstances = new TrackedEntityInstances();
+
+        for ( org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance : entityInstances )
+        {
+            trackedEntityInstances.getTrackedEntityInstances().add( getPerson( entityInstance ) );
+        }
+
+        return trackedEntityInstances;
+    }
+
+    @Override
+    public TrackedEntityInstance getPerson( String uid )
+    {
+        return getPerson( entityInstanceService.getTrackedEntityInstance( uid ) );
+    }
+
+    @Override
+    public TrackedEntityInstance getPerson( org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance )
+    {
+        if ( entityInstance == null )
+        {
+            return null;
+        }
+
+        TrackedEntityInstance trackedEntityInstance = new TrackedEntityInstance();
+        trackedEntityInstance.setTrackedEntityInstance( entityInstance.getUid() );
+        trackedEntityInstance.setOrgUnit( entityInstance.getOrganisationUnit().getUid() );
+
+        Collection<Relationship> relationships = relationshipService
+            .getRelationshipsForTrackedEntityInstance( entityInstance );
+
+        for ( Relationship entityRelationship : relationships )
+        {
+            org.hisp.dhis.dxf2.events.person.Relationship relationship = new org.hisp.dhis.dxf2.events.person.Relationship();
+            relationship.setDisplayName( entityRelationship.getRelationshipType().getDisplayName() );
+            relationship.setPerson( entityRelationship.getEntityInstanceA().getUid() );
+            relationship.setType( entityRelationship.getRelationshipType().getUid() );
+
+            trackedEntityInstance.getRelationships().add( relationship );
+        }
+
+        Collection<TrackedEntityAttributeValue> attributeValues = attributeValueService
+            .getTrackedEntityAttributeValues( entityInstance );
+
+        for ( TrackedEntityAttributeValue attributeValue : attributeValues )
+        {
+            Attribute attribute = new Attribute();
+
+            attribute.setDisplayName( attributeValue.getAttribute().getDisplayName() );
+            attribute.setAttribute( attributeValue.getAttribute().getUid() );
+            attribute.setType( attributeValue.getAttribute().getValueType() );
+            attribute.setCode( attributeValue.getAttribute().getCode() );
+            attribute.setValue( attributeValue.getValue() );
+
+            trackedEntityInstance.getAttributes().add( attribute );
+        }
+
+        return trackedEntityInstance;
+    }
+
+    public org.hisp.dhis.trackedentity.TrackedEntityInstance getTrackedEntityInstance( TrackedEntityInstance trackedEntityInstance )
+    {
+        Assert.hasText( trackedEntityInstance.getOrgUnit() );
+
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = new org.hisp.dhis.trackedentity.TrackedEntityInstance();
+
+        OrganisationUnit organisationUnit = manager.get( OrganisationUnit.class, trackedEntityInstance.getOrgUnit() );
+        Assert.notNull( organisationUnit );
+
+        entityInstance.setOrganisationUnit( organisationUnit );
+
+        return entityInstance;
+    }
+
+    // -------------------------------------------------------------------------
+    // CREATE
+    // -------------------------------------------------------------------------
+
+    @Override
+    public ImportSummary savePerson( TrackedEntityInstance trackedEntityInstance )
+    {
+        ImportSummary importSummary = new ImportSummary();
+        importSummary.setDataValueCount( null );
+
+        List<ImportConflict> importConflicts = new ArrayList<ImportConflict>();
+        importConflicts.addAll( checkAttributes( trackedEntityInstance ) );
+
+        importSummary.setConflicts( importConflicts );
+
+        if ( !importConflicts.isEmpty() )
+        {
+            importSummary.setStatus( ImportStatus.ERROR );
+            importSummary.getImportCount().incrementIgnored();
+            return importSummary;
+        }
+
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance );
+        entityInstanceService.saveTrackedEntityInstance( entityInstance );
+
+        updateAttributeValues( trackedEntityInstance, entityInstance );
+        entityInstanceService.updateTrackedEntityInstance( entityInstance );
+
+        importSummary.setStatus( ImportStatus.SUCCESS );
+        importSummary.setReference( entityInstance.getUid() );
+        importSummary.getImportCount().incrementImported();
+
+        return importSummary;
+    }
+
+    // -------------------------------------------------------------------------
+    // UPDATE
+    // -------------------------------------------------------------------------
+
+    @Override
+    public ImportSummary updatePerson( TrackedEntityInstance trackedEntityInstance )
+    {
+        ImportSummary importSummary = new ImportSummary();
+        importSummary.setDataValueCount( null );
+
+        List<ImportConflict> importConflicts = new ArrayList<ImportConflict>();
+        importConflicts.addAll( checkRelationships( trackedEntityInstance ) );
+        importConflicts.addAll( checkAttributes( trackedEntityInstance ) );
+
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = manager.get( org.hisp.dhis.trackedentity.TrackedEntityInstance.class, trackedEntityInstance.getTrackedEntityInstance() );
+
+        if ( entityInstance == null )
+        {
+            importConflicts.add( new ImportConflict( "Person", "person " + trackedEntityInstance.getTrackedEntityInstance()
+                + " does not point to valid person" ) );
+        }
+
+        OrganisationUnit organisationUnit = manager.get( OrganisationUnit.class, trackedEntityInstance.getOrgUnit() );
+
+        if ( organisationUnit == null )
+        {
+            importConflicts.add( new ImportConflict( "OrganisationUnit", "orgUnit " + trackedEntityInstance.getOrgUnit()
+                + " does not point to valid organisation unit" ) );
+        }
+
+        importSummary.setConflicts( importConflicts );
+
+        if ( !importConflicts.isEmpty() )
+        {
+            importSummary.setStatus( ImportStatus.ERROR );
+            importSummary.getImportCount().incrementIgnored();
+            return importSummary;
+        }
+
+        removeRelationships( entityInstance );
+        removeAttributeValues( entityInstance );
+        entityInstanceService.updateTrackedEntityInstance( entityInstance );
+
+        updateRelationships( trackedEntityInstance, entityInstance );
+        updateAttributeValues( trackedEntityInstance, entityInstance );
+        entityInstanceService.updateTrackedEntityInstance( entityInstance );
+
+        importSummary.setStatus( ImportStatus.SUCCESS );
+        importSummary.setReference( entityInstance.getUid() );
+        importSummary.getImportCount().incrementUpdated();
+
+        return importSummary;
+    }
+
+    // -------------------------------------------------------------------------
+    // DELETE
+    // -------------------------------------------------------------------------
+
+    @Override
+    public void deletePerson( TrackedEntityInstance trackedEntityInstance )
+    {
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = entityInstanceService.getTrackedEntityInstance( trackedEntityInstance.getTrackedEntityInstance() );
+
+        if ( entityInstance != null )
+        {
+            entityInstanceService.deleteTrackedEntityInstance( entityInstance );
+        }
+        else
+        {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    // -------------------------------------------------------------------------
+    // HELPERS
+    // -------------------------------------------------------------------------
+
+    private List<ImportConflict> checkAttributes( TrackedEntityInstance trackedEntityInstance )
+    {
+        List<ImportConflict> importConflicts = new ArrayList<ImportConflict>();
+        Collection<TrackedEntityAttribute> entityAttributes = manager.getAll( TrackedEntityAttribute.class );
+        Set<String> cache = new HashSet<String>();
+
+        for ( Attribute attribute : trackedEntityInstance.getAttributes() )
+        {
+            if ( attribute.getValue() != null )
+            {
+                cache.add( attribute.getAttribute() );
+            }
+        }
+
+        for ( TrackedEntityAttribute entityAttribute : entityAttributes )
+        {
+            if ( entityAttribute.isMandatory() )
+            {
+                if ( !cache.contains( entityAttribute.getUid() ) )
+                {
+                    importConflicts.add( new ImportConflict( "Attribute.type", "Missing required attribute type "
+                        + entityAttribute.getUid() ) );
+                }
+            }
+        }
+
+        for ( Attribute attribute : trackedEntityInstance.getAttributes() )
+        {
+            TrackedEntityAttribute entityAttribute = manager.get( TrackedEntityAttribute.class,
+                attribute.getAttribute() );
+
+            if ( entityAttribute == null )
+            {
+                importConflicts
+                    .add( new ImportConflict( "Attribute.type", "Invalid type " + attribute.getAttribute() ) );
+            }
+        }
+
+        return importConflicts;
+    }
+
+    private List<ImportConflict> checkRelationships( TrackedEntityInstance trackedEntityInstance )
+    {
+        List<ImportConflict> importConflicts = new ArrayList<ImportConflict>();
+
+        for ( org.hisp.dhis.dxf2.events.person.Relationship relationship : trackedEntityInstance.getRelationships() )
+        {
+            RelationshipType relationshipType = manager.get( RelationshipType.class, relationship.getType() );
+
+            if ( relationshipType == null )
+            {
+                importConflicts
+                    .add( new ImportConflict( "Relationship.type", "Invalid type " + relationship.getType() ) );
+            }
+
+            org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = manager.get( org.hisp.dhis.trackedentity.TrackedEntityInstance.class, relationship.getPerson() );
+
+            if ( entityInstance == null )
+            {
+                importConflicts.add( new ImportConflict( "Relationship.person", "Invalid person "
+                    + relationship.getPerson() ) );
+            }
+        }
+
+        return importConflicts;
+    }
+
+    private void updateAttributeValues( TrackedEntityInstance trackedEntityInstance, org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance )
+    {
+        for ( Attribute attribute : trackedEntityInstance.getAttributes() )
+        {
+            TrackedEntityAttribute entityAttribute = manager.get( TrackedEntityAttribute.class,
+                attribute.getAttribute() );
+
+            if ( entityAttribute != null )
+            {
+                TrackedEntityAttributeValue attributeValue = new TrackedEntityAttributeValue();
+                attributeValue.setEntityInstance( entityInstance );
+                attributeValue.setValue( attribute.getValue() );
+                attributeValue.setAttribute( entityAttribute );
+
+                attributeValueService.saveTrackedEntityAttributeValue( attributeValue );
+            }
+        }
+    }
+
+    private void updateRelationships( TrackedEntityInstance trackedEntityInstance, org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance )
+    {
+        for ( org.hisp.dhis.dxf2.events.person.Relationship relationship : trackedEntityInstance.getRelationships() )
+        {
+            org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstanceB = manager.get( org.hisp.dhis.trackedentity.TrackedEntityInstance.class, relationship.getPerson() );
+            RelationshipType relationshipType = manager.get( RelationshipType.class, relationship.getType() );
+
+            Relationship entityRelationship = new Relationship();
+            entityRelationship.setEntityInstanceA( entityInstance );
+            entityRelationship.setEntityInstanceB( entityInstanceB );
+            entityRelationship.setRelationshipType( relationshipType );
+
+            relationshipService.saveRelationship( entityRelationship );
+        }
+    }
+
+    private void removeRelationships( org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance )
+    {
+        Collection<Relationship> relationships = relationshipService
+            .getRelationshipsForTrackedEntityInstance( entityInstance );
+
+        for ( Relationship relationship : relationships )
+        {
+            relationshipService.deleteRelationship( relationship );
+        }
+    }
+
+    private void removeAttributeValues( org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance )
+    {
+        for ( TrackedEntityAttributeValue trackedEntityAttributeValue : entityInstance.getAttributeValues() )
+        {
+            attributeValueService.deleteTrackedEntityAttributeValue( trackedEntityAttributeValue );
+        }
+
+        entityInstanceService.updateTrackedEntityInstance( entityInstance );
+    }
+}

=== removed file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/JacksonPersonService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/JacksonPersonService.java	2014-01-24 08:41:50 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/JacksonPersonService.java	1970-01-01 00:00:00 +0000
@@ -1,169 +0,0 @@
-package org.hisp.dhis.dxf2.events.person;
-
-/*
- * Copyright (c) 2004-2013, 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.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-
-import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
-import org.hisp.dhis.dxf2.importsummary.ImportSummary;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.StreamUtils;
-
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.dataformat.xml.XmlMapper;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-@Transactional
-public class JacksonPersonService extends AbstractPersonService
-{
-    // -------------------------------------------------------------------------
-    // Implementation
-    // -------------------------------------------------------------------------
-
-    private final static ObjectMapper xmlMapper = new XmlMapper();
-
-    private final static ObjectMapper jsonMapper = new ObjectMapper();
-
-    @SuppressWarnings( "unchecked" )
-    private static <T> T fromXml( InputStream inputStream, Class<?> clazz ) throws IOException
-    {
-        return (T) xmlMapper.readValue( inputStream, clazz );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private static <T> T fromXml( String input, Class<?> clazz ) throws IOException
-    {
-        return (T) xmlMapper.readValue( input, clazz );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private static <T> T fromJson( InputStream inputStream, Class<?> clazz ) throws IOException
-    {
-        return (T) jsonMapper.readValue( inputStream, clazz );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private static <T> T fromJson( String input, Class<?> clazz ) throws IOException
-    {
-        return (T) jsonMapper.readValue( input, clazz );
-    }
-
-    static
-    {
-        xmlMapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true );
-        xmlMapper.configure( DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true );
-        xmlMapper.configure( DeserializationFeature.WRAP_EXCEPTIONS, true );
-        jsonMapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true );
-        jsonMapper.configure( DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true );
-        jsonMapper.configure( DeserializationFeature.WRAP_EXCEPTIONS, true );
-    }
-
-    // -------------------------------------------------------------------------
-    // CREATE
-    // -------------------------------------------------------------------------
-
-    @Override
-    public ImportSummaries savePersonXml( InputStream inputStream ) throws IOException
-    {
-        ImportSummaries importSummaries = new ImportSummaries();
-        String input = StreamUtils.copyToString( inputStream, Charset.forName( "UTF-8" ) );
-
-        try
-        {
-            Persons persons = fromXml( input, Persons.class );
-
-            for ( Person person : persons.getPersons() )
-            {
-                person.setPerson( null );
-                importSummaries.addImportSummary( savePerson( person ) );
-            }
-        }
-        catch ( Exception ex )
-        {
-            Person person = fromXml( input, Person.class );
-            person.setPerson( null );
-            importSummaries.addImportSummary( savePerson( person ) );
-        }
-
-        return importSummaries;
-    }
-
-    @Override
-    public ImportSummaries savePersonJson( InputStream inputStream ) throws IOException
-    {
-        ImportSummaries importSummaries = new ImportSummaries();
-        String input = StreamUtils.copyToString( inputStream, Charset.forName( "UTF-8" ) );
-
-        try
-        {
-            Persons persons = fromJson( input, Persons.class );
-
-            for ( Person person : persons.getPersons() )
-            {
-                person.setPerson( null );
-                importSummaries.addImportSummary( savePerson( person ) );
-            }
-        }
-        catch ( Exception ex )
-        {
-            Person person = fromJson( input, Person.class );
-            person.setPerson( null );
-            importSummaries.addImportSummary( savePerson( person ) );
-        }
-
-        return importSummaries;
-    }
-
-    // -------------------------------------------------------------------------
-    // UPDATE
-    // -------------------------------------------------------------------------
-
-    @Override
-    public ImportSummary updatePersonXml( String id, InputStream inputStream ) throws IOException
-    {
-        Person person = fromXml( inputStream, Person.class );
-        person.setPerson( id );
-
-        return updatePerson( person );
-    }
-
-    @Override
-    public ImportSummary updatePersonJson( String id, InputStream inputStream ) throws IOException
-    {
-        Person person = fromJson( inputStream, Person.class );
-        person.setPerson( id );
-
-        return updatePerson( person );
-    }
-}

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/JacksonTrackedEntityInstanceService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/JacksonTrackedEntityInstanceService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/JacksonTrackedEntityInstanceService.java	2014-03-17 08:06:21 +0000
@@ -0,0 +1,169 @@
+package org.hisp.dhis.dxf2.events.person;
+
+/*
+ * Copyright (c) 2004-2013, 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.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+
+import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
+import org.hisp.dhis.dxf2.importsummary.ImportSummary;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StreamUtils;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@Transactional
+public class JacksonTrackedEntityInstanceService extends AbstractTrackedEntityInstanceService
+{
+    // -------------------------------------------------------------------------
+    // Implementation
+    // -------------------------------------------------------------------------
+
+    private final static ObjectMapper xmlMapper = new XmlMapper();
+
+    private final static ObjectMapper jsonMapper = new ObjectMapper();
+
+    @SuppressWarnings( "unchecked" )
+    private static <T> T fromXml( InputStream inputStream, Class<?> clazz ) throws IOException
+    {
+        return (T) xmlMapper.readValue( inputStream, clazz );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private static <T> T fromXml( String input, Class<?> clazz ) throws IOException
+    {
+        return (T) xmlMapper.readValue( input, clazz );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private static <T> T fromJson( InputStream inputStream, Class<?> clazz ) throws IOException
+    {
+        return (T) jsonMapper.readValue( inputStream, clazz );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private static <T> T fromJson( String input, Class<?> clazz ) throws IOException
+    {
+        return (T) jsonMapper.readValue( input, clazz );
+    }
+
+    static
+    {
+        xmlMapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true );
+        xmlMapper.configure( DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true );
+        xmlMapper.configure( DeserializationFeature.WRAP_EXCEPTIONS, true );
+        jsonMapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true );
+        jsonMapper.configure( DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true );
+        jsonMapper.configure( DeserializationFeature.WRAP_EXCEPTIONS, true );
+    }
+
+    // -------------------------------------------------------------------------
+    // CREATE
+    // -------------------------------------------------------------------------
+
+    @Override
+    public ImportSummaries savePersonXml( InputStream inputStream ) throws IOException
+    {
+        ImportSummaries importSummaries = new ImportSummaries();
+        String input = StreamUtils.copyToString( inputStream, Charset.forName( "UTF-8" ) );
+
+        try
+        {
+            TrackedEntityInstances trackedEntityInstances = fromXml( input, TrackedEntityInstances.class );
+
+            for ( TrackedEntityInstance trackedEntityInstance : trackedEntityInstances.getTrackedEntityInstances() )
+            {
+                trackedEntityInstance.setTrackedEntityInstance( null );
+                importSummaries.addImportSummary( savePerson( trackedEntityInstance ) );
+            }
+        }
+        catch ( Exception ex )
+        {
+            TrackedEntityInstance trackedEntityInstance = fromXml( input, TrackedEntityInstance.class );
+            trackedEntityInstance.setTrackedEntityInstance( null );
+            importSummaries.addImportSummary( savePerson( trackedEntityInstance ) );
+        }
+
+        return importSummaries;
+    }
+
+    @Override
+    public ImportSummaries savePersonJson( InputStream inputStream ) throws IOException
+    {
+        ImportSummaries importSummaries = new ImportSummaries();
+        String input = StreamUtils.copyToString( inputStream, Charset.forName( "UTF-8" ) );
+
+        try
+        {
+            TrackedEntityInstances trackedEntityInstances = fromJson( input, TrackedEntityInstances.class );
+
+            for ( TrackedEntityInstance trackedEntityInstance : trackedEntityInstances.getTrackedEntityInstances() )
+            {
+                trackedEntityInstance.setTrackedEntityInstance( null );
+                importSummaries.addImportSummary( savePerson( trackedEntityInstance ) );
+            }
+        }
+        catch ( Exception ex )
+        {
+            TrackedEntityInstance trackedEntityInstance = fromJson( input, TrackedEntityInstance.class );
+            trackedEntityInstance.setTrackedEntityInstance( null );
+            importSummaries.addImportSummary( savePerson( trackedEntityInstance ) );
+        }
+
+        return importSummaries;
+    }
+
+    // -------------------------------------------------------------------------
+    // UPDATE
+    // -------------------------------------------------------------------------
+
+    @Override
+    public ImportSummary updatePersonXml( String id, InputStream inputStream ) throws IOException
+    {
+        TrackedEntityInstance trackedEntityInstance = fromXml( inputStream, TrackedEntityInstance.class );
+        trackedEntityInstance.setTrackedEntityInstance( id );
+
+        return updatePerson( trackedEntityInstance );
+    }
+
+    @Override
+    public ImportSummary updatePersonJson( String id, InputStream inputStream ) throws IOException
+    {
+        TrackedEntityInstance trackedEntityInstance = fromJson( inputStream, TrackedEntityInstance.class );
+        trackedEntityInstance.setTrackedEntityInstance( id );
+
+        return updatePerson( trackedEntityInstance );
+    }
+}

=== removed file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/Person.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/Person.java	2014-01-08 11:00:11 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/Person.java	1970-01-01 00:00:00 +0000
@@ -1,165 +0,0 @@
-package org.hisp.dhis.dxf2.events.person;
-
-/*
- * Copyright (c) 2004-2013, 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;
-
-import org.hisp.dhis.common.DxfNamespaces;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-@JacksonXmlRootElement( localName = "person", namespace = DxfNamespaces.DXF_2_0 )
-public class Person
-{
-    private String person;
-
-    private String orgUnit;
-
-    private List<Relationship> relationships = new ArrayList<Relationship>();
-
-    private List<Identifier> identifiers = new ArrayList<Identifier>();
-
-    private List<Attribute> attributes = new ArrayList<Attribute>();
-
-    public Person()
-    {
-    }
-
-    @JsonProperty( required = true )
-    @JacksonXmlProperty( isAttribute = true )
-    public String getPerson()
-    {
-        return person;
-    }
-
-    public void setPerson( String person )
-    {
-        this.person = person;
-    }
-
-    @JsonProperty( required = true )
-    @JacksonXmlProperty( isAttribute = true )
-    public String getOrgUnit()
-    {
-        return orgUnit;
-    }
-
-    public void setOrgUnit( String orgUnit )
-    {
-        this.orgUnit = orgUnit;
-    }
-
-    @JsonProperty
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
-    public List<Relationship> getRelationships()
-    {
-        return relationships;
-    }
-
-    public void setRelationships( List<Relationship> relationships )
-    {
-        this.relationships = relationships;
-    }
-
-    @JsonProperty
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
-    public List<Identifier> getIdentifiers()
-    {
-        return identifiers;
-    }
-
-    public void setIdentifiers( List<Identifier> identifiers )
-    {
-        this.identifiers = identifiers;
-    }
-
-    @JsonProperty
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
-    public List<Attribute> getAttributes()
-    {
-        return attributes;
-    }
-
-    public void setAttributes( List<Attribute> attributes )
-    {
-        this.attributes = attributes;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o )
-            return true;
-        if ( o == null || getClass() != o.getClass() )
-            return false;
-
-        Person person1 = (Person) o;
-        if ( attributes != null ? !attributes.equals( person1.attributes ) : person1.attributes != null )
-            return false;
-        if ( identifiers != null ? !identifiers.equals( person1.identifiers ) : person1.identifiers != null )
-            return false;
-        if ( orgUnit != null ? !orgUnit.equals( person1.orgUnit ) : person1.orgUnit != null )
-            return false;
-        if ( person != null ? !person.equals( person1.person ) : person1.person != null )
-            return false;
-        if ( relationships != null ? !relationships.equals( person1.relationships ) : person1.relationships != null )
-            return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        int result = person != null ? person.hashCode() : 0;
-        result = 31 * result + (orgUnit != null ? orgUnit.hashCode() : 0);
-        result = 31 * result + (relationships != null ? relationships.hashCode() : 0);
-        result = 31 * result + (identifiers != null ? identifiers.hashCode() : 0);
-        result = 31 * result + (attributes != null ? attributes.hashCode() : 0);
-        return result;
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Person{" +
-            "person='" + person + '\'' +
-            ", orgUnit='" + orgUnit + '\'' +
-            ", relationships=" + relationships +
-            ", identifiers=" + identifiers +
-            ", attributes=" + attributes +
-            '}';
-    }
-}

=== removed file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/PersonService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/PersonService.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/PersonService.java	1970-01-01 00:00:00 +0000
@@ -1,93 +0,0 @@
-package org.hisp.dhis.dxf2.events.person;
-
-/*
- * Copyright (c) 2004-2013, 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.io.IOException;
-import java.io.InputStream;
-import java.util.Collection;
-
-import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
-import org.hisp.dhis.dxf2.importsummary.ImportSummary;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.program.Program;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-public interface PersonService
-{
-    // -------------------------------------------------------------------------
-    // READ
-    // -------------------------------------------------------------------------
-
-    Persons getPersons();
-
-    Persons getPersons( OrganisationUnit organisationUnit );
-
-    Persons getPersons( Program program );
-
-    Persons getPersons( OrganisationUnit organisationUnit, Program program );
-
-    Persons getPersons( Collection<TrackedEntityInstance> entityInstances );
-
-    Person getPerson( String uid );
-
-    Person getPerson( TrackedEntityInstance entityInstance );
-
-    // -------------------------------------------------------------------------
-    // CREATE
-    // -------------------------------------------------------------------------
-
-    ImportSummaries savePersonXml( InputStream inputStream )
-        throws IOException;
-
-    ImportSummaries savePersonJson( InputStream inputStream )
-        throws IOException;
-
-    ImportSummary savePerson( Person person );
-
-    // -------------------------------------------------------------------------
-    // UPDATE
-    // -------------------------------------------------------------------------
-
-    ImportSummary updatePersonXml( String id, InputStream inputStream )
-        throws IOException;
-
-    ImportSummary updatePersonJson( String id, InputStream inputStream )
-        throws IOException;
-
-    ImportSummary updatePerson( Person person );
-
-    // -------------------------------------------------------------------------
-    // DELETE
-    // -------------------------------------------------------------------------
-
-    void deletePerson( Person person );
-}

=== removed file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/Persons.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/Persons.java	2013-09-17 12:15:39 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/Persons.java	1970-01-01 00:00:00 +0000
@@ -1,72 +0,0 @@
-package org.hisp.dhis.dxf2.events.person;
-
-/*
- * Copyright (c) 2004-2013, 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.annotation.JsonProperty;
-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.DxfNamespaces;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-@JacksonXmlRootElement( localName = "persons", namespace = DxfNamespaces.DXF_2_0 )
-public class Persons
-{
-    private List<Person> persons = new ArrayList<Person>();
-
-    public Persons()
-    {
-    }
-
-    @JsonProperty( "personList" )
-    @JacksonXmlElementWrapper( localName = "personList", namespace = DxfNamespaces.DXF_2_0 )
-    @JacksonXmlProperty( localName = "person", namespace = DxfNamespaces.DXF_2_0 )
-    public List<Person> getPersons()
-    {
-        return persons;
-    }
-
-    public void setPersons( List<Person> persons )
-    {
-        this.persons = persons;
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Persons{" +
-            "persons=" + persons +
-            '}';
-    }
-}

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstance.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstance.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstance.java	2014-03-17 08:06:21 +0000
@@ -0,0 +1,176 @@
+package org.hisp.dhis.dxf2.events.person;
+
+/*
+ * Copyright (c) 2004-2013, 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.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import org.hisp.dhis.common.DxfNamespaces;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@JacksonXmlRootElement( localName = "trackedEntityInstance", namespace = DxfNamespaces.DXF_2_0 )
+public class TrackedEntityInstance
+{
+    private String trackedEntity;
+
+    private String trackedEntityInstance;
+
+    private String orgUnit;
+
+    private List<Relationship> relationships = new ArrayList<Relationship>();
+
+    private List<Identifier> identifiers = new ArrayList<Identifier>();
+
+    private List<Attribute> attributes = new ArrayList<Attribute>();
+
+    public TrackedEntityInstance()
+    {
+    }
+
+    @JsonProperty( required = true )
+    @JacksonXmlProperty( isAttribute = true )
+    public String getTrackedEntity()
+    {
+        return trackedEntity;
+    }
+
+    public void setTrackedEntity( String trackedEntity )
+    {
+        this.trackedEntity = trackedEntity;
+    }
+
+    @JsonProperty( required = true )
+    @JacksonXmlProperty( isAttribute = true )
+    public String getTrackedEntityInstance()
+    {
+        return trackedEntityInstance;
+    }
+
+    public void setTrackedEntityInstance( String trackedEntityInstance )
+    {
+        this.trackedEntityInstance = trackedEntityInstance;
+    }
+
+    @JsonProperty( required = true )
+    @JacksonXmlProperty( isAttribute = true )
+    public String getOrgUnit()
+    {
+        return orgUnit;
+    }
+
+    public void setOrgUnit( String orgUnit )
+    {
+        this.orgUnit = orgUnit;
+    }
+
+    @JsonProperty
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public List<Relationship> getRelationships()
+    {
+        return relationships;
+    }
+
+    public void setRelationships( List<Relationship> relationships )
+    {
+        this.relationships = relationships;
+    }
+
+    @JsonProperty
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public List<Identifier> getIdentifiers()
+    {
+        return identifiers;
+    }
+
+    public void setIdentifiers( List<Identifier> identifiers )
+    {
+        this.identifiers = identifiers;
+    }
+
+    @JsonProperty
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public List<Attribute> getAttributes()
+    {
+        return attributes;
+    }
+
+    public void setAttributes( List<Attribute> attributes )
+    {
+        this.attributes = attributes;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass() != o.getClass() ) return false;
+
+        TrackedEntityInstance that = (TrackedEntityInstance) o;
+
+        if ( attributes != null ? !attributes.equals( that.attributes ) : that.attributes != null ) return false;
+        if ( identifiers != null ? !identifiers.equals( that.identifiers ) : that.identifiers != null ) return false;
+        if ( orgUnit != null ? !orgUnit.equals( that.orgUnit ) : that.orgUnit != null ) return false;
+        if ( relationships != null ? !relationships.equals( that.relationships ) : that.relationships != null ) return false;
+        if ( trackedEntity != null ? !trackedEntity.equals( that.trackedEntity ) : that.trackedEntity != null ) return false;
+        if ( trackedEntityInstance != null ? !trackedEntityInstance.equals( that.trackedEntityInstance ) : that.trackedEntityInstance != null )
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = trackedEntity != null ? trackedEntity.hashCode() : 0;
+        result = 31 * result + (trackedEntityInstance != null ? trackedEntityInstance.hashCode() : 0);
+        result = 31 * result + (orgUnit != null ? orgUnit.hashCode() : 0);
+        result = 31 * result + (relationships != null ? relationships.hashCode() : 0);
+        result = 31 * result + (identifiers != null ? identifiers.hashCode() : 0);
+        result = 31 * result + (attributes != null ? attributes.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "TrackedEntityInstance{" +
+            "trackedEntity='" + trackedEntity + '\'' +
+            ", trackedEntityInstance='" + trackedEntityInstance + '\'' +
+            ", orgUnit='" + orgUnit + '\'' +
+            ", relationships=" + relationships +
+            ", identifiers=" + identifiers +
+            ", attributes=" + attributes +
+            '}';
+    }
+}

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstanceService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstanceService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstanceService.java	2014-03-17 08:06:21 +0000
@@ -0,0 +1,92 @@
+package org.hisp.dhis.dxf2.events.person;
+
+/*
+ * Copyright (c) 2004-2013, 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.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+
+import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
+import org.hisp.dhis.dxf2.importsummary.ImportSummary;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.program.Program;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public interface TrackedEntityInstanceService
+{
+    // -------------------------------------------------------------------------
+    // READ
+    // -------------------------------------------------------------------------
+
+    TrackedEntityInstances getPersons();
+
+    TrackedEntityInstances getPersons( OrganisationUnit organisationUnit );
+
+    TrackedEntityInstances getPersons( Program program );
+
+    TrackedEntityInstances getPersons( OrganisationUnit organisationUnit, Program program );
+
+    TrackedEntityInstances getPersons( Collection<org.hisp.dhis.trackedentity.TrackedEntityInstance> entityInstances );
+
+    TrackedEntityInstance getPerson( String uid );
+
+    TrackedEntityInstance getPerson( org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance );
+
+    // -------------------------------------------------------------------------
+    // CREATE
+    // -------------------------------------------------------------------------
+
+    ImportSummaries savePersonXml( InputStream inputStream )
+        throws IOException;
+
+    ImportSummaries savePersonJson( InputStream inputStream )
+        throws IOException;
+
+    ImportSummary savePerson( TrackedEntityInstance trackedEntityInstance );
+
+    // -------------------------------------------------------------------------
+    // UPDATE
+    // -------------------------------------------------------------------------
+
+    ImportSummary updatePersonXml( String id, InputStream inputStream )
+        throws IOException;
+
+    ImportSummary updatePersonJson( String id, InputStream inputStream )
+        throws IOException;
+
+    ImportSummary updatePerson( TrackedEntityInstance trackedEntityInstance );
+
+    // -------------------------------------------------------------------------
+    // DELETE
+    // -------------------------------------------------------------------------
+
+    void deletePerson( TrackedEntityInstance trackedEntityInstance );
+}

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstances.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstances.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/TrackedEntityInstances.java	2014-03-17 08:06:21 +0000
@@ -0,0 +1,72 @@
+package org.hisp.dhis.dxf2.events.person;
+
+/*
+ * Copyright (c) 2004-2013, 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.annotation.JsonProperty;
+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.DxfNamespaces;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@JacksonXmlRootElement( localName = "trackedEntityInstances", namespace = DxfNamespaces.DXF_2_0 )
+public class TrackedEntityInstances
+{
+    private List<TrackedEntityInstance> trackedEntityInstances = new ArrayList<TrackedEntityInstance>();
+
+    public TrackedEntityInstances()
+    {
+    }
+
+    @JsonProperty( "trackedEntityInstanceList" )
+    @JacksonXmlElementWrapper( localName = "trackedEntityInstanceList", namespace = DxfNamespaces.DXF_2_0 )
+    @JacksonXmlProperty( localName = "trackedEntityInstance", namespace = DxfNamespaces.DXF_2_0 )
+    public List<TrackedEntityInstance> getTrackedEntityInstances()
+    {
+        return trackedEntityInstances;
+    }
+
+    public void setTrackedEntityInstances( List<TrackedEntityInstance> trackedEntityInstances )
+    {
+        this.trackedEntityInstances = trackedEntityInstances;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "TrackedEntityInstances{" +
+            "trackedEntityInstances=" + trackedEntityInstances +
+            '}';
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml	2014-03-14 10:25:42 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml	2014-03-17 08:06:21 +0000
@@ -30,7 +30,7 @@
 
   <bean id="org.hisp.dhis.dxf2.events.event.EventService" class="org.hisp.dhis.dxf2.events.event.JacksonEventService" />
 
-  <bean id="org.hisp.dhis.dxf2.events.person.PersonService" class="org.hisp.dhis.dxf2.events.person.JacksonPersonService" />
+  <bean id="org.hisp.dhis.dxf2.events.person.PersonService" class="org.hisp.dhis.dxf2.events.person.JacksonTrackedEntityInstanceService" />
 
   <bean id="org.hisp.dhis.dxf2.events.enrollment.EnrollmentService" class="org.hisp.dhis.dxf2.events.enrollment.JacksonEnrollmentService" />
 

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/EnrollmentServiceTest.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/EnrollmentServiceTest.java	2014-02-14 09:55:05 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/EnrollmentServiceTest.java	2014-03-17 08:06:21 +0000
@@ -42,8 +42,8 @@
 import org.hisp.dhis.dxf2.events.enrollment.Enrollment;
 import org.hisp.dhis.dxf2.events.enrollment.EnrollmentService;
 import org.hisp.dhis.dxf2.events.enrollment.EnrollmentStatus;
-import org.hisp.dhis.dxf2.events.person.Person;
-import org.hisp.dhis.dxf2.events.person.PersonService;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstanceService;
 import org.hisp.dhis.dxf2.importsummary.ImportStatus;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
 import org.hisp.dhis.i18n.I18nFormat;
@@ -53,7 +53,6 @@
 import org.hisp.dhis.program.ProgramInstance;
 import org.hisp.dhis.program.ProgramInstanceService;
 import org.hisp.dhis.program.ProgramStage;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -65,7 +64,7 @@
     extends DhisSpringTest
 {
     @Autowired
-    private PersonService personService;
+    private TrackedEntityInstanceService trackedEntityInstanceService;
 
     @Autowired
     private EnrollmentService enrollmentService;
@@ -76,10 +75,10 @@
     @Autowired
     private ProgramInstanceService programInstanceService;
 
-    private TrackedEntityInstance maleA;
-    private TrackedEntityInstance maleB;
-    private TrackedEntityInstance femaleA;
-    private TrackedEntityInstance femaleB;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance maleA;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance maleB;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance femaleA;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance femaleB;
 
     private OrganisationUnit organisationUnitA;
     private OrganisationUnit organisationUnitB;
@@ -147,8 +146,8 @@
         programInstanceService.enrollTrackedEntityInstance( maleA, programA, null, null, organisationUnitA, mock( I18nFormat.class ) );
         programInstanceService.enrollTrackedEntityInstance( femaleA, programA, null, null, organisationUnitA, mock( I18nFormat.class ) );
 
-        Person male = personService.getPerson( maleA );
-        Person female = personService.getPerson( femaleA );
+        TrackedEntityInstance male = trackedEntityInstanceService.getPerson( maleA );
+        TrackedEntityInstance female = trackedEntityInstanceService.getPerson( femaleA );
 
         assertEquals( 1, enrollmentService.getEnrollments( male ).getEnrollments().size() );
         assertEquals( 1, enrollmentService.getEnrollments( female ).getEnrollments().size() );
@@ -336,11 +335,11 @@
         ImportSummary importSummary = enrollmentService.saveEnrollment( enrollment );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
-        Person person = personService.getPerson( maleA );
+        TrackedEntityInstance trackedEntityInstance = trackedEntityInstanceService.getPerson( maleA );
         // person.setName( "Changed Name" );
-        personService.updatePerson( person );
+        trackedEntityInstanceService.updatePerson( trackedEntityInstance );
 
-        List<Enrollment> enrollments = enrollmentService.getEnrollments( person ).getEnrollments();
+        List<Enrollment> enrollments = enrollmentService.getEnrollments( trackedEntityInstance ).getEnrollments();
 
         assertEquals( 1, enrollments.size() );
         assertEquals( maleA.getUid(), enrollments.get( 0 ).getPerson() );

=== removed file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/PersonServiceTest.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/PersonServiceTest.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/PersonServiceTest.java	1970-01-01 00:00:00 +0000
@@ -1,189 +0,0 @@
-package org.hisp.dhis.dxf2.events;
-
-/*
- * Copyright (c) 2004-2013, 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.DhisTest;
-import org.hisp.dhis.common.IdentifiableObjectManager;
-import org.hisp.dhis.dxf2.events.person.Person;
-import org.hisp.dhis.dxf2.events.person.PersonService;
-import org.hisp.dhis.dxf2.importsummary.ImportStatus;
-import org.hisp.dhis.dxf2.importsummary.ImportSummary;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.program.Program;
-import org.hisp.dhis.program.ProgramInstanceService;
-import org.hisp.dhis.program.ProgramStage;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-
-import static org.junit.Assert.*;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-public class PersonServiceTest
-    extends DhisTest
-{
-    @Autowired
-    private PersonService personService;
-
-    @Autowired
-    private ProgramInstanceService programInstanceService;
-
-    @Autowired
-    private IdentifiableObjectManager manager;
-
-    private TrackedEntityInstance maleA;
-    private TrackedEntityInstance maleB;
-    private TrackedEntityInstance femaleA;
-    private TrackedEntityInstance femaleB;
-
-    private OrganisationUnit organisationUnitA;
-    private OrganisationUnit organisationUnitB;
-
-    private Program programA;
-
-    @Override
-    protected void setUpTest() throws Exception
-    {
-        organisationUnitA = createOrganisationUnit( 'A' );
-        organisationUnitB = createOrganisationUnit( 'B' );
-
-        organisationUnitB.setParent( organisationUnitA );
-
-        maleA = createTrackedEntityInstance(  'A', organisationUnitA );
-        maleB = createTrackedEntityInstance( 'B', organisationUnitB );
-        femaleA = createTrackedEntityInstance( 'C', organisationUnitA );
-        femaleB = createTrackedEntityInstance( 'D', organisationUnitB );
-
-        programA = createProgram( 'A', new HashSet<ProgramStage>(), organisationUnitA );
-        manager.save( organisationUnitA );
-        manager.save( organisationUnitB );
-        manager.save( maleA );
-        manager.save( maleB );
-        manager.save( femaleA );
-        manager.save( femaleB );
-        manager.save( programA );
-
-        programInstanceService.enrollTrackedEntityInstance( maleA, programA, null, null, organisationUnitA, null );
-        programInstanceService.enrollTrackedEntityInstance( femaleA, programA, null, null, organisationUnitA, null );
-    }
-
-    @Override
-    public boolean emptyDatabaseAfterTest()
-    {
-        return true;
-    }
-
-    @Test
-    public void testGetPersons()
-    {
-        assertEquals( 4, personService.getPersons().getPersons().size() );
-    }
-
-    @Test
-    public void testGetPersonByOrganisationUnit()
-    {
-        assertEquals( 2, personService.getPersons( organisationUnitA ).getPersons().size() );
-        assertEquals( 2, personService.getPersons( organisationUnitB ).getPersons().size() );
-    }
-
-    @Test
-    public void getPersonByPatients()
-    {
-        List<TrackedEntityInstance> patients = Arrays.asList( maleA, femaleB );
-        assertEquals( 2, personService.getPersons( patients ).getPersons().size() );
-    }
-
-    @Test
-    public void getPersonByUid()
-    {
-        assertEquals( maleA.getUid(), personService.getPerson( maleA.getUid() ).getPerson() );
-        assertEquals( femaleB.getUid(), personService.getPerson( femaleB.getUid() ).getPerson() );
-        assertNotEquals( femaleA.getUid(), personService.getPerson( femaleB.getUid() ).getPerson() );
-        assertNotEquals( maleA.getUid(), personService.getPerson( maleB.getUid() ).getPerson() );
-    }
-
-    @Test
-    public void getPersonByPatient()
-    {
-        assertEquals( maleA.getUid(), personService.getPerson( maleA ).getPerson() );
-        assertEquals( femaleB.getUid(), personService.getPerson( femaleB ).getPerson() );
-        assertNotEquals( femaleA.getUid(), personService.getPerson( femaleB ).getPerson() );
-        assertNotEquals( maleA.getUid(), personService.getPerson( maleB ).getPerson() );
-    }
-
-    @Test
-    public void testGetPersonByProgram()
-    {
-        assertEquals( 2, personService.getPersons( programA ).getPersons().size() );
-    }
-
-    @Test
-    @Ignore
-    public void testUpdatePerson()
-    {
-        Person person = personService.getPerson( maleA.getUid() );
-        // person.setName( "UPDATED_NAME" );
-
-        ImportSummary importSummary = personService.updatePerson( person );
-        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
-
-        // assertEquals( "UPDATED_NAME", personService.getPerson( maleA.getUid() ).getName() );
-    }
-
-    @Test
-    @Ignore
-    public void testSavePerson()
-    {
-        Person person = new Person();
-        // person.setName( "NAME" );
-        person.setOrgUnit( organisationUnitA.getUid() );
-
-        ImportSummary importSummary = personService.savePerson( person );
-        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
-
-        // assertEquals( "NAME", personService.getPerson( importSummary.getReference() ).getName() );
-    }
-
-    @Test
-    public void testDeletePerson()
-    {
-        Person person = personService.getPerson( maleA.getUid() );
-        personService.deletePerson( person );
-
-        assertNull( personService.getPerson( maleA.getUid() ) );
-        assertNotNull( personService.getPerson( maleB.getUid() ) );
-    }
-}

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationMultiEventsServiceTest.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationMultiEventsServiceTest.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationMultiEventsServiceTest.java	2014-03-17 08:06:21 +0000
@@ -42,8 +42,8 @@
 import org.hisp.dhis.dxf2.events.event.DataValue;
 import org.hisp.dhis.dxf2.events.event.Event;
 import org.hisp.dhis.dxf2.events.event.EventService;
-import org.hisp.dhis.dxf2.events.person.Person;
-import org.hisp.dhis.dxf2.events.person.PersonService;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstanceService;
 import org.hisp.dhis.dxf2.importsummary.ImportStatus;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
@@ -51,7 +51,6 @@
 import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.program.ProgramStageDataElement;
 import org.hisp.dhis.program.ProgramStageDataElementService;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
 import org.hisp.dhis.user.UserService;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -66,7 +65,7 @@
     private EventService eventService;
 
     @Autowired
-    private PersonService personService;
+    private TrackedEntityInstanceService trackedEntityInstanceService;
 
     @Autowired
     private ProgramStageDataElementService programStageDataElementService;
@@ -74,15 +73,15 @@
     @Autowired
     private EnrollmentService enrollmentService;
 
-    private TrackedEntityInstance maleA;
-
-    private TrackedEntityInstance maleB;
-
-    private TrackedEntityInstance femaleA;
-
-    private TrackedEntityInstance femaleB;
-
-    private Person personMaleA;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance maleA;
+
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance maleB;
+
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance femaleA;
+
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance femaleB;
+
+    private TrackedEntityInstance trackedEntityInstanceMaleA;
 
     private OrganisationUnit organisationUnitA;
 
@@ -120,7 +119,7 @@
         identifiableObjectManager.save( femaleA );
         identifiableObjectManager.save( femaleB );
 
-        personMaleA = personService.getPerson( maleA );
+        trackedEntityInstanceMaleA = trackedEntityInstanceService.getPerson( maleA );
 
         dataElementA = createDataElement( 'A' );
         dataElementB = createDataElement( 'B' );
@@ -177,7 +176,7 @@
     @Test
     public void testSaveWithoutProgramStageShouldFail()
     {
-        Event event = createEvent( programA.getUid(), null, organisationUnitA.getUid(), personMaleA.getPerson(),
+        Event event = createEvent( programA.getUid(), null, organisationUnitA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance(),
             dataElementA.getUid() );
         ImportSummary importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.ERROR, importSummary.getStatus() );
@@ -189,7 +188,7 @@
     public void testSaveWithoutEnrollmentShouldFail()
     {
         Event event = createEvent( programA.getUid(), programStageA.getUid(), organisationUnitA.getUid(),
-            personMaleA.getPerson(), dataElementA.getUid() );
+            trackedEntityInstanceMaleA.getTrackedEntityInstance(), dataElementA.getUid() );
         ImportSummary importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.ERROR, importSummary.getStatus() );
         assertThat( importSummary.getDescription(), CoreMatchers.containsString( "is not enrolled in program" ) );
@@ -198,22 +197,22 @@
     @Test
     public void testSaveSameEventMultipleTimesShouldOnlyGive1Event()
     {
-        Enrollment enrollment = createEnrollment( programA.getUid(), personMaleA.getPerson() );
+        Enrollment enrollment = createEnrollment( programA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         ImportSummary importSummary = enrollmentService.saveEnrollment( enrollment );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
         Event event = createEvent( programA.getUid(), programStageA.getUid(), organisationUnitA.getUid(),
-            personMaleA.getPerson(), dataElementA.getUid() );
-        importSummary = eventService.saveEvent( event );
-        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
-
-        event = createEvent( programA.getUid(), programStageA.getUid(), organisationUnitA.getUid(),
-            personMaleA.getPerson(), dataElementA.getUid() );
-        importSummary = eventService.saveEvent( event );
-        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
-
-        event = createEvent( programA.getUid(), programStageA.getUid(), organisationUnitA.getUid(),
-            personMaleA.getPerson(), dataElementA.getUid() );
+            trackedEntityInstanceMaleA.getTrackedEntityInstance(), dataElementA.getUid() );
+        importSummary = eventService.saveEvent( event );
+        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
+
+        event = createEvent( programA.getUid(), programStageA.getUid(), organisationUnitA.getUid(),
+            trackedEntityInstanceMaleA.getTrackedEntityInstance(), dataElementA.getUid() );
+        importSummary = eventService.saveEvent( event );
+        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
+
+        event = createEvent( programA.getUid(), programStageA.getUid(), organisationUnitA.getUid(),
+            trackedEntityInstanceMaleA.getTrackedEntityInstance(), dataElementA.getUid() );
         importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
@@ -223,24 +222,24 @@
     @Test
     public void testSaveRepeatableStageWithoutEventIdShouldCreateNewEvent()
     {
-        Enrollment enrollment = createEnrollment( programA.getUid(), personMaleA.getPerson() );
+        Enrollment enrollment = createEnrollment( programA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         ImportSummary importSummary = enrollmentService.saveEnrollment( enrollment );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
         Event event = createEvent( programA.getUid(), programStageA.getUid(), organisationUnitA.getUid(),
-            personMaleA.getPerson(), dataElementA.getUid() );
+            trackedEntityInstanceMaleA.getTrackedEntityInstance(), dataElementA.getUid() );
         importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
         event = createEvent( programA.getUid(), programStageB.getUid(), organisationUnitA.getUid(),
-            personMaleA.getPerson(), dataElementB.getUid() );
+            trackedEntityInstanceMaleA.getTrackedEntityInstance(), dataElementB.getUid() );
         importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
         assertEquals( 2, eventService.getEvents( programA, organisationUnitA ).getEvents().size() );
 
         event = createEvent( programA.getUid(), programStageB.getUid(), organisationUnitA.getUid(),
-            personMaleA.getPerson(), dataElementB.getUid() );
+            trackedEntityInstanceMaleA.getTrackedEntityInstance(), dataElementB.getUid() );
         importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
@@ -250,24 +249,24 @@
     @Test
     public void testSaveRepeatableStageWithEventIdShouldNotCreateAdditionalEvents()
     {
-        Enrollment enrollment = createEnrollment( programA.getUid(), personMaleA.getPerson() );
+        Enrollment enrollment = createEnrollment( programA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         ImportSummary importSummary = enrollmentService.saveEnrollment( enrollment );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
         Event event = createEvent( programA.getUid(), programStageA.getUid(), organisationUnitA.getUid(),
-            personMaleA.getPerson(), dataElementA.getUid() );
+            trackedEntityInstanceMaleA.getTrackedEntityInstance(), dataElementA.getUid() );
         importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
         event = createEvent( programA.getUid(), programStageB.getUid(), organisationUnitA.getUid(),
-            personMaleA.getPerson(), dataElementB.getUid() );
+            trackedEntityInstanceMaleA.getTrackedEntityInstance(), dataElementB.getUid() );
         importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
         assertEquals( 2, eventService.getEvents( programA, organisationUnitA ).getEvents().size() );
 
         event = createEvent( programA.getUid(), programStageB.getUid(), organisationUnitA.getUid(),
-            personMaleA.getPerson(), dataElementB.getUid() );
+            trackedEntityInstanceMaleA.getTrackedEntityInstance(), dataElementB.getUid() );
         event.setEvent( importSummary.getReference() );
         importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
@@ -275,7 +274,7 @@
         assertEquals( 2, eventService.getEvents( programA, organisationUnitA ).getEvents().size() );
 
         event = createEvent( programA.getUid(), programStageA.getUid(), organisationUnitA.getUid(),
-            personMaleA.getPerson(), dataElementA.getUid() );
+            trackedEntityInstanceMaleA.getTrackedEntityInstance(), dataElementA.getUid() );
         importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationSingleEventServiceTest.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationSingleEventServiceTest.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationSingleEventServiceTest.java	2014-03-17 08:06:21 +0000
@@ -44,8 +44,8 @@
 import org.hisp.dhis.dxf2.events.event.Event;
 import org.hisp.dhis.dxf2.events.event.EventService;
 import org.hisp.dhis.dxf2.events.event.EventStatus;
-import org.hisp.dhis.dxf2.events.person.Person;
-import org.hisp.dhis.dxf2.events.person.PersonService;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstanceService;
 import org.hisp.dhis.dxf2.importsummary.ImportStatus;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
@@ -53,7 +53,6 @@
 import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.program.ProgramStageDataElement;
 import org.hisp.dhis.program.ProgramStageDataElementService;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
 import org.hisp.dhis.user.UserService;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -68,7 +67,7 @@
     private EventService eventService;
 
     @Autowired
-    private PersonService personService;
+    private TrackedEntityInstanceService trackedEntityInstanceService;
 
     @Autowired
     private ProgramStageDataElementService programStageDataElementService;
@@ -76,12 +75,12 @@
     @Autowired
     private EnrollmentService enrollmentService;
 
-    private TrackedEntityInstance maleA;
-    private TrackedEntityInstance maleB;
-    private TrackedEntityInstance femaleA;
-    private TrackedEntityInstance femaleB;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance maleA;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance maleB;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance femaleA;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance femaleB;
 
-    private Person personMaleA;
+    private TrackedEntityInstance trackedEntityInstanceMaleA;
 
     private OrganisationUnit organisationUnitA;
     private OrganisationUnit organisationUnitB;
@@ -110,7 +109,7 @@
         identifiableObjectManager.save( femaleA );
         identifiableObjectManager.save( femaleB );
 
-        personMaleA = personService.getPerson( maleA );
+        trackedEntityInstanceMaleA = trackedEntityInstanceService.getPerson( maleA );
 
         dataElementA = createDataElement( 'A' );
         dataElementA.setType( DataElement.VALUE_TYPE_INT );
@@ -147,7 +146,7 @@
     @Test
     public void testSaveWithoutEnrollmentShouldFail()
     {
-        Event event = createEvent( programA.getUid(), organisationUnitA.getUid(), personMaleA.getPerson() );
+        Event event = createEvent( programA.getUid(), organisationUnitA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         ImportSummary importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.ERROR, importSummary.getStatus() );
         assertThat( importSummary.getDescription(), CoreMatchers.containsString( "is not enrolled in program" ) );
@@ -156,11 +155,11 @@
     @Test
     public void testSaveWithEnrollmentShouldNotFail()
     {
-        Enrollment enrollment = createEnrollment( programA.getUid(), personMaleA.getPerson() );
+        Enrollment enrollment = createEnrollment( programA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         ImportSummary importSummary = enrollmentService.saveEnrollment( enrollment );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
-        Event event = createEvent( programA.getUid(), organisationUnitA.getUid(), personMaleA.getPerson() );
+        Event event = createEvent( programA.getUid(), organisationUnitA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
     }
@@ -168,23 +167,23 @@
     @Test
     public void testSavingMultipleEventsShouldOnlyUpdate()
     {
-        Enrollment enrollment = createEnrollment( programA.getUid(), personMaleA.getPerson() );
+        Enrollment enrollment = createEnrollment( programA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         ImportSummary importSummary = enrollmentService.saveEnrollment( enrollment );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
-        Event event = createEvent( programA.getUid(), organisationUnitA.getUid(), personMaleA.getPerson() );
-        importSummary = eventService.saveEvent( event );
-        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
-
-        assertEquals( 1, eventService.getEvents( programA, organisationUnitA ).getEvents().size() );
-
-        event = createEvent( programA.getUid(), organisationUnitA.getUid(), personMaleA.getPerson() );
-        importSummary = eventService.saveEvent( event );
-        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
-
-        assertEquals( 1, eventService.getEvents( programA, organisationUnitA ).getEvents().size() );
-
-        event = createEvent( programA.getUid(), organisationUnitA.getUid(), personMaleA.getPerson() );
+        Event event = createEvent( programA.getUid(), organisationUnitA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
+        importSummary = eventService.saveEvent( event );
+        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
+
+        assertEquals( 1, eventService.getEvents( programA, organisationUnitA ).getEvents().size() );
+
+        event = createEvent( programA.getUid(), organisationUnitA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
+        importSummary = eventService.saveEvent( event );
+        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
+
+        assertEquals( 1, eventService.getEvents( programA, organisationUnitA ).getEvents().size() );
+
+        event = createEvent( programA.getUid(), organisationUnitA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         importSummary = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
 
@@ -194,24 +193,24 @@
     @Test
     public void testMultipleEnrollmentsWithEventShouldGiveDifferentUIDs()
     {
-        Enrollment enrollment = createEnrollment( programA.getUid(), personMaleA.getPerson() );
+        Enrollment enrollment = createEnrollment( programA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         enrollmentService.saveEnrollment( enrollment );
 
-        Event event = createEvent( programA.getUid(), organisationUnitA.getUid(), personMaleA.getPerson() );
+        Event event = createEvent( programA.getUid(), organisationUnitA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         event.setStatus( EventStatus.COMPLETED );
         ImportSummary importSummary1 = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary1.getStatus() );
-        enrollment = enrollmentService.getEnrollments( personMaleA ).getEnrollments().get( 0 );
+        enrollment = enrollmentService.getEnrollments( trackedEntityInstanceMaleA ).getEnrollments().get( 0 );
         enrollmentService.completeEnrollment( enrollment );
 
-        enrollment = createEnrollment( programA.getUid(), personMaleA.getPerson() );
+        enrollment = createEnrollment( programA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         enrollmentService.saveEnrollment( enrollment );
 
-        event = createEvent( programA.getUid(), organisationUnitA.getUid(), personMaleA.getPerson() );
+        event = createEvent( programA.getUid(), organisationUnitA.getUid(), trackedEntityInstanceMaleA.getTrackedEntityInstance() );
         event.setStatus( EventStatus.COMPLETED );
         ImportSummary importSummary2 = eventService.saveEvent( event );
         assertEquals( ImportStatus.SUCCESS, importSummary2.getStatus() );
-        enrollment = enrollmentService.getEnrollments( personMaleA ).getEnrollments().get( 0 );
+        enrollment = enrollmentService.getEnrollments( trackedEntityInstanceMaleA ).getEnrollments().get( 0 );
         enrollmentService.completeEnrollment( enrollment );
 
         assertNotEquals( importSummary1.getReference(), importSummary2.getReference() );

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/TrackedEntityInstanceServiceTest.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/TrackedEntityInstanceServiceTest.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/TrackedEntityInstanceServiceTest.java	2014-03-17 08:06:21 +0000
@@ -0,0 +1,188 @@
+package org.hisp.dhis.dxf2.events;
+
+/*
+ * Copyright (c) 2004-2013, 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.DhisTest;
+import org.hisp.dhis.common.IdentifiableObjectManager;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstanceService;
+import org.hisp.dhis.dxf2.importsummary.ImportStatus;
+import org.hisp.dhis.dxf2.importsummary.ImportSummary;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramInstanceService;
+import org.hisp.dhis.program.ProgramStage;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public class TrackedEntityInstanceServiceTest
+    extends DhisTest
+{
+    @Autowired
+    private TrackedEntityInstanceService trackedEntityInstanceService;
+
+    @Autowired
+    private ProgramInstanceService programInstanceService;
+
+    @Autowired
+    private IdentifiableObjectManager manager;
+
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance maleA;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance maleB;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance femaleA;
+    private org.hisp.dhis.trackedentity.TrackedEntityInstance femaleB;
+
+    private OrganisationUnit organisationUnitA;
+    private OrganisationUnit organisationUnitB;
+
+    private Program programA;
+
+    @Override
+    protected void setUpTest() throws Exception
+    {
+        organisationUnitA = createOrganisationUnit( 'A' );
+        organisationUnitB = createOrganisationUnit( 'B' );
+
+        organisationUnitB.setParent( organisationUnitA );
+
+        maleA = createTrackedEntityInstance(  'A', organisationUnitA );
+        maleB = createTrackedEntityInstance( 'B', organisationUnitB );
+        femaleA = createTrackedEntityInstance( 'C', organisationUnitA );
+        femaleB = createTrackedEntityInstance( 'D', organisationUnitB );
+
+        programA = createProgram( 'A', new HashSet<ProgramStage>(), organisationUnitA );
+        manager.save( organisationUnitA );
+        manager.save( organisationUnitB );
+        manager.save( maleA );
+        manager.save( maleB );
+        manager.save( femaleA );
+        manager.save( femaleB );
+        manager.save( programA );
+
+        programInstanceService.enrollTrackedEntityInstance( maleA, programA, null, null, organisationUnitA, null );
+        programInstanceService.enrollTrackedEntityInstance( femaleA, programA, null, null, organisationUnitA, null );
+    }
+
+    @Override
+    public boolean emptyDatabaseAfterTest()
+    {
+        return true;
+    }
+
+    @Test
+    public void testGetPersons()
+    {
+        assertEquals( 4, trackedEntityInstanceService.getPersons().getTrackedEntityInstances().size() );
+    }
+
+    @Test
+    public void testGetPersonByOrganisationUnit()
+    {
+        assertEquals( 2, trackedEntityInstanceService.getPersons( organisationUnitA ).getTrackedEntityInstances().size() );
+        assertEquals( 2, trackedEntityInstanceService.getPersons( organisationUnitB ).getTrackedEntityInstances().size() );
+    }
+
+    @Test
+    public void getPersonByPatients()
+    {
+        List<org.hisp.dhis.trackedentity.TrackedEntityInstance> patients = Arrays.asList( maleA, femaleB );
+        assertEquals( 2, trackedEntityInstanceService.getPersons( patients ).getTrackedEntityInstances().size() );
+    }
+
+    @Test
+    public void getPersonByUid()
+    {
+        assertEquals( maleA.getUid(), trackedEntityInstanceService.getPerson( maleA.getUid() ).getTrackedEntityInstance() );
+        assertEquals( femaleB.getUid(), trackedEntityInstanceService.getPerson( femaleB.getUid() ).getTrackedEntityInstance() );
+        assertNotEquals( femaleA.getUid(), trackedEntityInstanceService.getPerson( femaleB.getUid() ).getTrackedEntityInstance() );
+        assertNotEquals( maleA.getUid(), trackedEntityInstanceService.getPerson( maleB.getUid() ).getTrackedEntityInstance() );
+    }
+
+    @Test
+    public void getPersonByPatient()
+    {
+        assertEquals( maleA.getUid(), trackedEntityInstanceService.getPerson( maleA ).getTrackedEntityInstance() );
+        assertEquals( femaleB.getUid(), trackedEntityInstanceService.getPerson( femaleB ).getTrackedEntityInstance() );
+        assertNotEquals( femaleA.getUid(), trackedEntityInstanceService.getPerson( femaleB ).getTrackedEntityInstance() );
+        assertNotEquals( maleA.getUid(), trackedEntityInstanceService.getPerson( maleB ).getTrackedEntityInstance() );
+    }
+
+    @Test
+    public void testGetPersonByProgram()
+    {
+        assertEquals( 2, trackedEntityInstanceService.getPersons( programA ).getTrackedEntityInstances().size() );
+    }
+
+    @Test
+    @Ignore
+    public void testUpdatePerson()
+    {
+        TrackedEntityInstance trackedEntityInstance = trackedEntityInstanceService.getPerson( maleA.getUid() );
+        // person.setName( "UPDATED_NAME" );
+
+        ImportSummary importSummary = trackedEntityInstanceService.updatePerson( trackedEntityInstance );
+        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
+
+        // assertEquals( "UPDATED_NAME", personService.getPerson( maleA.getUid() ).getName() );
+    }
+
+    @Test
+    @Ignore
+    public void testSavePerson()
+    {
+        TrackedEntityInstance trackedEntityInstance = new TrackedEntityInstance();
+        // person.setName( "NAME" );
+        trackedEntityInstance.setOrgUnit( organisationUnitA.getUid() );
+
+        ImportSummary importSummary = trackedEntityInstanceService.savePerson( trackedEntityInstance );
+        assertEquals( ImportStatus.SUCCESS, importSummary.getStatus() );
+
+        // assertEquals( "NAME", personService.getPerson( importSummary.getReference() ).getName() );
+    }
+
+    @Test
+    public void testDeletePerson()
+    {
+        TrackedEntityInstance trackedEntityInstance = trackedEntityInstanceService.getPerson( maleA.getUid() );
+        trackedEntityInstanceService.deletePerson( trackedEntityInstance );
+
+        assertNull( trackedEntityInstanceService.getPerson( maleA.getUid() ) );
+        assertNotNull( trackedEntityInstanceService.getPerson( maleB.getUid() ) );
+    }
+}

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EnrollmentController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EnrollmentController.java	2014-01-02 13:13:21 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EnrollmentController.java	2014-03-17 08:06:21 +0000
@@ -36,8 +36,8 @@
 import org.hisp.dhis.dxf2.events.enrollment.EnrollmentService;
 import org.hisp.dhis.dxf2.events.enrollment.EnrollmentStatus;
 import org.hisp.dhis.dxf2.events.enrollment.Enrollments;
-import org.hisp.dhis.dxf2.events.person.Person;
-import org.hisp.dhis.dxf2.events.person.PersonService;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstanceService;
 import org.hisp.dhis.dxf2.importsummary.ImportStatus;
 import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
@@ -74,7 +74,7 @@
     private EnrollmentService enrollmentService;
 
     @Autowired
-    private PersonService personService;
+    private TrackedEntityInstanceService trackedEntityInstanceService;
 
     @Autowired
     private IdentifiableObjectManager manager;
@@ -108,10 +108,10 @@
         else if ( programUid != null && personUid != null )
         {
             Program program = getProgram( programUid );
-            Person person = getPerson( personUid );
+            TrackedEntityInstance trackedEntityInstance = getPerson( personUid );
 
-            enrollments = status != null ? enrollmentService.getEnrollments( program, person, status )
-                : enrollmentService.getEnrollments( program, person );
+            enrollments = status != null ? enrollmentService.getEnrollments( program, trackedEntityInstance, status )
+                : enrollmentService.getEnrollments( program, trackedEntityInstance );
         }
         else if ( orgUnitUid != null )
         {
@@ -126,8 +126,8 @@
         }
         else
         {
-            Person person = getPerson( personUid );
-            enrollments = status != null ? enrollmentService.getEnrollments( person, status ) : enrollmentService.getEnrollments( person );
+            TrackedEntityInstance trackedEntityInstance = getPerson( personUid );
+            enrollments = status != null ? enrollmentService.getEnrollments( trackedEntityInstance, status ) : enrollmentService.getEnrollments( trackedEntityInstance );
         }
 
         model.addAttribute( "model", enrollments );
@@ -271,16 +271,16 @@
         return enrollment;
     }
 
-    private Person getPerson( String id ) throws NotFoundException
+    private TrackedEntityInstance getPerson( String id ) throws NotFoundException
     {
-        Person person = personService.getPerson( id );
+        TrackedEntityInstance trackedEntityInstance = trackedEntityInstanceService.getPerson( id );
 
-        if ( person == null )
+        if ( trackedEntityInstance == null )
         {
             throw new NotFoundException( "Person", id );
         }
 
-        return person;
+        return trackedEntityInstance;
     }
 
     private OrganisationUnit getOrganisationUnit( String id ) throws NotFoundException

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EventController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EventController.java	2014-02-20 10:21:30 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EventController.java	2014-03-17 08:06:21 +0000
@@ -36,8 +36,8 @@
 import org.hisp.dhis.dxf2.events.event.EventService;
 import org.hisp.dhis.dxf2.events.event.Events;
 import org.hisp.dhis.dxf2.events.event.ImportEventTask;
-import org.hisp.dhis.dxf2.events.person.Person;
-import org.hisp.dhis.dxf2.events.person.PersonService;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstanceService;
 import org.hisp.dhis.dxf2.importsummary.ImportStatus;
 import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
@@ -102,7 +102,7 @@
     private EventService eventService;
 
     @Autowired
-    private PersonService personService;
+    private TrackedEntityInstanceService trackedEntityInstanceService;
 
     @Autowired
     private OrganisationUnitService organisationUnitService;
@@ -119,7 +119,7 @@
     public String getEvents(
         @RequestParam( value = "program", required = false ) String programUid,
         @RequestParam( value = "programStage", required = false ) String programStageUid,
-        @RequestParam( value = "person", required = false ) String personUid,
+        @RequestParam( value = "trackedEntityInstance", required = false ) String trackedEntityInstanceUid,
         @RequestParam( value = "orgUnit", required = false ) String orgUnitUid,
         @RequestParam( value = "includeChildren", required = false, defaultValue = "false" ) boolean includeChildren,
         @RequestParam( value = "includeDescendants", required = false, defaultValue = "false" ) boolean includeDescendants,
@@ -132,15 +132,15 @@
         ProgramStage programStage = manager.get( ProgramStage.class, programStageUid );
         List<OrganisationUnit> organisationUnits = new ArrayList<OrganisationUnit>();
         OrganisationUnit rootOrganisationUnit;
-        Person person = null;
+        TrackedEntityInstance trackedEntityInstance = null;
 
-        if ( personUid != null )
+        if ( trackedEntityInstanceUid != null )
         {
-            person = personService.getPerson( personUid );
+            trackedEntityInstance = trackedEntityInstanceService.getPerson( trackedEntityInstanceUid );
 
-            if ( person == null )
+            if ( trackedEntityInstance == null )
             {
-                throw new NotFoundException( "Person", personUid );
+                throw new NotFoundException( "TrackedEntityInstance", trackedEntityInstanceUid );
             }
         }
 
@@ -157,9 +157,9 @@
             }
         }
 
-        if ( rootOrganisationUnit == null && person != null )
+        if ( rootOrganisationUnit == null && trackedEntityInstance != null )
         {
-            Events events = eventService.getEvents( Arrays.asList( program ), Arrays.asList( programStage ), null, person, startDate, endDate );
+            Events events = eventService.getEvents( Arrays.asList( program ), Arrays.asList( programStage ), null, trackedEntityInstance, startDate, endDate );
 
             model.addAttribute( "model", events );
             model.addAttribute( "viewClass", options.getViewClass( "detailed" ) );
@@ -186,7 +186,7 @@
             organisationUnits.add( rootOrganisationUnit );
         }
 
-        Events events = eventService.getEvents( Arrays.asList( program ), Arrays.asList( programStage ), organisationUnits, person, startDate, endDate );
+        Events events = eventService.getEvents( Arrays.asList( program ), Arrays.asList( programStage ), organisationUnits, trackedEntityInstance, startDate, endDate );
 
         if ( options.hasLinks() )
         {

=== removed file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonAttributeGroupController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonAttributeGroupController.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonAttributeGroupController.java	1970-01-01 00:00:00 +0000
@@ -1,44 +0,0 @@
-package org.hisp.dhis.api.controller.event;
-
-/*
- * Copyright (c) 2004-2013, 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.api.controller.AbstractCrudController;
-import org.hisp.dhis.trackedentity.TrackedEntityAttributeGroup;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-@Controller
-@RequestMapping( value = PersonAttributeGroupController.RESOURCE_PATH )
-public class PersonAttributeGroupController extends AbstractCrudController<TrackedEntityAttributeGroup>
-{
-    public static final String RESOURCE_PATH = "/personAttributeGroups";
-}

=== removed file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonAttributeTypeController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonAttributeTypeController.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonAttributeTypeController.java	1970-01-01 00:00:00 +0000
@@ -1,104 +0,0 @@
-package org.hisp.dhis.api.controller.event;
-
-/*
- * Copyright (c) 2004-2013, 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;
-
-import org.hisp.dhis.api.controller.AbstractCrudController;
-import org.hisp.dhis.api.controller.WebMetaData;
-import org.hisp.dhis.api.controller.WebOptions;
-import org.hisp.dhis.common.Pager;
-import org.hisp.dhis.program.Program;
-import org.hisp.dhis.program.ProgramService;
-import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
-import org.hisp.dhis.trackedentity.TrackedEntityAttributeService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-@Controller
-@RequestMapping( value = PersonAttributeTypeController.RESOURCE_PATH )
-public class PersonAttributeTypeController
-    extends AbstractCrudController<TrackedEntityAttribute>
-{
-    public static final String RESOURCE_PATH = "/personAttributeTypes";
-
-    @Autowired
-    private TrackedEntityAttributeService attributeService;
-
-    @Autowired
-    private ProgramService programService;
-
-    @Override
-    protected List<TrackedEntityAttribute> getEntityList( WebMetaData metaData, WebOptions options )
-    {
-        List<TrackedEntityAttribute> entityList = new ArrayList<TrackedEntityAttribute>();
-
-        boolean withoutPrograms = options.getOptions().containsKey( "withoutPrograms" )
-            && Boolean.parseBoolean( options.getOptions().get( "withoutPrograms" ) );
-
-        if ( withoutPrograms )
-        {
-            entityList = new ArrayList<TrackedEntityAttribute>(
-                attributeService.getTrackedEntityAttributesWithoutProgram() );
-        }
-
-        else if ( options.getOptions().containsKey( "program" ) )
-        {
-            String programId = options.getOptions().get( "program" );
-            Program program = programService.getProgram( programId );
-
-            if ( program != null )
-            {
-                entityList = new ArrayList<TrackedEntityAttribute>( program.getEntityAttributes() );
-            }
-        }
-
-        else if ( options.hasPaging() )
-        {
-            int count = manager.getCount( getEntityClass() );
-
-            Pager pager = new Pager( options.getPage(), count, options.getPageSize() );
-            metaData.setPager( pager );
-
-            entityList = new ArrayList<TrackedEntityAttribute>( manager.getBetween( getEntityClass(),
-                pager.getOffset(), pager.getPageSize() ) );
-        }
-        else
-        {
-            entityList = new ArrayList<TrackedEntityAttribute>( attributeService.getAllTrackedEntityAttributes() );
-        }
-
-        return entityList;
-    }
-}

=== removed file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonController.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/PersonController.java	1970-01-01 00:00:00 +0000
@@ -1,396 +0,0 @@
-package org.hisp.dhis.api.controller.event;
-
-/*
- * Copyright (c) 2004-2013, 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.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.hibernate.Criteria;
-import org.hibernate.SessionFactory;
-import org.hibernate.criterion.Conjunction;
-import org.hibernate.criterion.Disjunction;
-import org.hibernate.criterion.Order;
-import org.hibernate.criterion.Restrictions;
-import org.hisp.dhis.api.controller.WebOptions;
-import org.hisp.dhis.api.controller.exception.NotFoundException;
-import org.hisp.dhis.api.utils.ContextUtils;
-import org.hisp.dhis.common.IdentifiableObjectManager;
-import org.hisp.dhis.dxf2.events.person.Person;
-import org.hisp.dhis.dxf2.events.person.PersonService;
-import org.hisp.dhis.dxf2.events.person.Persons;
-import org.hisp.dhis.dxf2.importsummary.ImportStatus;
-import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
-import org.hisp.dhis.dxf2.importsummary.ImportSummary;
-import org.hisp.dhis.dxf2.utils.JacksonUtils;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.program.Program;
-import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.client.HttpClientErrorException;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-@Controller
-@RequestMapping( value = PersonController.RESOURCE_PATH )
-@PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_LIST')" )
-public class PersonController
-{
-    public static final String RESOURCE_PATH = "/persons";
-
-    @Autowired
-    private PersonService personService;
-
-    @Autowired
-    private IdentifiableObjectManager manager;
-
-    @Autowired
-    private SessionFactory sessionFactory;
-
-    // -------------------------------------------------------------------------
-    // READ
-    // -------------------------------------------------------------------------
-
-    @RequestMapping( value = "", method = RequestMethod.GET )
-    @PreAuthorize( "hasRole('ALL') or hasRole('F_ACCESS_PATIENT_ATTRIBUTES')" )
-    public String getPersons( @RequestParam( value = "orgUnit", required = false ) String orgUnitUid,
-        @RequestParam( value = "program", required = false ) String programUid,
-        @RequestParam( value = "attribute", required = false ) List<String> attributeFilters,
-        @RequestParam( required = false ) Map<String, String> parameters, Model model )
-        throws Exception
-    {
-        WebOptions options = new WebOptions( parameters );
-        Persons persons = new Persons();
-
-        if ( attributeFilters != null )
-        {
-            persons = personsByFilter( attributeFilters, orgUnitUid );
-        }
-        else if ( orgUnitUid != null )
-        {
-            if ( programUid != null )
-            {
-                OrganisationUnit organisationUnit = getOrganisationUnit( orgUnitUid );
-                Program program = getProgram( programUid );
-
-                persons = personService.getPersons( organisationUnit, program );
-            }
-            else
-            {
-                OrganisationUnit organisationUnit = getOrganisationUnit( orgUnitUid );
-                persons = personService.getPersons( organisationUnit );
-            }
-        }
-        else
-        {
-            throw new HttpClientErrorException( HttpStatus.BAD_REQUEST, "Missing required orgUnit parameter." );
-        }
-
-        model.addAttribute( "model", persons );
-        model.addAttribute( "viewClass", options.getViewClass( "basic" ) );
-
-        return "persons";
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private Persons personsByFilter( List<String> attributeFilters, String orgUnitUid )
-    {
-        Criteria criteria = sessionFactory.getCurrentSession().createCriteria( TrackedEntityInstance.class );
-        criteria.createAlias( "attributeValues", "attributeValue" );
-        criteria.createAlias( "attributeValue.attribute", "attribute" );
-
-        Disjunction or = Restrictions.or();
-        criteria.add( or );
-
-        if ( orgUnitUid != null )
-        {
-            OrganisationUnit organisationUnit = manager.get( OrganisationUnit.class, orgUnitUid );
-
-            if ( organisationUnit == null )
-            {
-                throw new HttpClientErrorException( HttpStatus.BAD_REQUEST, "OrganisationUnit with UID " + orgUnitUid + " does not exist." );
-            }
-
-            criteria.createAlias( "organisationUnit", "organisationUnit" );
-            criteria.add( Restrictions.eq( "organisationUnit.uid", orgUnitUid ) );
-        }
-
-        // validate attributes, and build criteria
-        for ( String filter : attributeFilters )
-        {
-            String[] split = filter.split( ":" );
-
-            Conjunction and = Restrictions.and();
-            or.add( and );
-
-            if ( split.length != 3 )
-            {
-                throw new HttpClientErrorException( HttpStatus.BAD_REQUEST, "Filter " + filter + " is not in valid format. " +
-                    "Valid syntax is attribute=ATTRIBUTE_UID:OPERATOR:VALUE." );
-            }
-
-            TrackedEntityAttribute attribute = manager.get( TrackedEntityAttribute.class, split[0] );
-
-            if ( attribute == null )
-            {
-                throw new HttpClientErrorException( HttpStatus.BAD_REQUEST, "PersonAttribute with UID " + split[0] + " does not exist." );
-            }
-
-            if ( "like".equals( split[1].toLowerCase() ) )
-            {
-                and.add( Restrictions.and(
-                    Restrictions.eq( "attribute.uid", split[0] ),
-                    Restrictions.ilike( "attributeValue.value", "%" + split[2] + "%" )
-                ) );
-            }
-            else if ( "eq".equals( split[1].toLowerCase() ) )
-            {
-                and.add( Restrictions.and(
-                    Restrictions.eq( "attribute.uid", split[0] ),
-                    Restrictions.eq( "attributeValue.value", split[2] )
-                ) );
-            }
-            else if ( "ne".equals( split[1].toLowerCase() ) )
-            {
-                and.add( Restrictions.and(
-                    Restrictions.eq( "attribute.uid", split[0] ),
-                    Restrictions.ne( "attributeValue.value", split[2] )
-                ) );
-            }
-            else if ( "gt".equals( split[1].toLowerCase() ) )
-            {
-                and.add( Restrictions.and(
-                    Restrictions.eq( "attribute.uid", split[0] ),
-                    Restrictions.gt( "attributeValue.value", split[2] )
-                ) );
-            }
-            else if ( "lt".equals( split[1].toLowerCase() ) )
-            {
-                and.add( Restrictions.and(
-                    Restrictions.eq( "attribute.uid", split[0] ),
-                    Restrictions.lt( "attributeValue.value", split[2] )
-                ) );
-            }
-            else if ( "ge".equals( split[1].toLowerCase() ) )
-            {
-                and.add( Restrictions.and(
-                    Restrictions.eq( "attribute.uid", split[0] ),
-                    Restrictions.ge( "attributeValue.value", split[2] )
-                ) );
-            }
-            else if ( "in".equals( split[1].toLowerCase() ) )
-            {
-                String[] in = split[2].split( ";" );
-
-                and.add( Restrictions.and(
-                    Restrictions.eq( "attribute.uid", split[0] ),
-                    Restrictions.in( "attributeValue.value", in )
-                ) );
-            }
-        }
-
-        criteria.addOrder( Order.desc( "lastUpdated" ) );
-
-        return personService.getPersons( criteria.list() );
-    }
-
-    @RequestMapping( value = "/{id}", method = RequestMethod.GET )
-    @PreAuthorize( "hasRole('ALL') or hasRole('F_ACCESS_PATIENT_ATTRIBUTES')" )
-    public String getPerson( @PathVariable String id, @RequestParam Map<String, String> parameters, Model model )
-        throws NotFoundException
-    {
-        WebOptions options = new WebOptions( parameters );
-        Person person = getPerson( id );
-
-        model.addAttribute( "model", person );
-        model.addAttribute( "viewClass", options.getViewClass( "detailed" ) );
-
-        return "person";
-    }
-
-    // -------------------------------------------------------------------------
-    // CREATE
-    // -------------------------------------------------------------------------
-
-    @RequestMapping( value = "", method = RequestMethod.POST, consumes = MediaType.APPLICATION_XML_VALUE )
-    @PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_ADD')" )
-    public void postPersonXml( HttpServletRequest request, HttpServletResponse response )
-        throws IOException
-    {
-        ImportSummaries importSummaries = personService.savePersonXml( request.getInputStream() );
-
-        if ( importSummaries.getImportSummaries().size() > 1 )
-        {
-            response.setStatus( HttpServletResponse.SC_CREATED );
-            JacksonUtils.toXml( response.getOutputStream(), importSummaries );
-        }
-        else
-        {
-            response.setStatus( HttpServletResponse.SC_CREATED );
-            ImportSummary importSummary = importSummaries.getImportSummaries().get( 0 );
-
-            if ( !importSummary.getStatus().equals( ImportStatus.ERROR ) )
-            {
-                response.setHeader( "Location", getResourcePath( request, importSummary ) );
-            }
-
-            JacksonUtils.toXml( response.getOutputStream(), importSummary );
-        }
-    }
-
-    @RequestMapping( value = "", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE )
-    @PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_ADD')" )
-    public void postPersonJson( HttpServletRequest request, HttpServletResponse response )
-        throws IOException
-    {
-        ImportSummaries importSummaries = personService.savePersonJson( request.getInputStream() );
-
-        if ( importSummaries.getImportSummaries().size() > 1 )
-        {
-            response.setStatus( HttpServletResponse.SC_CREATED );
-            JacksonUtils.toJson( response.getOutputStream(), importSummaries );
-        }
-        else
-        {
-            response.setStatus( HttpServletResponse.SC_CREATED );
-            ImportSummary importSummary = importSummaries.getImportSummaries().get( 0 );
-
-            if ( !importSummary.getStatus().equals( ImportStatus.ERROR ) )
-            {
-                response.setHeader( "Location", getResourcePath( request, importSummary ) );
-            }
-
-            JacksonUtils.toJson( response.getOutputStream(), importSummary );
-        }
-    }
-
-    // -------------------------------------------------------------------------
-    // UPDATE
-    // -------------------------------------------------------------------------
-
-    @RequestMapping( value = "/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_XML_VALUE )
-    @ResponseStatus( value = HttpStatus.NO_CONTENT )
-    @PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_ADD')" )
-    public void updatePersonXml( @PathVariable String id, HttpServletRequest request, HttpServletResponse response )
-        throws IOException
-    {
-        ImportSummary importSummary = personService.updatePersonXml( id, request.getInputStream() );
-        JacksonUtils.toXml( response.getOutputStream(), importSummary );
-    }
-
-    @RequestMapping( value = "/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE )
-    @ResponseStatus( value = HttpStatus.NO_CONTENT )
-    @PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_ADD')" )
-    public void updatePersonJson( @PathVariable String id, HttpServletRequest request, HttpServletResponse response )
-        throws IOException
-    {
-        ImportSummary importSummary = personService.updatePersonJson( id, request.getInputStream() );
-        JacksonUtils.toJson( response.getOutputStream(), importSummary );
-    }
-
-    // -------------------------------------------------------------------------
-    // DELETE
-    // -------------------------------------------------------------------------
-
-    @RequestMapping( value = "/{id}", method = RequestMethod.DELETE )
-    @ResponseStatus( value = HttpStatus.NO_CONTENT )
-    @PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_DELETE')" )
-    public void deletePerson( @PathVariable String id )
-        throws NotFoundException
-    {
-        Person person = getPerson( id );
-        personService.deletePerson( person );
-    }
-
-    // -------------------------------------------------------------------------
-    // HELPERS
-    // -------------------------------------------------------------------------
-
-    private Person getPerson( String id )
-        throws NotFoundException
-    {
-        Person person = personService.getPerson( id );
-
-        if ( person == null )
-        {
-            throw new NotFoundException( "Person", id );
-        }
-        return person;
-    }
-
-    private Program getProgram( String id )
-        throws NotFoundException
-    {
-        Program program = manager.get( Program.class, id );
-
-        if ( program == null )
-        {
-            throw new NotFoundException( "Person", id );
-        }
-
-        return program;
-    }
-
-    private String getResourcePath( HttpServletRequest request, ImportSummary importSummary )
-    {
-        return ContextUtils.getContextPath( request ) + "/api/" + "persons" + "/" + importSummary.getReference();
-    }
-
-    private OrganisationUnit getOrganisationUnit( String orgUnitUid )
-    {
-        if ( orgUnitUid == null )
-        {
-            return null;
-        }
-
-        OrganisationUnit organisationUnit = manager.get( OrganisationUnit.class, orgUnitUid );
-
-        if ( organisationUnit == null )
-        {
-            throw new HttpClientErrorException( HttpStatus.BAD_REQUEST, "orgUnit is not a valid uid." );
-        }
-
-        return organisationUnit;
-    }
-}
\ No newline at end of file

=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityAttributeGroupController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityAttributeGroupController.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityAttributeGroupController.java	2014-03-17 08:06:21 +0000
@@ -0,0 +1,44 @@
+package org.hisp.dhis.api.controller.event;
+
+/*
+ * Copyright (c) 2004-2013, 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.api.controller.AbstractCrudController;
+import org.hisp.dhis.trackedentity.TrackedEntityAttributeGroup;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@Controller
+@RequestMapping( value = TrackedEntityAttributeGroupController.RESOURCE_PATH )
+public class TrackedEntityAttributeGroupController extends AbstractCrudController<TrackedEntityAttributeGroup>
+{
+    public static final String RESOURCE_PATH = "/trackedEntityAttributes";
+}

=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityAttributeTypeController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityAttributeTypeController.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityAttributeTypeController.java	2014-03-17 08:06:21 +0000
@@ -0,0 +1,104 @@
+package org.hisp.dhis.api.controller.event;
+
+/*
+ * Copyright (c) 2004-2013, 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;
+
+import org.hisp.dhis.api.controller.AbstractCrudController;
+import org.hisp.dhis.api.controller.WebMetaData;
+import org.hisp.dhis.api.controller.WebOptions;
+import org.hisp.dhis.common.Pager;
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramService;
+import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
+import org.hisp.dhis.trackedentity.TrackedEntityAttributeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@Controller
+@RequestMapping( value = TrackedEntityAttributeTypeController.RESOURCE_PATH )
+public class TrackedEntityAttributeTypeController
+    extends AbstractCrudController<TrackedEntityAttribute>
+{
+    public static final String RESOURCE_PATH = "/trackedEntityAttributeTypes";
+
+    @Autowired
+    private TrackedEntityAttributeService attributeService;
+
+    @Autowired
+    private ProgramService programService;
+
+    @Override
+    protected List<TrackedEntityAttribute> getEntityList( WebMetaData metaData, WebOptions options )
+    {
+        List<TrackedEntityAttribute> entityList = new ArrayList<TrackedEntityAttribute>();
+
+        boolean withoutPrograms = options.getOptions().containsKey( "withoutPrograms" )
+            && Boolean.parseBoolean( options.getOptions().get( "withoutPrograms" ) );
+
+        if ( withoutPrograms )
+        {
+            entityList = new ArrayList<TrackedEntityAttribute>(
+                attributeService.getTrackedEntityAttributesWithoutProgram() );
+        }
+
+        else if ( options.getOptions().containsKey( "program" ) )
+        {
+            String programId = options.getOptions().get( "program" );
+            Program program = programService.getProgram( programId );
+
+            if ( program != null )
+            {
+                entityList = new ArrayList<TrackedEntityAttribute>( program.getEntityAttributes() );
+            }
+        }
+
+        else if ( options.hasPaging() )
+        {
+            int count = manager.getCount( getEntityClass() );
+
+            Pager pager = new Pager( options.getPage(), count, options.getPageSize() );
+            metaData.setPager( pager );
+
+            entityList = new ArrayList<TrackedEntityAttribute>( manager.getBetween( getEntityClass(),
+                pager.getOffset(), pager.getPageSize() ) );
+        }
+        else
+        {
+            entityList = new ArrayList<TrackedEntityAttribute>( attributeService.getAllTrackedEntityAttributes() );
+        }
+
+        return entityList;
+    }
+}

=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityInstanceController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityInstanceController.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/TrackedEntityInstanceController.java	2014-03-17 08:06:21 +0000
@@ -0,0 +1,395 @@
+package org.hisp.dhis.api.controller.event;
+
+/*
+ * Copyright (c) 2004-2013, 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.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.hibernate.Criteria;
+import org.hibernate.SessionFactory;
+import org.hibernate.criterion.Conjunction;
+import org.hibernate.criterion.Disjunction;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Restrictions;
+import org.hisp.dhis.api.controller.WebOptions;
+import org.hisp.dhis.api.controller.exception.NotFoundException;
+import org.hisp.dhis.api.utils.ContextUtils;
+import org.hisp.dhis.common.IdentifiableObjectManager;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstance;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstanceService;
+import org.hisp.dhis.dxf2.events.person.TrackedEntityInstances;
+import org.hisp.dhis.dxf2.importsummary.ImportStatus;
+import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
+import org.hisp.dhis.dxf2.importsummary.ImportSummary;
+import org.hisp.dhis.dxf2.utils.JacksonUtils;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.client.HttpClientErrorException;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@Controller
+@RequestMapping( value = TrackedEntityInstanceController.RESOURCE_PATH )
+@PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_LIST')" )
+public class TrackedEntityInstanceController
+{
+    public static final String RESOURCE_PATH = "/trackedEntityInstances";
+
+    @Autowired
+    private TrackedEntityInstanceService trackedEntityInstanceService;
+
+    @Autowired
+    private IdentifiableObjectManager manager;
+
+    @Autowired
+    private SessionFactory sessionFactory;
+
+    // -------------------------------------------------------------------------
+    // READ
+    // -------------------------------------------------------------------------
+
+    @RequestMapping( value = "", method = RequestMethod.GET )
+    @PreAuthorize( "hasRole('ALL') or hasRole('F_ACCESS_PATIENT_ATTRIBUTES')" )
+    public String getTrackedEntityInstances( @RequestParam(value = "orgUnit", required = false) String orgUnitUid,
+        @RequestParam(value = "program", required = false) String programUid,
+        @RequestParam(value = "attribute", required = false) List<String> attributeFilters,
+        @RequestParam(required = false) Map<String, String> parameters, Model model )
+        throws Exception
+    {
+        WebOptions options = new WebOptions( parameters );
+        TrackedEntityInstances trackedEntityInstances = new TrackedEntityInstances();
+
+        if ( attributeFilters != null )
+        {
+            trackedEntityInstances = personsByFilter( attributeFilters, orgUnitUid );
+        }
+        else if ( orgUnitUid != null )
+        {
+            if ( programUid != null )
+            {
+                OrganisationUnit organisationUnit = getOrganisationUnit( orgUnitUid );
+                Program program = getProgram( programUid );
+
+                trackedEntityInstances = trackedEntityInstanceService.getPersons( organisationUnit, program );
+            }
+            else
+            {
+                OrganisationUnit organisationUnit = getOrganisationUnit( orgUnitUid );
+                trackedEntityInstances = trackedEntityInstanceService.getPersons( organisationUnit );
+            }
+        }
+        else
+        {
+            throw new HttpClientErrorException( HttpStatus.BAD_REQUEST, "Missing required orgUnit parameter." );
+        }
+
+        model.addAttribute( "model", trackedEntityInstances );
+        model.addAttribute( "viewClass", options.getViewClass( "basic" ) );
+
+        return "persons";
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private TrackedEntityInstances personsByFilter( List<String> attributeFilters, String orgUnitUid )
+    {
+        Criteria criteria = sessionFactory.getCurrentSession().createCriteria( org.hisp.dhis.trackedentity.TrackedEntityInstance.class );
+        criteria.createAlias( "attributeValues", "attributeValue" );
+        criteria.createAlias( "attributeValue.attribute", "attribute" );
+
+        Disjunction or = Restrictions.or();
+        criteria.add( or );
+
+        if ( orgUnitUid != null )
+        {
+            OrganisationUnit organisationUnit = manager.get( OrganisationUnit.class, orgUnitUid );
+
+            if ( organisationUnit == null )
+            {
+                throw new HttpClientErrorException( HttpStatus.BAD_REQUEST, "OrganisationUnit with UID " + orgUnitUid + " does not exist." );
+            }
+
+            criteria.createAlias( "organisationUnit", "organisationUnit" );
+            criteria.add( Restrictions.eq( "organisationUnit.uid", orgUnitUid ) );
+        }
+
+        // validate attributes, and build criteria
+        for ( String filter : attributeFilters )
+        {
+            String[] split = filter.split( ":" );
+
+            Conjunction and = Restrictions.and();
+            or.add( and );
+
+            if ( split.length != 3 )
+            {
+                throw new HttpClientErrorException( HttpStatus.BAD_REQUEST, "Filter " + filter + " is not in valid format. " +
+                    "Valid syntax is attribute=ATTRIBUTE_UID:OPERATOR:VALUE." );
+            }
+
+            TrackedEntityAttribute attribute = manager.get( TrackedEntityAttribute.class, split[0] );
+
+            if ( attribute == null )
+            {
+                throw new HttpClientErrorException( HttpStatus.BAD_REQUEST, "PersonAttribute with UID " + split[0] + " does not exist." );
+            }
+
+            if ( "like".equals( split[1].toLowerCase() ) )
+            {
+                and.add( Restrictions.and(
+                    Restrictions.eq( "attribute.uid", split[0] ),
+                    Restrictions.ilike( "attributeValue.value", "%" + split[2] + "%" )
+                ) );
+            }
+            else if ( "eq".equals( split[1].toLowerCase() ) )
+            {
+                and.add( Restrictions.and(
+                    Restrictions.eq( "attribute.uid", split[0] ),
+                    Restrictions.eq( "attributeValue.value", split[2] )
+                ) );
+            }
+            else if ( "ne".equals( split[1].toLowerCase() ) )
+            {
+                and.add( Restrictions.and(
+                    Restrictions.eq( "attribute.uid", split[0] ),
+                    Restrictions.ne( "attributeValue.value", split[2] )
+                ) );
+            }
+            else if ( "gt".equals( split[1].toLowerCase() ) )
+            {
+                and.add( Restrictions.and(
+                    Restrictions.eq( "attribute.uid", split[0] ),
+                    Restrictions.gt( "attributeValue.value", split[2] )
+                ) );
+            }
+            else if ( "lt".equals( split[1].toLowerCase() ) )
+            {
+                and.add( Restrictions.and(
+                    Restrictions.eq( "attribute.uid", split[0] ),
+                    Restrictions.lt( "attributeValue.value", split[2] )
+                ) );
+            }
+            else if ( "ge".equals( split[1].toLowerCase() ) )
+            {
+                and.add( Restrictions.and(
+                    Restrictions.eq( "attribute.uid", split[0] ),
+                    Restrictions.ge( "attributeValue.value", split[2] )
+                ) );
+            }
+            else if ( "in".equals( split[1].toLowerCase() ) )
+            {
+                String[] in = split[2].split( ";" );
+
+                and.add( Restrictions.and(
+                    Restrictions.eq( "attribute.uid", split[0] ),
+                    Restrictions.in( "attributeValue.value", in )
+                ) );
+            }
+        }
+
+        criteria.addOrder( Order.desc( "lastUpdated" ) );
+
+        return trackedEntityInstanceService.getPersons( criteria.list() );
+    }
+
+    @RequestMapping( value = "/{id}", method = RequestMethod.GET )
+    @PreAuthorize( "hasRole('ALL') or hasRole('F_ACCESS_PATIENT_ATTRIBUTES')" )
+    public String getPerson( @PathVariable String id, @RequestParam Map<String, String> parameters, Model model )
+        throws NotFoundException
+    {
+        WebOptions options = new WebOptions( parameters );
+        TrackedEntityInstance trackedEntityInstance = getPerson( id );
+
+        model.addAttribute( "model", trackedEntityInstance );
+        model.addAttribute( "viewClass", options.getViewClass( "detailed" ) );
+
+        return "person";
+    }
+
+    // -------------------------------------------------------------------------
+    // CREATE
+    // -------------------------------------------------------------------------
+
+    @RequestMapping( value = "", method = RequestMethod.POST, consumes = MediaType.APPLICATION_XML_VALUE )
+    @PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_ADD')" )
+    public void postPersonXml( HttpServletRequest request, HttpServletResponse response )
+        throws IOException
+    {
+        ImportSummaries importSummaries = trackedEntityInstanceService.savePersonXml( request.getInputStream() );
+
+        if ( importSummaries.getImportSummaries().size() > 1 )
+        {
+            response.setStatus( HttpServletResponse.SC_CREATED );
+            JacksonUtils.toXml( response.getOutputStream(), importSummaries );
+        }
+        else
+        {
+            response.setStatus( HttpServletResponse.SC_CREATED );
+            ImportSummary importSummary = importSummaries.getImportSummaries().get( 0 );
+
+            if ( !importSummary.getStatus().equals( ImportStatus.ERROR ) )
+            {
+                response.setHeader( "Location", getResourcePath( request, importSummary ) );
+            }
+
+            JacksonUtils.toXml( response.getOutputStream(), importSummary );
+        }
+    }
+
+    @RequestMapping( value = "", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE )
+    @PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_ADD')" )
+    public void postPersonJson( HttpServletRequest request, HttpServletResponse response )
+        throws IOException
+    {
+        ImportSummaries importSummaries = trackedEntityInstanceService.savePersonJson( request.getInputStream() );
+
+        if ( importSummaries.getImportSummaries().size() > 1 )
+        {
+            response.setStatus( HttpServletResponse.SC_CREATED );
+            JacksonUtils.toJson( response.getOutputStream(), importSummaries );
+        }
+        else
+        {
+            response.setStatus( HttpServletResponse.SC_CREATED );
+            ImportSummary importSummary = importSummaries.getImportSummaries().get( 0 );
+
+            if ( !importSummary.getStatus().equals( ImportStatus.ERROR ) )
+            {
+                response.setHeader( "Location", getResourcePath( request, importSummary ) );
+            }
+
+            JacksonUtils.toJson( response.getOutputStream(), importSummary );
+        }
+    }
+
+    // -------------------------------------------------------------------------
+    // UPDATE
+    // -------------------------------------------------------------------------
+
+    @RequestMapping( value = "/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_XML_VALUE )
+    @ResponseStatus( value = HttpStatus.NO_CONTENT )
+    @PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_ADD')" )
+    public void updatePersonXml( @PathVariable String id, HttpServletRequest request, HttpServletResponse response )
+        throws IOException
+    {
+        ImportSummary importSummary = trackedEntityInstanceService.updatePersonXml( id, request.getInputStream() );
+        JacksonUtils.toXml( response.getOutputStream(), importSummary );
+    }
+
+    @RequestMapping( value = "/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE )
+    @ResponseStatus( value = HttpStatus.NO_CONTENT )
+    @PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_ADD')" )
+    public void updatePersonJson( @PathVariable String id, HttpServletRequest request, HttpServletResponse response )
+        throws IOException
+    {
+        ImportSummary importSummary = trackedEntityInstanceService.updatePersonJson( id, request.getInputStream() );
+        JacksonUtils.toJson( response.getOutputStream(), importSummary );
+    }
+
+    // -------------------------------------------------------------------------
+    // DELETE
+    // -------------------------------------------------------------------------
+
+    @RequestMapping( value = "/{id}", method = RequestMethod.DELETE )
+    @ResponseStatus( value = HttpStatus.NO_CONTENT )
+    @PreAuthorize( "hasRole('ALL') or hasRole('F_PATIENT_DELETE')" )
+    public void deletePerson( @PathVariable String id )
+        throws NotFoundException
+    {
+        TrackedEntityInstance trackedEntityInstance = getPerson( id );
+        trackedEntityInstanceService.deletePerson( trackedEntityInstance );
+    }
+
+    // -------------------------------------------------------------------------
+    // HELPERS
+    // -------------------------------------------------------------------------
+
+    private TrackedEntityInstance getPerson( String id )
+        throws NotFoundException
+    {
+        TrackedEntityInstance trackedEntityInstance = trackedEntityInstanceService.getPerson( id );
+
+        if ( trackedEntityInstance == null )
+        {
+            throw new NotFoundException( "Person", id );
+        }
+        return trackedEntityInstance;
+    }
+
+    private Program getProgram( String id )
+        throws NotFoundException
+    {
+        Program program = manager.get( Program.class, id );
+
+        if ( program == null )
+        {
+            throw new NotFoundException( "Person", id );
+        }
+
+        return program;
+    }
+
+    private String getResourcePath( HttpServletRequest request, ImportSummary importSummary )
+    {
+        return ContextUtils.getContextPath( request ) + "/api/" + "persons" + "/" + importSummary.getReference();
+    }
+
+    private OrganisationUnit getOrganisationUnit( String orgUnitUid )
+    {
+        if ( orgUnitUid == null )
+        {
+            return null;
+        }
+
+        OrganisationUnit organisationUnit = manager.get( OrganisationUnit.class, orgUnitUid );
+
+        if ( organisationUnit == null )
+        {
+            throw new HttpClientErrorException( HttpStatus.BAD_REQUEST, "orgUnit is not a valid uid." );
+        }
+
+        return organisationUnit;
+    }
+}
\ No newline at end of file