class ProgramInstancePreProcessor implements Processor {

    @Override
    public void process( Event event, WorkContext ctx )
    {
        ProgramInstanceStore programInstanceStore = ctx.getServiceDelegator().getProgramInstanceStore();

        Program program = ctx.getProgramsMap().get( event.getProgram() );

        if ( program == null )
        {
            return; // Program is a mandatory value, it will be caught by the validation
        }

        ProgramInstance programInstance = ctx.getProgramInstanceMap().get( event.getUid() );
        final Optional<TrackedEntityInstance> trackedEntityInstance = ctx.getTrackedEntityInstance( event.getUid() );

        if ( program.isRegistration() && programInstance == null )
        {
            List<ProgramInstance> programInstances = new ArrayList<>(
                programInstanceStore.get( trackedEntityInstance.orElse( null ), program, ProgramStatus.ACTIVE ) );

            if ( programInstances.size() == 1 )
            {
                event.setEnrollment( programInstances.get( 0 ).getUid() );
                ctx.getProgramInstanceMap().put( event.getUid(), programInstances.get( 0 ) );
            }
        }
        else if ( program.isWithoutRegistration() && programInstance == null )
        {
            List<ProgramInstance> programInstances = getProgramInstances( ctx.getServiceDelegator().getJdbcTemplate(),
                program, ProgramStatus.ACTIVE );

            // the "original" event import code creates a Program Instance, if none is found
            // but this is no longer needed, since a Program POST-CREATION hook takes care of that
            if ( programInstances.size() == 1 )
            {
                event.setEnrollment( programInstances.get( 0 ).getUid() );
                ctx.getProgramInstanceMap().put( event.getUid(), programInstances.get( 0 ) );
            }
            // If more than one Program Instance is present, the validation will detect it later
        }
    }

}