blob: 08e268ddbda4f39248afaa8ec219ff3c760b780f [file] [log] [blame]
/*
* Copyright (c) 2009, Rickard Öberg. 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.spi.entitystore;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import org.qi4j.api.entity.EntityReference;
import org.qi4j.api.injection.scope.This;
import org.qi4j.api.mixin.Mixins;
import org.qi4j.api.usecase.Usecase;
import org.qi4j.spi.entity.EntityState;
import org.qi4j.spi.entity.EntityStatus;
import org.qi4j.spi.module.ModuleSpi;
/**
* Entity versions state.
*/
@Mixins( EntityStateVersions.EntityStateVersionsMixin.class )
public interface EntityStateVersions
{
void forgetVersions( Iterable<EntityState> states );
void rememberVersion( EntityReference identity, String version );
void checkForConcurrentModification( Iterable<EntityState> loaded, ModuleSpi module, long currentTime )
throws ConcurrentEntityStateModificationException;
/**
* Entity versions state mixin.
*/
class EntityStateVersionsMixin
implements EntityStateVersions
{
@This
private EntityStore store;
private final Map<EntityReference, String> versions = new WeakHashMap<>();
@Override
public synchronized void forgetVersions( Iterable<EntityState> states )
{
for( EntityState state : states )
{
versions.remove( state.identity() );
}
}
@Override
public synchronized void rememberVersion( EntityReference identity, String version )
{
versions.put( identity, version );
}
@Override
public synchronized void checkForConcurrentModification( Iterable<EntityState> loaded,
ModuleSpi module,
long currentTime
)
throws ConcurrentEntityStateModificationException
{
List<EntityReference> changed = null;
for( EntityState entityState : loaded )
{
if( entityState.status().equals( EntityStatus.NEW ) )
{
continue;
}
String storeVersion = versions.get( entityState.identity() );
if( storeVersion == null )
{
EntityStoreUnitOfWork unitOfWork = store.newUnitOfWork( Usecase.DEFAULT, module, currentTime );
EntityState state = unitOfWork.entityStateOf( module, entityState.identity() );
storeVersion = state.version();
unitOfWork.discard();
}
if( !entityState.version().equals( storeVersion ) )
{
if( changed == null )
{
changed = new ArrayList<>();
}
changed.add( entityState.identity() );
}
}
if( changed != null )
{
throw new ConcurrentEntityStateModificationException( changed );
}
}
}
}