Package org.qi4j.sample.dcicargo.sample_a.context.support

Source Code of org.qi4j.sample.dcicargo.sample_a.context.support.RoutingService$Mixin

/*
* 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.qi4j.sample.dcicargo.sample_a.context.support;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.joda.time.LocalDate;
import org.qi4j.api.injection.scope.Service;
import org.qi4j.api.injection.scope.Structure;
import org.qi4j.api.mixin.Mixins;
import org.qi4j.api.service.ServiceComposite;
import org.qi4j.api.unitofwork.UnitOfWork;
import org.qi4j.api.unitofwork.UnitOfWorkFactory;
import org.qi4j.api.value.ValueBuilder;
import org.qi4j.api.value.ValueBuilderFactory;
import org.qi4j.sample.dcicargo.pathfinder_a.api.GraphTraversalService;
import org.qi4j.sample.dcicargo.pathfinder_a.api.TransitEdge;
import org.qi4j.sample.dcicargo.pathfinder_a.api.TransitPath;
import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Leg;
import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Routing service.
*
* Our end of the routing service. This is basically a data model
* translation layer between our domain model and the API put forward
* by the path finder team, which operates in a different context from us.
*/
@Mixins( RoutingService.Mixin.class )
public interface RoutingService
    extends ServiceComposite
{
    /**
     * @param routeSpecification route specification
     *
     * @return A list of itineraries that satisfy the specification. May be an empty list if no route is found.
     */
    List<Itinerary> fetchRoutesForSpecification( RouteSpecification routeSpecification )
        throws FoundNoRoutesException;

    abstract class Mixin
        implements RoutingService
    {
        private static final Logger logger = LoggerFactory.getLogger( RoutingService.class );

        @Structure
        ValueBuilderFactory vbf;

        @Structure
        UnitOfWorkFactory uowf;

        @Service
        GraphTraversalService graphTraversalService;

        final static int MAX_TRIES = 10;

        public List<Itinerary> fetchRoutesForSpecification( RouteSpecification routeSpecification )
            throws FoundNoRoutesException
        {
            final Location origin = routeSpecification.origin().get();
            final Location destination = routeSpecification.destination().get();

            List<TransitPath> transitPaths;
            List<Itinerary> itineraries = new ArrayList<Itinerary>();

            // Try a MAX_TRIES times to avoid empty results too often
            int tries = 0;
            do
            {
                try
                {
                    transitPaths = graphTraversalService.findShortestPath( origin.getCode(), destination.getCode() );
                }
                catch( RemoteException e )
                {
                    logger.error( e.getMessage(), e );
                    return Collections.emptyList();
                }

                // The returned result is then translated back into our domain model.
                for( TransitPath transitPath : transitPaths )
                {
                    final Itinerary itinerary = toItinerary( transitPath );

                    // Use the specification to safe-guard against invalid itineraries
                    // We can use the side-effects free method of the RouteSpecification data object
                    if( routeSpecification.isSatisfiedBy( itinerary ) )
                    {
                        itineraries.add( itinerary );
                    }
                }
            }
            while( tries++ < MAX_TRIES && itineraries.size() == 0 );

            if( itineraries.size() == 0 )
            {
                throw new FoundNoRoutesException( destination.name().get(),
                                                  new LocalDate( routeSpecification.arrivalDeadline().get() ) );
            }

            return itineraries;
        }

        private Itinerary toItinerary( TransitPath transitPath )
        {
            ValueBuilder<Itinerary> itinerary = vbf.newValueBuilder( Itinerary.class );
            List<Leg> legs = new ArrayList<Leg>();
            for( TransitEdge edge : transitPath.getTransitEdges() )
            {
                legs.add( toLeg( edge ) );
            }
            itinerary.prototype().legs().set( legs );

            return itinerary.newInstance();
        }

        private Leg toLeg( TransitEdge edge )
        {
            UnitOfWork uow = uowf.currentUnitOfWork();

            // Build Leg value object
            ValueBuilder<Leg> leg = vbf.newValueBuilder( Leg.class );
            leg.prototype().voyage().set( uow.get( Voyage.class, edge.getVoyageNumber() ) );
            leg.prototype().loadLocation().set( uow.get( Location.class, edge.getFromUnLocode() ) );
            leg.prototype().unloadLocation().set( uow.get( Location.class, edge.getToUnLocode() ) );
            leg.prototype().loadTime().set( edge.getFromDate() );
            leg.prototype().unloadTime().set( edge.getToDate() );

            return leg.newInstance();
        }
    }
}
TOP

Related Classes of org.qi4j.sample.dcicargo.sample_a.context.support.RoutingService$Mixin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.