@Override
public Representation post( Representation entityRepresentation, Variant variant )
throws ResourceException
{
Usecase usecase = UsecaseBuilder.newUsecase( "Update entity" );
EntityStoreUnitOfWork unitOfWork = entityStore.newUnitOfWork( usecase, module, System.currentTimeMillis() );
EntityState entity = getEntityState( unitOfWork );
Form form = new Form( entityRepresentation );
try
{
final EntityDescriptor descriptor = entity.entityDescriptor();
// Parse JSON into properties
for( PropertyDescriptor persistentProperty : descriptor.state().properties() )
{
if( !persistentProperty.isImmutable() )
{
String formValue = form.getFirstValue( persistentProperty.qualifiedName().name(), null );
if( formValue == null )
{
entity.setPropertyValue( persistentProperty.qualifiedName(), null );
}
else
{
entity.setPropertyValue(
persistentProperty.qualifiedName(),
valueSerialization.deserialize( persistentProperty.valueType(), formValue ) );
}
}
}
for( AssociationDescriptor associationType : descriptor.state().associations() )
{
String newStringAssociation = form.getFirstValue( associationType.qualifiedName().name() );
if( newStringAssociation == null || newStringAssociation.isEmpty() )
{
entity.setAssociationValue( associationType.qualifiedName(), null );
}
else
{
entity.setAssociationValue( associationType.qualifiedName(),
EntityReference.parseEntityReference( newStringAssociation ) );
}
}
for( AssociationDescriptor associationType : descriptor.state().manyAssociations() )
{
String newStringAssociation = form.getFirstValue( associationType.qualifiedName().name() );
ManyAssociationState manyAssociation = entity.manyAssociationValueOf( associationType.qualifiedName() );
if( newStringAssociation == null )
{
// Remove "left-overs"
for( EntityReference entityReference : manyAssociation )
{
manyAssociation.remove( entityReference );
}
continue;
}
BufferedReader bufferedReader = new BufferedReader( new StringReader( newStringAssociation ) );
String identity;
try
{
// Synchronize old and new association
int index = 0;
while( ( identity = bufferedReader.readLine() ) != null )
{
EntityReference reference = new EntityReference( identity );
if( manyAssociation.count() < index && manyAssociation.get( index ).equals( reference ) )
{
continue;
}
try
{
unitOfWork.entityStateOf( reference );
manyAssociation.remove( reference );
manyAssociation.add( index++, reference );
}
catch( EntityNotFoundException e )
{
// Ignore this entity - doesn't exist
}
}
// Remove "left-overs"
while( manyAssociation.count() > index )
{
manyAssociation.remove( manyAssociation.get( index ) );
}
}
catch( IOException e )
{
// Ignore
}
}
for( AssociationDescriptor associationType : descriptor.state().namedAssociations() )
{
String newStringAssociation = form.getFirstValue( associationType.qualifiedName().name() );
NamedAssociationState namedAssociation = entity.namedAssociationValueOf( associationType.qualifiedName() );
if( newStringAssociation == null )
{
// Remove "left-overs"
for( String name : namedAssociation )
{
namedAssociation.remove( name );
}
continue;
}
Set<String> names = new HashSet<>();
BufferedReader bufferedReader = new BufferedReader( new StringReader( newStringAssociation ) );
String line;
try
{
while( ( line = bufferedReader.readLine() ) != null )
{
String name = line;
line = bufferedReader.readLine();
if( line == null )
{
break;
}
String identity = line;
EntityReference reference = new EntityReference( identity );
try
{
unitOfWork.entityStateOf( reference );
namedAssociation.remove( name );
namedAssociation.put( name, reference );
names.add( name );
}
catch( EntityNotFoundException e )
{
// Ignore this entity - doesn't exist
}
}
// Remove "left-overs"
for( String assocName : Iterables.toList( namedAssociation ) )
{
if( !names.contains( assocName ) )
{
namedAssociation.remove( assocName );
}
}
}
catch( IOException e )
{
// Ignore
}
}
}
catch( ValueSerializationException | IllegalArgumentException e )
{
throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e );
}
try
{
unitOfWork.applyChanges().commit();
}
catch( ConcurrentEntityStateModificationException e )
{
throw new ResourceException( Status.CLIENT_ERROR_CONFLICT );
}