| /* |
| * Copyright 2011 Marc Grue. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| * implied. |
| * |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.zest.sample.dcicargo.sample_a.context.shipping.handling; |
| |
| import java.util.Arrays; |
| import java.util.Date; |
| import org.apache.zest.api.injection.scope.Service; |
| import org.apache.zest.api.injection.scope.This; |
| import org.apache.zest.api.mixin.Mixins; |
| import org.apache.zest.api.unitofwork.NoSuchEntityException; |
| import org.apache.zest.api.unitofwork.UnitOfWork; |
| import org.apache.zest.api.value.ValueBuilder; |
| import org.apache.zest.sample.dcicargo.sample_a.context.support.ApplicationEvents; |
| import org.apache.zest.sample.dcicargo.sample_a.context.support.RegisterHandlingEventAttemptDTO; |
| import org.apache.zest.sample.dcicargo.sample_a.data.entity.HandlingEventsEntity; |
| import org.apache.zest.sample.dcicargo.sample_a.data.shipping.cargo.Cargo; |
| import org.apache.zest.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId; |
| import org.apache.zest.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent; |
| import org.apache.zest.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType; |
| import org.apache.zest.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvents; |
| import org.apache.zest.sample.dcicargo.sample_a.data.shipping.location.Location; |
| import org.apache.zest.sample.dcicargo.sample_a.data.shipping.voyage.Voyage; |
| import org.apache.zest.sample.dcicargo.sample_a.infrastructure.dci.Context; |
| import org.apache.zest.sample.dcicargo.sample_a.infrastructure.dci.RoleMixin; |
| |
| import static org.apache.zest.sample.dcicargo.sample_a.data.entity.HandlingEventsEntity.HANDLING_EVENTS_ID; |
| |
| /** |
| * Register new handling event use case. |
| * |
| * The Cargo is updated synchronously in this implementation. |
| */ |
| public class RegisterHandlingEvent extends Context |
| { |
| // ROLES --------------------------------------------------------------------- |
| |
| private HandlingEventFactoryRole handlingEventFactory; |
| |
| private Date registrationTime; |
| private Date completionTime; |
| private String trackingIdString; |
| private String eventTypeString; |
| private String unLocodeString; |
| private String voyageNumberString; |
| |
| // CONTEXT CONSTRUCTORS ------------------------------------------------------ |
| |
| public RegisterHandlingEvent( Date registrationTime, |
| Date completionTime, |
| String trackingIdString, |
| String eventTypeString, |
| String unLocodeString, |
| String voyageNumberString |
| ) |
| { |
| handlingEventFactory = rolePlayer( HandlingEventFactoryRole.class, HandlingEventsEntity.class, HANDLING_EVENTS_ID ); |
| |
| this.registrationTime = registrationTime; |
| this.completionTime = completionTime; |
| this.trackingIdString = trackingIdString; |
| this.eventTypeString = eventTypeString; |
| this.unLocodeString = unLocodeString; |
| this.voyageNumberString = voyageNumberString; |
| } |
| |
| // INTERACTIONS -------------------------------------------------------------- |
| |
| public void register() |
| { |
| handlingEventFactory.registerHandlingEvent(); |
| } |
| |
| // METHODFUL ROLE IMPLEMENTATIONS -------------------------------------------- |
| |
| @Mixins( HandlingEventFactoryRole.Mixin.class ) |
| public interface HandlingEventFactoryRole |
| { |
| void setContext( RegisterHandlingEvent context ); |
| |
| void registerHandlingEvent(); |
| |
| class Mixin |
| extends RoleMixin<RegisterHandlingEvent> |
| implements HandlingEventFactoryRole |
| { |
| @Service |
| ApplicationEvents applicationEvents; |
| |
| @This |
| HandlingEvents handlingEvents; |
| |
| // Handling event properties |
| TrackingId trackingId; |
| HandlingEventType handlingEventType; |
| Location location; |
| Voyage voyage; |
| |
| public void registerHandlingEvent() |
| { |
| RegisterHandlingEventAttemptDTO registrationAttempt = buildRegistrationAttempt(); |
| |
| // Step 1: Publish event stating that registration attempt has been received. |
| applicationEvents.receivedHandlingEventRegistrationAttempt( registrationAttempt ); |
| |
| HandlingEvent handlingEvent = null; |
| try |
| { |
| // Step 2: Verify existing data |
| verifyExistingData(); |
| |
| // Step 3: Verify that received data can represent a valid handling event |
| verifyValidData(); |
| |
| // Step 4: Create and save handling event |
| handlingEvent = handlingEvents.createHandlingEvent( |
| context.registrationTime, context.completionTime, trackingId, handlingEventType, location, voyage ); |
| } |
| catch( IllegalArgumentException e ) |
| { |
| // Deviation 2-5a: Publish event if registration is unsuccessful |
| applicationEvents.unsuccessfulHandlingEventRegistration( registrationAttempt ); |
| throw e; |
| } |
| |
| // Step 5: Inspect cargo |
| new InspectCargo( handlingEvent ).inspect(); |
| |
| // Step 6: Publish notification that cargo was successfully handled |
| applicationEvents.cargoWasHandled( handlingEvent ); |
| } |
| |
| private RegisterHandlingEventAttemptDTO buildRegistrationAttempt() |
| { |
| ValueBuilder<RegisterHandlingEventAttemptDTO> builder = |
| vbf.newValueBuilder( RegisterHandlingEventAttemptDTO.class ); |
| builder.prototype().registrationTime().set( context.registrationTime ); |
| builder.prototype().completionTime().set( context.completionTime ); |
| builder.prototype().trackingIdString().set( context.trackingIdString ); |
| builder.prototype().eventTypeString().set( context.eventTypeString ); |
| builder.prototype().unLocodeString().set( context.unLocodeString ); |
| builder.prototype().voyageNumberString().set( context.voyageNumberString ); |
| return builder.newInstance(); |
| } |
| |
| private void verifyExistingData() |
| { |
| if( context.registrationTime == null ) |
| { |
| throw new IllegalArgumentException( "Registration time was null. All parameters have to be passed." ); |
| } |
| if( context.completionTime == null ) |
| { |
| throw new IllegalArgumentException( "Completion time was null. All parameters have to be passed." ); |
| } |
| |
| context.trackingIdString = getClean( "Tracking id", context.trackingIdString ); |
| context.eventTypeString = getClean( "Event type", context.eventTypeString ); |
| context.unLocodeString = getClean( "UnLocode", context.unLocodeString ); |
| |
| // Voyage is optional |
| } |
| |
| private String getClean( String parameter, String value ) |
| { |
| if( value == null ) |
| { |
| throw new IllegalArgumentException( parameter + " was null. All parameters have to be passed." ); |
| } |
| |
| if( value.trim().length() == 0 ) |
| { |
| throw new IllegalArgumentException( parameter + " cannot be empty." ); |
| } |
| |
| return value.trim(); |
| } |
| |
| private void verifyValidData() |
| { |
| // Deviation 3a |
| try |
| { |
| handlingEventType = HandlingEventType.valueOf( context.eventTypeString ); |
| } |
| catch( Exception e ) |
| { |
| throw new IllegalArgumentException( |
| "'" + context.eventTypeString + "' is not a valid handling event type. Valid types are: " |
| + Arrays.toString( HandlingEventType.values() ) ); |
| } |
| |
| // Verifications against data store |
| UnitOfWork uow = uowf.currentUnitOfWork(); |
| |
| // Deviation 3b |
| try |
| { |
| // Will throw NoSuchEntityException if not found in store |
| Cargo cargo = uow.get( Cargo.class, context.trackingIdString ); |
| trackingId = cargo.trackingId().get(); |
| |
| // Deviation 3c |
| if( cargo.itinerary().get() == null ) |
| { |
| throw new IllegalArgumentException( "Can't create handling event for non-routed cargo '" |
| + context.trackingIdString + "'." ); |
| } |
| } |
| catch( NoSuchEntityException e ) |
| { |
| throw new IllegalArgumentException( "Found no cargo with tracking id '" + context.trackingIdString + "'." ); |
| } |
| |
| // Deviation 3d |
| try |
| { |
| location = uow.get( Location.class, context.unLocodeString ); |
| } |
| catch( NoSuchEntityException e ) |
| { |
| throw new IllegalArgumentException( "Unknown location: " + context.unLocodeString ); |
| } |
| |
| // Deviation 3e |
| if( handlingEventType.requiresVoyage() ) |
| { |
| // Deviation 3e1a |
| if( context.voyageNumberString == null ) |
| { |
| throw new IllegalArgumentException( "Handling event " + handlingEventType.toString() + |
| " requires a voyage. No voyage number submitted." ); |
| } |
| |
| // Deviation 3e1b |
| try |
| { |
| voyage = uow.get( Voyage.class, context.voyageNumberString ); |
| } |
| catch( NoSuchEntityException e ) |
| { |
| throw new IllegalArgumentException( |
| "Found no voyage with voyage number '" + context.voyageNumberString + "'." ); |
| } |
| } |
| else |
| { |
| // Deviation 3f |
| voyage = null; |
| } |
| } |
| } |
| } |
| } |