blob: f5f39dd98873e27523f8a1faf91d3cbf3a8555f3 [file] [log] [blame]
/*
* Copyright (c) 2007-2009, Rickard Öberg. All Rights Reserved.
* Copyright (c) 2008, Alin Dreghiciu. All Rights Reserved.
* Copyright (c) 2008, Edward Yakop. All Rights Reserved.
* Copyright (c) 2014-2015, Paul Merlin. All Rights Reserved.
*
* 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.runtime.unitofwork;
import org.qi4j.api.common.QualifiedName;
import org.qi4j.api.entity.EntityBuilder;
import org.qi4j.api.entity.EntityReference;
import org.qi4j.api.entity.Identity;
import org.qi4j.api.entity.LifecycleException;
import org.qi4j.runtime.composite.FunctionStateResolver;
import org.qi4j.runtime.entity.EntityInstance;
import org.qi4j.runtime.entity.EntityModel;
import org.qi4j.spi.module.ModelModule;
import org.qi4j.runtime.structure.ModuleUnitOfWork;
import org.qi4j.spi.entity.EntityState;
import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
/**
* Implementation of EntityBuilder. Maintains an instance of the entity which
* will not have its state validated until it is created by calling newInstance().
*/
public final class EntityBuilderInstance<T>
implements EntityBuilder<T>
{
private static final QualifiedName IDENTITY_STATE_NAME;
private final ModelModule<EntityModel> model;
private final ModuleUnitOfWork uow;
private final EntityStoreUnitOfWork store;
private String identity;
private final BuilderEntityState entityState;
private final EntityInstance prototypeInstance;
static
{
try
{
IDENTITY_STATE_NAME = QualifiedName.fromAccessor( Identity.class.getMethod( "identity" ) );
}
catch( NoSuchMethodException e )
{
throw new InternalError( "Zest Core Runtime codebase is corrupted. Contact Zest team: EntityBuilderInstance" );
}
}
public EntityBuilderInstance(
ModelModule<EntityModel> model,
ModuleUnitOfWork uow,
EntityStoreUnitOfWork store,
String identity
)
{
this( model, uow, store, identity, null );
}
public EntityBuilderInstance(
ModelModule<EntityModel> model,
ModuleUnitOfWork uow,
EntityStoreUnitOfWork store,
String identity,
FunctionStateResolver stateResolver
)
{
this.model = model;
this.uow = uow;
this.store = store;
this.identity = identity;
EntityReference reference = new EntityReference( identity );
entityState = new BuilderEntityState( model.model(), reference );
model.model().initState( model.module(), entityState );
if( stateResolver != null )
{
stateResolver.populateState( model.model(), entityState );
}
entityState.setPropertyValue( IDENTITY_STATE_NAME, identity );
prototypeInstance = model.model().newInstance( uow, model.module(), entityState );
}
@SuppressWarnings( "unchecked" )
@Override
public T instance()
{
checkValid();
return prototypeInstance.<T>proxy();
}
@Override
public <K> K instanceFor( Class<K> mixinType )
{
checkValid();
return prototypeInstance.newProxy( mixinType );
}
@Override
@SuppressWarnings( "unchecked" )
public T newInstance()
throws LifecycleException
{
checkValid();
String identity;
// Figure out whether to use given or generated identity
identity = (String) entityState.propertyValueOf( IDENTITY_STATE_NAME );
EntityState newEntityState = model.model().newEntityState( store, uow.module(),
EntityReference.parseEntityReference( identity ) );
prototypeInstance.invokeCreate();
// Check constraints
prototypeInstance.checkConstraints();
entityState.copyTo( newEntityState );
EntityInstance instance = model.model().newInstance( uow, model.module(), newEntityState );
Object proxy = instance.proxy();
// Add entity in UOW
uow.addEntity( instance );
// Invalidate builder
this.identity = null;
return (T) proxy;
}
private void checkValid()
throws IllegalStateException
{
if( identity == null )
{
throw new IllegalStateException( "EntityBuilder is not valid after call to newInstance()" );
}
}
}