| /* |
| * 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_b.infrastructure.dci; |
| |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Proxy; |
| import org.apache.zest.api.structure.Module; |
| import org.apache.zest.api.value.ValueBuilder; |
| import org.apache.zest.api.value.ValueComposite; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Context |
| * |
| * Base class for DCI Contexts |
| * |
| * Helps assigning Entity objects to Roles and to "inject" the Context object into Methodful Roles. |
| */ |
| public abstract class Context |
| { |
| protected Logger logger = LoggerFactory.getLogger( getClass() ); |
| |
| /** |
| * We don't allow SubContexts to access the store directly |
| * |
| * All entities should be created through aggregate r |
| */ |
| private static Module module; |
| |
| protected Context() |
| { |
| } |
| |
| /* |
| * Role assignment + Context "injection" |
| * |
| * Cast a Data object to a Role, set the Context object in the Role and return the RolePlayer. |
| * |
| * Requirements: |
| * 1) SomeRole interface declares a 'void setContext(YourContext context);' method |
| * 2) SomeRole.Mixin class extends RoleMixin<YourContext> |
| * |
| * The RolePlayer can then use the context pointer to lookup other Roles in the current Context. |
| */ |
| protected <T> T rolePlayer( Class<T> roleClass, Object dataObject ) |
| { |
| if( dataObject == null ) |
| { |
| return null; |
| } |
| |
| objectCanPlayRole( roleClass, dataObject ); |
| T rolePlayer = roleClass.cast( dataObject ); |
| setContext( rolePlayer, this ); |
| return rolePlayer; |
| } |
| |
| private <T> void objectCanPlayRole( Class<T> roleClass, Object dataObject ) |
| { |
| if( roleClass.isAssignableFrom( dataObject.getClass() ) ) |
| { |
| return; |
| } |
| |
| String className; |
| if( dataObject instanceof Proxy ) |
| { |
| className = Proxy.getInvocationHandler( dataObject ).getClass().getSimpleName(); |
| } |
| else |
| { |
| className = dataObject.getClass().getSimpleName(); |
| } |
| |
| throw new IllegalArgumentException( |
| "Object '" + className + "' can't play Role of '" + roleClass.getSimpleName() + "'" ); |
| } |
| |
| /* |
| * Poor mans Context injection |
| * */ |
| private <T> void setContext( T rolePlayer, Context context ) |
| { |
| try |
| { |
| Method setContextMethod = rolePlayer.getClass().getDeclaredMethod( "setContext", context.getClass() ); |
| |
| // Set Context in Role |
| setContextMethod.invoke( rolePlayer, context ); |
| } |
| catch( Exception e ) |
| { |
| String c = context.getClass().getSimpleName(); |
| String r = rolePlayer.getClass().getSimpleName(); |
| String msg = "Couldn't invoke 'void setContext( " + c + " context);' on " + r + "." + |
| "\nPlease check the following requirements: " + |
| "\n1) 'void setContext( " + c + " context);' is declared in " + r + " interface." + |
| "\n2) " + r + " extends RoleMixin<" + c + ">"; |
| logger.error( msg, e.getMessage() ); |
| e.printStackTrace(); |
| throw new RuntimeException( msg ); |
| } |
| } |
| |
| // Entity object instantiation |
| |
| protected <T, U> T rolePlayer( Class<T> roleClass, Class<U> dataClass, String entityId ) |
| { |
| U dataObject = module.currentUnitOfWork().get( dataClass, entityId ); |
| return rolePlayer( roleClass, dataObject ); |
| } |
| |
| protected static <T> T loadEntity( Class<T> entityRoleClass, String entityId ) |
| { |
| return module.currentUnitOfWork().get( entityRoleClass, entityId ); |
| } |
| |
| protected static <T extends ValueComposite> ValueBuilder<T> valueBuilder( Class<T> valueClass ) |
| { |
| return module.newValueBuilder( valueClass ); |
| } |
| |
| public static void prepareContextBaseClass( Module module ) |
| { |
| Context.module = module; |
| } |
| } |