polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From paulmer...@apache.org
Subject [14/19] polygene-java git commit: Serialization 3 step 1
Date Fri, 03 Feb 2017 07:58:15 GMT
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
index 82d4c05..a7f7690 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
@@ -14,8 +14,6 @@
  *  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.polygene.spi.entitystore.helpers;
 
@@ -24,12 +22,18 @@ import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.io.Reader;
+import java.io.StringReader;
 import java.io.Writer;
 import java.time.Instant;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
+import java.util.function.Function;
 import java.util.stream.Stream;
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonReader;
 import org.apache.polygene.api.cache.CacheOptions;
 import org.apache.polygene.api.common.Optional;
 import org.apache.polygene.api.entity.EntityDescriptor;
@@ -42,13 +46,11 @@ import org.apache.polygene.api.injection.scope.Structure;
 import org.apache.polygene.api.injection.scope.This;
 import org.apache.polygene.api.injection.scope.Uses;
 import org.apache.polygene.api.service.ServiceDescriptor;
-import org.apache.polygene.api.service.qualifier.Tagged;
 import org.apache.polygene.api.structure.Application;
 import org.apache.polygene.api.structure.ModuleDescriptor;
 import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
 import org.apache.polygene.api.usecase.Usecase;
-import org.apache.polygene.api.value.ValueSerialization;
-import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.serialization.javaxjson.JavaxJson;
 import org.apache.polygene.spi.cache.Cache;
 import org.apache.polygene.spi.cache.CachePool;
 import org.apache.polygene.spi.cache.NullCache;
@@ -60,9 +62,7 @@ import org.apache.polygene.spi.entitystore.EntityStoreException;
 import org.apache.polygene.spi.entitystore.EntityStoreSPI;
 import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
 import org.apache.polygene.spi.entitystore.StateCommitter;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONTokener;
+import org.apache.polygene.spi.serialization.JsonSerialization;
 
 /**
  * Implementation of EntityStore that works with an implementation of MapEntityStore.
@@ -82,14 +82,10 @@ public class JSONMapEntityStoreMixin
     private EntityStoreSPI entityStoreSpi;
 
     @Structure
-    private PolygeneSPI spi;
-
-    @Structure
     private Application application;
 
     @Service
-    @Tagged( ValueSerialization.Formats.JSON )
-    private ValueSerialization valueSerialization;
+    private JsonSerialization serialization;
 
     @Service
     IdentityGenerator identityGenerator;
@@ -107,7 +103,6 @@ public class JSONMapEntityStoreMixin
     private Cache<CacheState> cache;
 
     protected String uuid;
-    private int count;
 
     public JSONMapEntityStoreMixin()
     {
@@ -142,102 +137,109 @@ public class JSONMapEntityStoreMixin
     // EntityStore
 
     @Override
-    public EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecaseMetaInfo, Instant currentTime )
+    public EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecase, Instant currentTime )
     {
-        return new DefaultEntityStoreUnitOfWork( module, entityStoreSpi, newUnitOfWorkId(), usecaseMetaInfo, currentTime );
+        return new DefaultEntityStoreUnitOfWork( module, entityStoreSpi, newUnitOfWorkId(), usecase, currentTime );
     }
 
     // EntityStoreSPI
 
     @Override
-    public EntityState newEntityState( EntityStoreUnitOfWork unitOfWork,
+    public EntityState newEntityState( EntityStoreUnitOfWork uow,
                                        EntityReference reference,
                                        EntityDescriptor entityDescriptor
     )
     {
         try
         {
-            JSONObject state = new JSONObject();
-            state.put( JSONKeys.IDENTITY, reference.identity() );
-            state.put( JSONKeys.APPLICATION_VERSION, application.version() );
-            state.put( JSONKeys.TYPE, entityDescriptor.types().findFirst().get().getName() );
-            state.put( JSONKeys.VERSION, unitOfWork.identity() );
-            state.put( JSONKeys.MODIFIED, unitOfWork.currentTime().toEpochMilli() );
-            state.put( JSONKeys.PROPERTIES, new JSONObject() );
-            state.put( JSONKeys.ASSOCIATIONS, new JSONObject() );
-            state.put( JSONKeys.MANY_ASSOCIATIONS, new JSONObject() );
-            state.put( JSONKeys.NAMED_ASSOCIATIONS, new JSONObject() );
-            return new JSONEntityState( entityDescriptor.module(),
-                                        valueSerialization,
-                                        "",
-                                        unitOfWork.currentTime(),
+            JsonObjectBuilder builder = Json.createObjectBuilder();
+            builder.add( JSONKeys.IDENTITY, reference.identity().toString() );
+            builder.add( JSONKeys.APPLICATION_VERSION, application.version() );
+            builder.add( JSONKeys.TYPE, entityDescriptor.types().findFirst().get().getName() );
+            builder.add( JSONKeys.VERSION, uow.identity().toString() );
+            builder.add( JSONKeys.MODIFIED, uow.currentTime().toEpochMilli() );
+            builder.add( JSONKeys.PROPERTIES, Json.createObjectBuilder().build() );
+            builder.add( JSONKeys.ASSOCIATIONS, Json.createObjectBuilder().build() );
+            builder.add( JSONKeys.MANY_ASSOCIATIONS, Json.createObjectBuilder().build() );
+            builder.add( JSONKeys.NAMED_ASSOCIATIONS, Json.createObjectBuilder().build() );
+            JsonObject state = builder.build();
+            return new JSONEntityState( entityDescriptor.module(), serialization,
+                                        "", uow.currentTime(),
                                         reference,
-                                        EntityStatus.NEW,
-                                        entityDescriptor,
+                                        EntityStatus.NEW, entityDescriptor,
                                         state );
         }
-        catch( JSONException e )
+        catch( Exception e )
         {
             throw new EntityStoreException( e );
         }
     }
 
     @Override
-    public synchronized EntityState entityStateOf( EntityStoreUnitOfWork unitOfWork,
+    public synchronized EntityState entityStateOf( EntityStoreUnitOfWork uow,
                                                    ModuleDescriptor module,
-                                                   EntityReference reference
-    )
+                                                   EntityReference reference )
     {
-        EntityState state = fetchCachedState( reference, module, unitOfWork.currentTime() );
-        if( state != null )
+        try
         {
-            return state;
+            EntityState state = fetchCachedState( reference, module, uow.currentTime() );
+            if( state != null )
+            {
+                return state;
+            }
+            // Get state
+            try( Reader in = mapEntityStore.get( reference ) )
+            {
+                JSONEntityState loadedState = readEntityState( module, in );
+                if( loadedState.status() == EntityStatus.UPDATED )
+                {
+                    List<JSONEntityState> migrated = new ArrayList<>( 1 );
+                    migrated.add( loadedState );
+                    synchMigratedEntities( migrated );
+                }
+                if( doCacheOnRead( uow ) )
+                {
+                    cache.put( reference.identity().toString(), new CacheState( loadedState.state() ) );
+                }
+                return loadedState;
+            }
         }
-        // Get state
-        Reader in = mapEntityStore.get( reference );
-        JSONEntityState loadedState = readEntityState( module, in );
-        if( doCacheOnRead( unitOfWork ) )
+        catch( EntityStoreException ex )
         {
-            cache.put( reference.identity().toString(), new CacheState( loadedState.state() ) );
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
         }
-        return loadedState;
     }
 
     @Override
-    public synchronized String versionOf( EntityStoreUnitOfWork unitOfWork,
-                                          EntityReference reference
-    )
+    public synchronized String versionOf( EntityStoreUnitOfWork uow, EntityReference reference )
     {
         CacheState cacheState = cache.get( reference.identity().toString() );
         if( cacheState != null )
         {
-            try
-            {
-                return cacheState.json.getString( JSONKeys.VERSION );
-            }
-            catch( JSONException e )
-            {
-                // Should not be able to happen, unless internal error in the cache system.
-                throw new EntityStoreException( e );
-            }
+            return cacheState.json.getString( JSONKeys.VERSION );
         }
-        // Get state
-        Reader entityState = mapEntityStore.get( reference );
         try
         {
-            JSONObject jsonObject = new JSONObject( new JSONTokener( entityState ) );
-            return jsonObject.getString( JSONKeys.VERSION );
+            // Get state
+            Reader entityState = mapEntityStore.get( reference );
+            return Json.createReader( entityState ).readObject().getString( JSONKeys.VERSION );
         }
-        catch( JSONException e )
+        catch( EntityStoreException ex )
         {
-            throw new EntityStoreException( e );
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
         }
     }
 
     @Override
-    public StateCommitter applyChanges( final EntityStoreUnitOfWork unitOfWork,
-                                        final Iterable<EntityState> state
-    )
+    public StateCommitter applyChanges( EntityStoreUnitOfWork uow, Iterable<EntityState> state )
         throws EntityStoreException
     {
         return new StateCommitter()
@@ -250,10 +252,9 @@ public class JSONMapEntityStoreMixin
                     mapEntityStore.applyChanges( new MapEntityStore.MapChanges()
                     {
                         @Override
-                        public void visitMap( MapEntityStore.MapChanger changer )
-                            throws IOException
+                        public void visitMap( MapEntityStore.MapChanger changer ) throws Exception
                         {
-                            CacheOptions options = unitOfWork.usecase().metaInfo( CacheOptions.class );
+                            CacheOptions options = uow.usecase().metaInfo( CacheOptions.class );
                             if( options == null )
                             {
                                 options = CacheOptions.ALWAYS;
@@ -262,26 +263,35 @@ public class JSONMapEntityStoreMixin
                             for( EntityState entityState : state )
                             {
                                 JSONEntityState state = (JSONEntityState) entityState;
+                                String newVersion = uow.identity().toString();
+                                Instant lastModified = uow.currentTime();
                                 if( state.status().equals( EntityStatus.NEW ) )
                                 {
-                                    try (Writer writer = changer.newEntity( state.entityReference(), state.entityDescriptor() ))
+                                    try( Writer writer = changer.newEntity( state.entityReference(),
+                                                                            state.entityDescriptor() ) )
                                     {
-                                        writeEntityState( state, writer, unitOfWork.identity().toString(), unitOfWork.currentTime() );
+                                        writeEntityState( state, writer, newVersion, lastModified );
                                     }
                                     if( options.cacheOnNew() )
                                     {
-                                        cache.put( state.entityReference().identity().toString(), new CacheState( state.state() ) );
+                                        cache.put( state.entityReference().identity().toString(),
+                                                   new CacheState( state.state() ) );
                                     }
                                 }
                                 else if( state.status().equals( EntityStatus.UPDATED ) )
                                 {
-                                    try (Writer writer = changer.updateEntity( state.entityReference(), state.entityDescriptor() ))
+                                    MapEntityStore.MapChange mapChange = new MapEntityStore.MapChange(
+                                        state.entityReference(), state.entityDescriptor(),
+                                        state.version(), newVersion, lastModified
+                                    );
+                                    try( Writer writer = changer.updateEntity( mapChange ) )
                                     {
-                                        writeEntityState( state, writer, unitOfWork.identity().toString(), unitOfWork.currentTime() );
+                                        writeEntityState( state, writer, newVersion, lastModified );
                                     }
                                     if( options.cacheOnWrite() )
                                     {
-                                        cache.put( state.entityReference().identity().toString(), new CacheState( state.state() ) );
+                                        cache.put( state.entityReference().identity().toString(),
+                                                   new CacheState( state.state() ) );
                                     }
                                 }
                                 else if( state.status().equals( EntityStatus.REMOVED ) )
@@ -293,7 +303,7 @@ public class JSONMapEntityStoreMixin
                         }
                     } );
                 }
-                catch( IOException e )
+                catch( Exception e )
                 {
                     throw new EntityStoreException( e );
                 }
@@ -309,11 +319,13 @@ public class JSONMapEntityStoreMixin
     @Override
     public Stream<EntityState> entityStates( ModuleDescriptor module )
     {
-        List<EntityState> migrated = new ArrayList<>();
-        return mapEntityStore.entityStates().map(
-            reader ->
+        try
+        {
+            Stream<Reader> stateStream = mapEntityStore.entityStates();
+            List<JSONEntityState> migrated = new ArrayList<>();
+            Function<Reader, EntityState> function = reader ->
             {
-                EntityState entity = readEntityState( module, reader );
+                JSONEntityState entity = readEntityState( module, reader );
                 if( entity.status() == EntityStatus.UPDATED )
                 {
                     migrated.add( entity );
@@ -324,42 +336,55 @@ public class JSONMapEntityStoreMixin
                     }
                 }
                 return entity;
-            }
-        ).onClose(
-            () ->
+            };
+            Runnable closer = () ->
             {
                 // Synch any remaining migrated entities
                 if( !migrated.isEmpty() )
                 {
                     synchMigratedEntities( migrated );
                 }
-            }
-        );
+            };
+            return stateStream.map( function ).onClose( closer );
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
     }
 
-    private void synchMigratedEntities( final List<EntityState> migratedEntities )
+    private void synchMigratedEntities( List<JSONEntityState> migratedEntities )
     {
         try
         {
-            mapEntityStore.applyChanges( new MapEntityStore.MapChanges()
-            {
-                @Override
-                public void visitMap( MapEntityStore.MapChanger changer )
-                    throws IOException
+            mapEntityStore.applyChanges(
+                changer ->
                 {
-                    for( EntityState migratedEntity : migratedEntities )
+                    for( JSONEntityState state : migratedEntities )
                     {
-                        JSONEntityState state = (JSONEntityState) migratedEntity;
-                        try( Writer writer = changer.updateEntity( state.entityReference(), state.entityDescriptor() ) )
+                        Instant lastModified = state.lastModified();
+                        String version = state.version();
+                        MapEntityStore.MapChange changeInfo = new MapEntityStore.MapChange(
+                            state.entityReference(), state.entityDescriptor(),
+                            version, version, lastModified
+                        );
+                        try( Writer writer = changer.updateEntity( changeInfo ) )
                         {
-                            writeEntityState( state, writer, state.version(), state.lastModified() );
+                            writeEntityState( state, writer, version, lastModified );
                         }
                     }
-                }
-            } );
+                } );
             migratedEntities.clear();
         }
-        catch( IOException ex )
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
         {
             throw new EntityStoreException( "Synchronization of Migrated Entities failed.", ex );
         }
@@ -367,20 +392,18 @@ public class JSONMapEntityStoreMixin
 
     protected Identity newUnitOfWorkId()
     {
-        return identityGenerator.generate(EntityStore.class);
+        return identityGenerator.generate( EntityStore.class );
     }
 
-    protected void writeEntityState(JSONEntityState state, Writer writer, String version, Instant lastModified )
+    protected void writeEntityState( JSONEntityState state, Writer writer, String version, Instant lastModified )
         throws EntityStoreException
     {
         try
         {
-            JSONObject jsonState = state.state();
-            jsonState.put( JSONKeys.VERSION, version );
-            jsonState.put( JSONKeys.MODIFIED, lastModified.toEpochMilli() );
-            writer.append( jsonState.toString() );
+            state.stateCloneWithVersionAndModified( version, lastModified );
+            writer.append( state.state().toString() );
         }
-        catch( JSONException | IOException e )
+        catch( IOException e )
         {
             throw new EntityStoreException( "Could not store EntityState", e );
         }
@@ -391,37 +414,38 @@ public class JSONMapEntityStoreMixin
     {
         try
         {
-            JSONObject jsonObject = new JSONObject( new JSONTokener( entityState ) );
+            JsonObject parsedState = Json.createReader( entityState ).readObject();
+            JsonObjectBuilder jsonStateBuilder = JavaxJson.toBuilder( parsedState );
             EntityStatus status = EntityStatus.LOADED;
 
-            String version = jsonObject.getString( JSONKeys.VERSION );
-            Instant modified = Instant.ofEpochMilli(jsonObject.getLong( JSONKeys.MODIFIED ));
-            Identity identity = new StringIdentity(jsonObject.getString( JSONKeys.IDENTITY ));
+            String version = parsedState.getString( JSONKeys.VERSION );
+            Instant modified = Instant.ofEpochMilli( parsedState.getJsonNumber( JSONKeys.MODIFIED ).longValueExact() );
+            Identity identity = new StringIdentity( parsedState.getString( JSONKeys.IDENTITY ) );
 
-            // Check if NamedAssociation is supported
-            if( !jsonObject.has( JSONKeys.NAMED_ASSOCIATIONS ) )
+            // Check if version is correct
+            JsonObject state;
+            String currentAppVersion = parsedState.getString( JSONKeys.APPLICATION_VERSION, "0.0" );
+            if( currentAppVersion.equals( application.version() ) )
             {
-                jsonObject.put( JSONKeys.NAMED_ASSOCIATIONS, new JSONObject() );
+                state = jsonStateBuilder.build();
             }
-
-            // Check if version is correct
-            String currentAppVersion = jsonObject.optString( JSONKeys.APPLICATION_VERSION, "0.0" );
-            if( !currentAppVersion.equals( application.version() ) )
+            else
             {
                 if( migration != null )
                 {
-                    migration.migrate( jsonObject, application.version(), this );
+                    state = migration.migrate( jsonStateBuilder.build(), application.version(), this );
                 }
                 else
                 {
                     // Do nothing - set version to be correct
-                    jsonObject.put( JSONKeys.APPLICATION_VERSION, application.version() );
+                    jsonStateBuilder.add( JSONKeys.APPLICATION_VERSION, application.version() );
+                    state = jsonStateBuilder.build();
                 }
                 // State changed
                 status = EntityStatus.UPDATED;
             }
 
-            String type = jsonObject.getString( JSONKeys.TYPE );
+            String type = state.getString( JSONKeys.TYPE );
 
             EntityDescriptor entityDescriptor = module.entityDescriptor( type );
             if( entityDescriptor == null )
@@ -429,33 +453,40 @@ public class JSONMapEntityStoreMixin
                 throw new NoSuchEntityTypeException( type, module.name(), module.typeLookup() );
             }
 
-            return new JSONEntityState( module,
-                                        valueSerialization,
-                                        version,
-                                        modified,
+            return new JSONEntityState( module, serialization,
+                                        version, modified,
                                         EntityReference.create( identity ),
-                                        status,
-                                        entityDescriptor,
-                                        jsonObject
+                                        status, entityDescriptor,
+                                        state
             );
         }
-        catch( JSONException e )
+        catch( EntityStoreException ex )
         {
-            throw new EntityStoreException( e );
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
         }
     }
 
     @Override
-    public JSONObject jsonStateOf( String id )
-        throws IOException
+    public JsonObject jsonStateOf( String id )
     {
-        try (Reader reader = mapEntityStore.get( EntityReference.parseEntityReference( id ) ))
+        try( Reader reader = mapEntityStore.get( EntityReference.parseEntityReference( id ) ) )
+        {
+            try( JsonReader jsonReader = Json.createReader( reader ) )
+            {
+                return jsonReader.readObject();
+            }
+        }
+        catch( EntityStoreException ex )
         {
-            return new JSONObject( new JSONTokener( reader ) );
+            throw ex;
         }
-        catch( JSONException e )
+        catch( Exception ex )
         {
-            throw new IOException( e );
+            throw new EntityStoreException( ex );
         }
     }
 
@@ -464,15 +495,20 @@ public class JSONMapEntityStoreMixin
         CacheState cacheState = cache.get( reference.identity().toString() );
         if( cacheState != null )
         {
-            JSONObject data = cacheState.json;
+            JsonObject data = cacheState.json;
             try
             {
                 String type = data.getString( JSONKeys.TYPE );
                 EntityDescriptor entityDescriptor = module.entityDescriptor( type );
-                Instant lastModified = Instant.ofEpochMilli(data.getLong(JSONKeys.MODIFIED));
-                return new JSONEntityState( module, valueSerialization, data.getString( JSONKeys.VERSION ), lastModified, reference, EntityStatus.LOADED, entityDescriptor, data );
+                String version = data.getString( JSONKeys.VERSION );
+                Instant lastModified = Instant.ofEpochMilli( data.getJsonNumber( JSONKeys.MODIFIED ).longValueExact() );
+                return new JSONEntityState( module, serialization,
+                                            version, lastModified,
+                                            reference,
+                                            EntityStatus.LOADED, entityDescriptor,
+                                            data );
             }
-            catch( JSONException e )
+            catch( Exception e )
             {
                 // Should not be able to happen, unless internal error in the cache system.
                 throw new EntityStoreException( e );
@@ -490,13 +526,13 @@ public class JSONMapEntityStoreMixin
     public static class CacheState
         implements Externalizable
     {
-        public JSONObject json;
+        public JsonObject json;
 
         public CacheState()
         {
         }
 
-        private CacheState( JSONObject state )
+        private CacheState( JsonObject state )
         {
             json = state;
         }
@@ -512,14 +548,7 @@ public class JSONMapEntityStoreMixin
         public void readExternal( ObjectInput in )
             throws IOException, ClassNotFoundException
         {
-            try
-            {
-                json = new JSONObject( in.readUTF() );
-            }
-            catch( JSONException e )
-            {
-                throw new IOException( e );
-            }
+            json = Json.createReader( new StringReader( in.readUTF() ) ).readObject();
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java
index d37bb9c..74ea667 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java
@@ -19,42 +19,56 @@
  */
 package org.apache.polygene.spi.entitystore.helpers;
 
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 import java.util.NoSuchElementException;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.Json;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
 import org.apache.polygene.api.entity.EntityReference;
 import org.apache.polygene.spi.entity.NamedAssociationState;
 import org.apache.polygene.spi.entitystore.EntityStoreException;
 
 /**
  * JSON implementation of NamedAssociationState.
- * <p>Backed by a JSONObject.</p>
+ * <p>Backed by a JsonObject.</p>
  */
 public final class JSONNamedAssociationState
     implements NamedAssociationState
 {
 
     private final JSONEntityState entityState;
-    private final JSONObject references;
+    private final String stateName;
 
-    public JSONNamedAssociationState( JSONEntityState entityState, JSONObject references )
+    /* package */ JSONNamedAssociationState( JSONEntityState entityState, String stateName )
     {
         this.entityState = entityState;
-        this.references = references;
+        this.stateName = stateName;
+    }
+
+    private JsonObject getReferences()
+    {
+        JsonObject namedAssociations = entityState.state().getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
+        JsonValue references = namedAssociations.get( stateName );
+        if( references != null && references.getValueType() == JsonValue.ValueType.OBJECT )
+        {
+            return (JsonObject) references;
+        }
+        return Json.createObjectBuilder().build();
     }
 
     @Override
     public int count()
     {
-        return references.length();
+        return getReferences().size();
     }
 
     @Override
     public boolean containsName( String name )
     {
-        return references.has( name );
+        return getReferences().containsKey( name );
     }
 
     @Override
@@ -62,16 +76,16 @@ public final class JSONNamedAssociationState
     {
         try
         {
-            if( references.has( name ) && entityReference.identity().toString().equals( references.getString( name ) ) )
+            if( containsName( name )
+                && entityReference.identity().toString().equals( getReferences().getString( name ) ) )
             {
                 return false;
             }
-            entityState.cloneStateIfGlobalStateLoaded();
-            references.put( name, entityReference.identity().toString() );
+            entityState.stateCloneAddNamedAssociation( stateName, name, entityReference );
             entityState.markUpdated();
             return true;
         }
-        catch( JSONException ex )
+        catch( JsonException ex )
         {
             throw new EntityStoreException( ex );
         }
@@ -80,12 +94,11 @@ public final class JSONNamedAssociationState
     @Override
     public boolean remove( String name )
     {
-        if( !references.has( name ) )
+        if( !containsName( name ) )
         {
             return false;
         }
-        entityState.cloneStateIfGlobalStateLoaded();
-        references.remove( name );
+        entityState.stateCloneRemoveNamedAssociation( stateName, name );
         entityState.markUpdated();
         return true;
     }
@@ -93,29 +106,18 @@ public final class JSONNamedAssociationState
     @Override
     public EntityReference get( String name )
     {
-        try
-        {
-            return EntityReference.parseEntityReference( references.getString( name ) );
-        }
-        catch( JSONException ex )
-        {
-            return null;
-        }
+        String stringRef = getReferences().getString( name, null );
+        return stringRef == null ? null : EntityReference.parseEntityReference( stringRef );
     }
 
     @Override
     public String nameOf( EntityReference entityReference )
     {
-        JSONArray names = references.names();
-        if( names == null )
-        {
-            return null;
-        }
         try
         {
-            for( int idx = 0; idx < names.length(); idx++ )
+            JsonObject references = getReferences();
+            for( String name : references.keySet() )
             {
-                String name = names.getString( idx );
                 if( entityReference.identity().toString().equals( references.getString( name ) ) )
                 {
                     return name;
@@ -123,7 +125,7 @@ public final class JSONNamedAssociationState
             }
             return null;
         }
-        catch( JSONException ex )
+        catch( JsonException ex )
         {
             throw new EntityStoreException( ex );
         }
@@ -132,7 +134,7 @@ public final class JSONNamedAssociationState
     @Override
     public Iterator<String> iterator()
     {
-        final JSONArray names = references.names() == null ? new JSONArray() : references.names();
+        List<String> names = new ArrayList<>( getReferences().keySet() );
         return new Iterator<String>()
         {
             private int idx = 0;
@@ -140,7 +142,7 @@ public final class JSONNamedAssociationState
             @Override
             public boolean hasNext()
             {
-                return idx < names.length();
+                return idx < names.size();
             }
 
             @Override
@@ -148,11 +150,11 @@ public final class JSONNamedAssociationState
             {
                 try
                 {
-                    String next = names.getString( idx );
+                    String next = names.get( idx );
                     idx++;
                     return next;
                 }
-                catch( JSONException ex )
+                catch( JsonException ex )
                 {
                     throw new NoSuchElementException();
                 }
@@ -169,7 +171,6 @@ public final class JSONNamedAssociationState
     @Override
     public String toString()
     {
-        return references.toString();
+        return getReferences().toString();
     }
-
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStore.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStore.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStore.java
index a8ff1c9..901c2c1 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStore.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStore.java
@@ -22,48 +22,41 @@ package org.apache.polygene.spi.entitystore.helpers;
 import java.io.IOException;
 import java.io.Reader;
 import java.io.Writer;
+import java.time.Instant;
 import java.util.stream.Stream;
 import org.apache.polygene.api.entity.EntityDescriptor;
 import org.apache.polygene.api.entity.EntityReference;
-import org.apache.polygene.spi.entitystore.EntityNotFoundException;
-import org.apache.polygene.spi.entitystore.EntityStoreException;
 
 /**
  * MapEntityStore.
  */
 public interface MapEntityStore
 {
-
     /**
      * @param entityReference The reference to the entity that we want to get.
      * @return Entity state Reader
      */
-    Reader get( EntityReference entityReference )
-        throws EntityStoreException;
+    Reader get( EntityReference entityReference ) throws Exception;
 
     /**
      * @return All entities state Readers, must be closed
      */
-    Stream<Reader> entityStates();
+    Stream<Reader> entityStates() throws Exception;
 
-    void applyChanges( MapChanges changes )
-        throws IOException;
+    void applyChanges( MapChanges changes ) throws Exception;
 
     /**
      * Changes to be applied on a MapEntityStore.
      */
     interface MapChanges
     {
-
         /**
          * Visitable MapChanges.
          *
          * @param changer Map changer
          * @throws IOException on error
          */
-        void visitMap( MapChanger changer )
-            throws IOException;
-
+        void visitMap( MapChanger changer ) throws Exception;
     }
 
     /**
@@ -71,16 +64,65 @@ public interface MapEntityStore
      */
     interface MapChanger
     {
-
         Writer newEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-            throws IOException;
+            throws Exception;
 
-        Writer updateEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-            throws IOException;
+        Writer updateEntity( MapChange mapChange ) throws Exception;
 
         void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-            throws EntityNotFoundException;
-
+            throws Exception;
     }
 
+    /**
+     * MapEntityStore change meta info.
+     *
+     * Implementations backed by a shared store can make use of this for e.g. optimistic locking.
+     */
+    class MapChange
+    {
+        private final EntityReference reference;
+        private final EntityDescriptor descriptor;
+        private final String previousVersion;
+        private final String newVersion;
+        private final Instant lastModified;
+
+        public MapChange( EntityReference reference, EntityDescriptor descriptor,
+                          String previousVersion, String newVersion,
+                          Instant lastModified )
+        {
+            this.reference = reference;
+            this.descriptor = descriptor;
+            this.previousVersion = previousVersion;
+            this.newVersion = newVersion;
+            this.lastModified = lastModified;
+        }
+
+        public EntityReference reference()
+        {
+            return reference;
+        }
+
+        public EntityDescriptor descriptor()
+        {
+            return descriptor;
+        }
+
+        /**
+         * @return null if the change is an insertion
+         */
+        public String previousVersion()
+        {
+            return previousVersion;
+        }
+
+        public String newVersion()
+        {
+            return newVersion;
+        }
+
+        public Instant lastModified()
+        {
+            return lastModified;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java
index 40cfa76..461c76d 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java
@@ -14,12 +14,9 @@
  *  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.polygene.spi.entitystore.helpers;
 
-import java.io.IOException;
 import java.io.Reader;
 import java.io.Writer;
 import java.time.Instant;
@@ -28,7 +25,15 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 import java.util.stream.Stream;
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonValue;
 import org.apache.polygene.api.common.Optional;
 import org.apache.polygene.api.common.QualifiedName;
 import org.apache.polygene.api.entity.EntityDescriptor;
@@ -39,15 +44,11 @@ import org.apache.polygene.api.identity.StringIdentity;
 import org.apache.polygene.api.injection.scope.Service;
 import org.apache.polygene.api.injection.scope.Structure;
 import org.apache.polygene.api.injection.scope.This;
-import org.apache.polygene.api.service.qualifier.Tagged;
 import org.apache.polygene.api.structure.Application;
 import org.apache.polygene.api.structure.ModuleDescriptor;
-import org.apache.polygene.api.type.ValueType;
 import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
 import org.apache.polygene.api.usecase.Usecase;
-import org.apache.polygene.api.value.ValueSerialization;
-import org.apache.polygene.api.value.ValueSerializationException;
-import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.serialization.javaxjson.JavaxJson;
 import org.apache.polygene.spi.entity.EntityState;
 import org.apache.polygene.spi.entity.EntityStatus;
 import org.apache.polygene.spi.entitystore.DefaultEntityStoreUnitOfWork;
@@ -56,11 +57,7 @@ import org.apache.polygene.spi.entitystore.EntityStoreException;
 import org.apache.polygene.spi.entitystore.EntityStoreSPI;
 import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
 import org.apache.polygene.spi.entitystore.StateCommitter;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONTokener;
-import org.json.JSONWriter;
+import org.apache.polygene.spi.serialization.JsonSerialization;
 
 /**
  * Implementation of EntityStore that works with an implementation of MapEntityStore.
@@ -80,14 +77,10 @@ public class MapEntityStoreMixin
     private EntityStoreSPI entityStoreSpi;
 
     @Structure
-    private PolygeneSPI spi;
-
-    @Structure
     private Application application;
 
     @Service
-    @Tagged( ValueSerialization.Formats.JSON )
-    private ValueSerialization valueSerialization;
+    private JsonSerialization jsonSerialization;
 
     @Optional
     @Service
@@ -97,58 +90,70 @@ public class MapEntityStoreMixin
     private IdentityGenerator identityGenerator;
 
     @Override
-    public void activateMapEntityStore()
-        throws Exception
-    {
-    }
+    public void activateMapEntityStore() {}
 
     // EntityStore
     @Override
-    public EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecaseMetaInfo, Instant currentTime )
+    public EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecase, Instant currentTime )
     {
-        return new DefaultEntityStoreUnitOfWork( module, entityStoreSpi, newUnitOfWorkId(), usecaseMetaInfo, currentTime );
+        return new DefaultEntityStoreUnitOfWork( module, entityStoreSpi, newUnitOfWorkId(),
+                                                 usecase, currentTime );
     }
 
     // EntityStoreSPI
     @Override
-    public EntityState newEntityState( EntityStoreUnitOfWork unitOfWork,
-                                       EntityReference reference,
-                                       EntityDescriptor entityDescriptor
-    )
+    public EntityState newEntityState( EntityStoreUnitOfWork uow,
+                                       EntityReference reference, EntityDescriptor entityDescriptor )
     {
-        return new DefaultEntityState( unitOfWork.currentTime(), reference, entityDescriptor );
+        return new DefaultEntityState( uow.currentTime(), reference, entityDescriptor );
     }
 
     @Override
-    public synchronized EntityState entityStateOf( EntityStoreUnitOfWork unitofwork,
-                                                   ModuleDescriptor module,
-                                                   EntityReference reference
-    )
+    public synchronized EntityState entityStateOf( EntityStoreUnitOfWork uow,
+                                                   ModuleDescriptor module, EntityReference reference )
     {
-        Reader in = mapEntityStore.get( reference );
-        return readEntityState( module, in );
+        try
+        {
+            Reader in = mapEntityStore.get( reference );
+            EntityState loadedState = readEntityState( module, in );
+            if( loadedState.status() == EntityStatus.UPDATED )
+            {
+                List<EntityState> migrated = new ArrayList<>( 1 );
+                migrated.add( loadedState );
+                synchMigratedEntities( migrated );
+            }
+            return loadedState;
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
     }
 
     @Override
-    public synchronized String versionOf( EntityStoreUnitOfWork unitofwork,
-                                          EntityReference reference
-    )
+    public synchronized String versionOf( EntityStoreUnitOfWork uow, EntityReference reference )
     {
-        Reader in = mapEntityStore.get( reference );
         try
         {
-            JSONObject jsonObject = new JSONObject( new JSONTokener( in ) );
-            return jsonObject.getString( JSONKeys.VERSION );
+            Reader in = mapEntityStore.get( reference );
+            return Json.createReader( in ).readObject().getString( JSONKeys.VERSION );
         }
-        catch( JSONException e )
+        catch( EntityStoreException ex )
         {
-            throw new EntityStoreException( e );
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
         }
     }
 
     @Override
-    public StateCommitter applyChanges( final EntityStoreUnitOfWork unitofwork, final Iterable<EntityState> state
-    )
+    public StateCommitter applyChanges( EntityStoreUnitOfWork uow, Iterable<EntityState> state )
         throws EntityStoreException
     {
         return new StateCommitter()
@@ -158,34 +163,47 @@ public class MapEntityStoreMixin
             {
                 try
                 {
-                    mapEntityStore.applyChanges( changer -> {
-                        for( EntityState entityState : state )
+                    mapEntityStore.applyChanges(
+                        changer ->
                         {
-                            DefaultEntityState state1 = (DefaultEntityState) entityState;
-                            if( state1.status().equals( EntityStatus.NEW ) )
+                            for( EntityState entityState : state )
                             {
-                                try (Writer writer = changer.newEntity( state1.entityReference(), state1.entityDescriptor() ))
+                                DefaultEntityState state1 = (DefaultEntityState) entityState;
+                                String newVersion = uow.identity().toString();
+                                Instant lastModified = uow.currentTime();
+                                if( state1.status().equals( EntityStatus.NEW ) )
                                 {
-                                    writeEntityState( state1, writer, unitofwork.identity().toString(), unitofwork.currentTime() );
+                                    try( Writer writer = changer.newEntity( state1.entityReference(),
+                                                                            state1.entityDescriptor() ) )
+                                    {
+                                        writeEntityState( state1, writer, newVersion, lastModified );
+                                    }
                                 }
-                            }
-                            else if( state1.status().equals( EntityStatus.UPDATED ) )
-                            {
-                                try (Writer writer = changer.updateEntity( state1.entityReference(), state1.entityDescriptor() ))
+                                else if( state1.status().equals( EntityStatus.UPDATED ) )
                                 {
-                                    writeEntityState( state1, writer, unitofwork.identity().toString(), unitofwork.currentTime() );
+                                    MapEntityStore.MapChange mapChange = new MapEntityStore.MapChange(
+                                        state1.entityReference(), state1.entityDescriptor(),
+                                        state1.version(), newVersion, lastModified
+                                    );
+                                    try( Writer writer = changer.updateEntity( mapChange ) )
+                                    {
+                                        writeEntityState( state1, writer, newVersion, lastModified );
+                                    }
+                                }
+                                else if( state1.status().equals( EntityStatus.REMOVED ) )
+                                {
+                                    changer.removeEntity( state1.entityReference(), state1.entityDescriptor() );
                                 }
                             }
-                            else if( state1.status().equals( EntityStatus.REMOVED ) )
-                            {
-                                changer.removeEntity( state1.entityReference(), state1.entityDescriptor() );
-                            }
-                        }
-                    } );
+                        } );
+                }
+                catch( EntityStoreException ex )
+                {
+                    throw ex;
                 }
-                catch( IOException e )
+                catch( Exception ex )
                 {
-                    throw new EntityStoreException( e );
+                    throw new EntityStoreException( ex );
                 }
             }
 
@@ -197,62 +215,90 @@ public class MapEntityStoreMixin
     }
 
     @Override
-    public Stream<EntityState> entityStates( final ModuleDescriptor module )
+    public Stream<EntityState> entityStates( ModuleDescriptor module )
     {
-        List<EntityState> migrated = new ArrayList<>();
-        return mapEntityStore
-            .entityStates()
-            .map( reader ->
-                  {
-                      EntityState entity = readEntityState( module, reader );
-                      if( entity.status() == EntityStatus.UPDATED )
-                      {
-                          migrated.add( entity );
-                          // Synch back 100 at a time
-                          if( migrated.size() > 100 )
-                          {
-                              try
-                              {
-                                  synchMigratedEntities( migrated );
-                              }
-                              catch( IOException e )
-                              {
-                                  throw new EntityStoreException( "Synchronization of Migrated Entities failed.", e );
-                              }
-                          }
-                      }
-                      return entity;
-                  } )
-            .onClose( () ->
-                      {
-                          // Synch any remaining migrated entities
-                          if( !migrated.isEmpty() )
-                          {
-                              try
-                              {
-                                  synchMigratedEntities( migrated );
-                              }
-                              catch( IOException e )
-                              {
-                                  throw new EntityStoreException( "Synchronization of Migrated Entities failed.", e );
-                              }
-                          }
-                      } );
+        try
+        {
+            Stream<Reader> stateStream = mapEntityStore.entityStates();
+            List<EntityState> migrated = new ArrayList<>();
+            String migrationErrorMsg = "Synchronization of Migrated Entities failed.";
+            Function<Reader, EntityState> function = reader ->
+            {
+                EntityState entity = readEntityState( module, reader );
+                if( entity.status() == EntityStatus.UPDATED )
+                {
+                    migrated.add( entity );
+                    // Sync back 100 at a time
+                    if( migrated.size() > 100 )
+                    {
+                        try
+                        {
+                            synchMigratedEntities( migrated );
+                        }
+                        catch( EntityStoreException ex )
+                        {
+                            throw ex;
+                        }
+                        catch( Exception ex )
+                        {
+                            throw new EntityStoreException( migrationErrorMsg, ex );
+                        }
+                    }
+                }
+                return entity;
+            };
+            Runnable closer = () ->
+            {
+                // Sync any remaining migrated entities
+                if( !migrated.isEmpty() )
+                {
+                    try
+                    {
+                        synchMigratedEntities( migrated );
+                    }
+                    catch( EntityStoreException ex )
+                    {
+                        throw ex;
+                    }
+                    catch( Exception ex )
+                    {
+                        throw new EntityStoreException( migrationErrorMsg, ex );
+                    }
+                }
+            };
+            return stateStream.map( function ).onClose( closer );
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
     }
 
     private void synchMigratedEntities( final List<EntityState> migratedEntities )
-        throws IOException
+        throws Exception
     {
-        mapEntityStore.applyChanges( changer -> {
-            for( EntityState migratedEntity : migratedEntities )
+        mapEntityStore.applyChanges(
+            changer ->
             {
-                DefaultEntityState state = (DefaultEntityState) migratedEntity;
-                try (Writer writer = changer.updateEntity( state.entityReference(), state.entityDescriptor() ))
+                for( EntityState migratedEntity : migratedEntities )
                 {
-                    writeEntityState( state, writer, state.version(), state.lastModified() );
+                    DefaultEntityState state = (DefaultEntityState) migratedEntity;
+                    String version = state.version();
+                    Instant lastModified = state.lastModified();
+                    MapEntityStore.MapChange mapChange = new MapEntityStore.MapChange(
+                        state.entityReference(), state.entityDescriptor(),
+                        version, version, lastModified
+                    );
+                    try( Writer writer = changer.updateEntity( mapChange ) )
+                    {
+                        writeEntityState( state, writer, version, lastModified );
+                    }
                 }
-            }
-        } );
+            } );
         migratedEntities.clear();
     }
 
@@ -261,87 +307,63 @@ public class MapEntityStoreMixin
         return identityGenerator.generate( EntityStore.class );
     }
 
-    protected void writeEntityState(DefaultEntityState state, Writer writer, String version, Instant lastModified )
+    protected void writeEntityState( DefaultEntityState state, Writer writer, String version, Instant lastModified )
         throws EntityStoreException
     {
         try
         {
-            JSONWriter json = new JSONWriter( writer );
-            JSONWriter properties = json.object().
-                key( JSONKeys.IDENTITY ).value( state.entityReference().identity() ).
-                key( JSONKeys.APPLICATION_VERSION ).value( application.version() ).
-                key( JSONKeys.TYPE ).value( state.entityDescriptor().types().findFirst().get().getName() ).
-                key( JSONKeys.VERSION ).value( version ).
-                key( JSONKeys.MODIFIED ).value( lastModified.toEpochMilli() ).
-                key( JSONKeys.PROPERTIES ).object();
+            JsonObjectBuilder json = Json.createObjectBuilder();
+            json.add( JSONKeys.IDENTITY, state.entityReference().identity().toString() );
+            json.add( JSONKeys.APPLICATION_VERSION, application.version() );
+            json.add( JSONKeys.TYPE, state.entityDescriptor().primaryType().getName() );
+            json.add( JSONKeys.VERSION, version );
+            json.add( JSONKeys.MODIFIED, lastModified.toEpochMilli() );
+            JsonObjectBuilder properties = Json.createObjectBuilder();
             EntityDescriptor entityType = state.entityDescriptor();
-            entityType.state().properties().forEach( persistentProperty -> {
-                Object value = state.properties().get( persistentProperty.qualifiedName() );
-                try
-                {
-                    json.key( persistentProperty.qualifiedName().name() );
-                    if( value == null || ValueType.isPrimitiveValue( value ) )
-                    {
-                        json.value( value );
-                    }
-                    else
-                    {
-                        String serialized = valueSerialization.serialize( value );
-                        if( serialized.startsWith( "{" ) )
-                        {
-                            json.value( new JSONObject( serialized ) );
-                        }
-                        else if( serialized.startsWith( "[" ) )
-                        {
-                            json.value( new JSONArray( serialized ) );
-                        }
-                        else
-                        {
-                            json.value( serialized );
-                        }
-                    }
-                }
-                catch( JSONException e )
+            entityType.state().properties().forEach(
+                persistentProperty ->
                 {
-                    throw new ValueSerializationException( "Unable to write property " + persistentProperty, e );
-                }
-            } );
-
-            JSONWriter associations = properties.endObject().key( JSONKeys.ASSOCIATIONS ).object();
-            for( Map.Entry<QualifiedName, EntityReference> stateNameEntityReferenceEntry : state.associations()
-                .entrySet() )
+                    Object value = state.properties().get( persistentProperty.qualifiedName() );
+                    JsonValue jsonValue = jsonSerialization.toJson( value );
+                    properties.add( persistentProperty.qualifiedName().name(), jsonValue );
+                } );
+            json.add( JSONKeys.PROPERTIES, properties.build() );
+
+            JsonObjectBuilder associations = Json.createObjectBuilder();
+            for( Map.Entry<QualifiedName, EntityReference> entry : state.associations().entrySet() )
             {
-                EntityReference value = stateNameEntityReferenceEntry.getValue();
-                associations.key( stateNameEntityReferenceEntry.getKey().name() ).
-                    value( value != null ? value.identity() : null );
+                EntityReference value = entry.getValue();
+                associations.add( entry.getKey().name(), value == null ? null : value.identity().toString() );
             }
+            json.add( JSONKeys.ASSOCIATIONS, associations.build() );
 
-            JSONWriter manyAssociations = associations.endObject().key( JSONKeys.MANY_ASSOCIATIONS ).object();
-            for( Map.Entry<QualifiedName, List<EntityReference>> stateNameListEntry : state.manyAssociations()
-                .entrySet() )
+            JsonObjectBuilder manyAssociations = Json.createObjectBuilder();
+            for( Map.Entry<QualifiedName, List<EntityReference>> entry : state.manyAssociations().entrySet() )
             {
-                JSONWriter assocs = manyAssociations.key( stateNameListEntry.getKey().name() ).array();
-                for( EntityReference entityReference : stateNameListEntry.getValue() )
+                JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+                for( EntityReference entityReference : entry.getValue() )
                 {
-                    assocs.value( entityReference.identity() );
+                    arrayBuilder.add( entityReference.identity().toString() );
                 }
-                assocs.endArray();
+                manyAssociations.add( entry.getKey().name(), arrayBuilder.build() );
             }
+            json.add( JSONKeys.MANY_ASSOCIATIONS, manyAssociations.build() );
 
-            JSONWriter namedAssociations = manyAssociations.endObject().key( JSONKeys.NAMED_ASSOCIATIONS ).object();
-            for( Map.Entry<QualifiedName, Map<String, EntityReference>> stateNameMapEntry : state.namedAssociations()
-                .entrySet() )
+            JsonObjectBuilder namedAssociations = Json.createObjectBuilder();
+            for( Map.Entry<QualifiedName, Map<String, EntityReference>> entry : state.namedAssociations().entrySet() )
             {
-                JSONWriter assocs = namedAssociations.key( stateNameMapEntry.getKey().name() ).object();
-                for( Map.Entry<String, EntityReference> namedRef : stateNameMapEntry.getValue().entrySet() )
+                JsonObjectBuilder objectBuilder = Json.createObjectBuilder();
+                for( Map.Entry<String, EntityReference> namedRef : entry.getValue().entrySet() )
                 {
-                    assocs.key( namedRef.getKey() ).value( namedRef.getValue().identity() );
+                    objectBuilder.add( namedRef.getKey(), namedRef.getValue().identity().toString() );
                 }
-                assocs.endObject();
+                namedAssociations.add( entry.getKey().name(), objectBuilder.build() );
             }
-            namedAssociations.endObject().endObject();
+            json.add( JSONKeys.NAMED_ASSOCIATIONS, namedAssociations.build() );
+            JsonObject jsonState = json.build();
+            Json.createWriter( writer ).write( jsonState );
         }
-        catch( JSONException e )
+        catch( Exception e )
         {
             throw new EntityStoreException( "Could not store EntityState", e );
         }
@@ -352,31 +374,38 @@ public class MapEntityStoreMixin
     {
         try
         {
-            JSONObject jsonObject = new JSONObject( new JSONTokener( entityState ) );
+            JsonObject parsedState = Json.createReader( entityState ).readObject();
+            JsonObjectBuilder jsonStateBuilder = JavaxJson.toBuilder( parsedState );
             final EntityStatus[] status = { EntityStatus.LOADED };
 
-            String version = jsonObject.getString( JSONKeys.VERSION );
-            Instant modified = Instant.ofEpochMilli(jsonObject.getLong( JSONKeys.MODIFIED ));
-            Identity identity = new StringIdentity(jsonObject.getString( JSONKeys.IDENTITY ));
+            String version = parsedState.getString( JSONKeys.VERSION );
+            Instant modified = Instant.ofEpochMilli( parsedState.getJsonNumber( JSONKeys.MODIFIED ).longValueExact() );
+            Identity identity = new StringIdentity( parsedState.getString( JSONKeys.IDENTITY ) );
 
             // Check if version is correct
-            String currentAppVersion = jsonObject.optString( JSONKeys.APPLICATION_VERSION, "0.0" );
-            if( !currentAppVersion.equals( application.version() ) )
+            JsonObject state;
+            String currentAppVersion = parsedState.getString( JSONKeys.APPLICATION_VERSION, "0.0" );
+            if( currentAppVersion.equals( application.version() ) )
+            {
+                state = jsonStateBuilder.build();
+            }
+            else
             {
                 if( migration != null )
                 {
-                    migration.migrate( jsonObject, application.version(), this );
+                    state = migration.migrate( jsonStateBuilder.build(), application.version(), this );
                 }
                 else
                 {
                     // Do nothing - set version to be correct
-                    jsonObject.put( JSONKeys.APPLICATION_VERSION, application.version() );
+                    jsonStateBuilder.add( JSONKeys.APPLICATION_VERSION, application.version() );
+                    state = jsonStateBuilder.build();
                 }
                 // State changed
                 status[ 0 ] = EntityStatus.UPDATED;
             }
 
-            String type = jsonObject.getString( JSONKeys.TYPE );
+            String type = state.getString( JSONKeys.TYPE );
 
             EntityDescriptor entityDescriptor = module.entityDescriptor( type );
             if( entityDescriptor == null )
@@ -385,107 +414,101 @@ public class MapEntityStoreMixin
             }
 
             Map<QualifiedName, Object> properties = new HashMap<>();
-            JSONObject props = jsonObject.getJSONObject( JSONKeys.PROPERTIES );
-            entityDescriptor.state().properties().forEach( propertyDescriptor -> {
-                Object jsonValue;
-                try
+            JsonObject props = state.getJsonObject( JSONKeys.PROPERTIES );
+            entityDescriptor.state().properties().forEach(
+                property ->
                 {
-                    jsonValue = props.get( propertyDescriptor.qualifiedName().name() );
-                    if( JSONObject.NULL.equals( jsonValue ) )
+                    try
                     {
-                        properties.put( propertyDescriptor.qualifiedName(), null );
+                        JsonValue jsonValue = props.get( property.qualifiedName().name() );
+                        Object value = jsonSerialization.fromJson( module, property.valueType(), jsonValue );
+                        properties.put( property.qualifiedName(), value );
                     }
-                    else
+                    catch( JsonException e )
                     {
-                        Object value = valueSerialization.deserialize( module, propertyDescriptor.valueType(), jsonValue
-                            .toString() );
-                        properties.put( propertyDescriptor.qualifiedName(), value );
+                        // Value not found, default it
+                        Object initialValue = property.initialValue( module );
+                        properties.put( property.qualifiedName(), initialValue );
+                        status[ 0 ] = EntityStatus.UPDATED;
                     }
-                }
-                catch( JSONException e )
-                {
-                    // Value not found, default it
-                    Object initialValue = propertyDescriptor.initialValue( module );
-                    properties.put( propertyDescriptor.qualifiedName(), initialValue );
-                    status[ 0 ] = EntityStatus.UPDATED;
-                }
-            } );
+                } );
 
             Map<QualifiedName, EntityReference> associations = new HashMap<>();
-            JSONObject assocs = jsonObject.getJSONObject( JSONKeys.ASSOCIATIONS );
-            entityDescriptor.state().associations().forEach( associationType -> {
-                try
+            JsonObject assocs = state.getJsonObject( JSONKeys.ASSOCIATIONS );
+            entityDescriptor.state().associations().forEach(
+                association ->
                 {
-                    Object jsonValue = assocs.get( associationType.qualifiedName().name() );
-                    EntityReference value = jsonValue == JSONObject.NULL
-                                            ? null
-                                            : EntityReference.parseEntityReference( (String) jsonValue );
-                    associations.put( associationType.qualifiedName(), value );
-                }
-                catch( JSONException e )
-                {
-                    // Association not found, default it to null
-                    associations.put( associationType.qualifiedName(), null );
-                    status[ 0 ] = EntityStatus.UPDATED;
-                }
-            } );
+                    try
+                    {
+                        String jsonValue = assocs.getString( association.qualifiedName().name(), null );
+                        EntityReference value = jsonValue == null
+                                                ? null
+                                                : EntityReference.parseEntityReference( jsonValue );
+                        associations.put( association.qualifiedName(), value );
+                    }
+                    catch( JsonException e )
+                    {
+                        // Association not found, default it to null
+                        associations.put( association.qualifiedName(), null );
+                        status[ 0 ] = EntityStatus.UPDATED;
+                    }
+                } );
 
-            JSONObject manyAssocs = jsonObject.getJSONObject( JSONKeys.MANY_ASSOCIATIONS );
+            JsonObject manyAssocs = state.getJsonObject( JSONKeys.MANY_ASSOCIATIONS );
             Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>();
-            entityDescriptor.state().manyAssociations().forEach( manyAssociationType -> {
-                List<EntityReference> references = new ArrayList<>();
-                try
+            entityDescriptor.state().manyAssociations().forEach(
+                association ->
                 {
-                    JSONArray jsonValues = manyAssocs.getJSONArray( manyAssociationType.qualifiedName().name() );
-                    for( int i = 0; i < jsonValues.length(); i++ )
+                    List<EntityReference> references = new ArrayList<>();
+                    try
                     {
-                        Object jsonValue = jsonValues.getString( i );
-                        EntityReference value = jsonValue == JSONObject.NULL
-                                                ? null
-                                                : EntityReference.parseEntityReference( (String) jsonValue );
-                        references.add( value );
+                        JsonArray jsonValues = manyAssocs.getJsonArray( association.qualifiedName().name() );
+                        for( int i = 0; i < jsonValues.size(); i++ )
+                        {
+                            String jsonValue = jsonValues.getString( i, null );
+                            EntityReference value = jsonValue == null
+                                                    ? null
+                                                    : EntityReference.parseEntityReference( jsonValue );
+                            references.add( value );
+                        }
+                        manyAssociations.put( association.qualifiedName(), references );
                     }
-                    manyAssociations.put( manyAssociationType.qualifiedName(), references );
-                }
-                catch( JSONException e )
-                {
-                    // ManyAssociation not found, default to empty one
-                    manyAssociations.put( manyAssociationType.qualifiedName(), references );
-                }
-            } );
+                    catch( JsonException e )
+                    {
+                        // ManyAssociation not found, default to empty one
+                        manyAssociations.put( association.qualifiedName(), references );
+                    }
+                } );
 
-            JSONObject namedAssocs = jsonObject.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS );
+            JsonObject namedAssocs = state.getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
             Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>();
-            entityDescriptor.state().namedAssociations().forEach( namedAssociationType -> {
-                Map<String, EntityReference> references = new LinkedHashMap<>();
-                try
+            entityDescriptor.state().namedAssociations().forEach(
+                association ->
                 {
-                    JSONObject jsonValues = namedAssocs.getJSONObject( namedAssociationType.qualifiedName().name() );
-                    JSONArray names = jsonValues.names();
-                    if( names != null )
+                    Map<String, EntityReference> references = new LinkedHashMap<>();
+                    try
                     {
-                        for( int idx = 0; idx < names.length(); idx++ )
+                        JsonObject jsonValues = namedAssocs.getJsonObject( association.qualifiedName().name() );
+                        for( String name : jsonValues.keySet() )
                         {
-                            String name = names.getString( idx );
-                            Object value = jsonValues.get( name );
-                            EntityReference ref = value == JSONObject.NULL
+                            String value = jsonValues.getString( name, null );
+                            EntityReference ref = value == null
                                                   ? null
-                                                  : EntityReference.parseEntityReference( (String) value );
+                                                  : EntityReference.parseEntityReference( value );
                             references.put( name, ref );
                         }
+                        namedAssociations.put( association.qualifiedName(), references );
                     }
-                    namedAssociations.put( namedAssociationType.qualifiedName(), references );
-                }
-                catch( JSONException e )
-                {
-                    // NamedAssociation not found, default to empty one
-                    namedAssociations.put( namedAssociationType.qualifiedName(), references );
-                }
-            } );
+                    catch( JsonException e )
+                    {
+                        // NamedAssociation not found, default to empty one
+                        namedAssociations.put( association.qualifiedName(), references );
+                    }
+                } );
 
             return new DefaultEntityState( version,
                                            modified,
-                                           EntityReference.create(identity),
+                                           EntityReference.create( identity ),
                                            status[ 0 ],
                                            entityDescriptor,
                                            properties,
@@ -494,25 +517,26 @@ public class MapEntityStoreMixin
                                            namedAssociations
             );
         }
-        catch( JSONException e )
+        catch( Exception e )
         {
             throw new EntityStoreException( e );
         }
     }
 
     @Override
-    public JSONObject jsonStateOf( String id )
-        throws IOException
+    public JsonObject jsonStateOf( String id )
     {
-        JSONObject jsonObject;
-        try (Reader reader = mapEntityStore.get( EntityReference.parseEntityReference( id ) ))
+        try( Reader reader = mapEntityStore.get( EntityReference.parseEntityReference( id ) ) )
+        {
+            return Json.createReader( reader ).readObject();
+        }
+        catch( EntityStoreException ex )
         {
-            jsonObject = new JSONObject( new JSONTokener( reader ) );
+            throw ex;
         }
-        catch( JSONException e )
+        catch( Exception ex )
         {
-            throw new IOException( e );
+            throw new EntityStoreException( ex );
         }
-        return jsonObject;
     }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/Migration.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/Migration.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/Migration.java
index 4b5e8e6..6a8ebfb 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/Migration.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/Migration.java
@@ -20,14 +20,14 @@
 
 package org.apache.polygene.spi.entitystore.helpers;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonException;
+import javax.json.JsonObject;
 
 /**
  * State Migration SPI.
  */
 public interface Migration
 {
-    boolean migrate( JSONObject state, String toVersion, StateStore stateStore )
-        throws JSONException;
+    JsonObject migrate( JsonObject state, String toVersion, StateStore stateStore )
+        throws JsonException;
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/StateStore.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/StateStore.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/StateStore.java
index 1f1f728..8aa9e6e 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/StateStore.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/StateStore.java
@@ -20,14 +20,13 @@
 
 package org.apache.polygene.spi.entitystore.helpers;
 
-import java.io.IOException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
 
 /**
  * StateStore SPI.
  */
 public interface StateStore
 {
-    JSONObject jsonStateOf( String id )
-        throws IOException;
+    JsonObject jsonStateOf( String id ) throws EntityStoreException;
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/core/spi/src/main/java/org/apache/polygene/spi/module/ModuleSpi.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/module/ModuleSpi.java b/core/spi/src/main/java/org/apache/polygene/spi/module/ModuleSpi.java
index 8aa7c0d..22883f4 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/module/ModuleSpi.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/module/ModuleSpi.java
@@ -21,10 +21,10 @@ package org.apache.polygene.spi.module;
 
 import org.apache.polygene.api.identity.IdentityGenerator;
 import org.apache.polygene.api.metrics.MetricsProvider;
+import org.apache.polygene.api.serialization.Serialization;
 import org.apache.polygene.api.structure.Module;
-import org.apache.polygene.api.structure.TypeLookup;
-import org.apache.polygene.api.value.ValueSerialization;
 import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.types.ValueTypeFactory;
 
 public interface ModuleSpi extends Module
 {
@@ -32,9 +32,9 @@ public interface ModuleSpi extends Module
 
     IdentityGenerator identityGenerator();
 
-    ValueSerialization valueSerialization();
-
-    TypeLookup typeLookup();
+    Serialization serialization();
 
     MetricsProvider metricsProvider();
+
+    ValueTypeFactory valueTypeFactory();
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinaryDeserializer.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinaryDeserializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinaryDeserializer.java
new file mode 100644
index 0000000..a8f2c2c
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinaryDeserializer.java
@@ -0,0 +1,48 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.polygene.spi.serialization;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.UncheckedIOException;
+import java.util.Base64;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueType;
+
+import static java.util.stream.Collectors.joining;
+
+public abstract class AbstractBinaryDeserializer extends AbstractDeserializer
+{
+    @Override
+    public <T> T deserialize( ModuleDescriptor module, ValueType valueType, Reader state )
+    {
+        String stateString;
+        try( BufferedReader buffer = new BufferedReader( state ) )
+        {
+            stateString = buffer.lines().collect( joining( "\n" ) );
+        }
+        catch( IOException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+        byte[] decoded = Base64.getDecoder().decode( stateString );
+        return deserialize( module, valueType, new ByteArrayInputStream( decoded ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinarySerializer.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinarySerializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinarySerializer.java
new file mode 100644
index 0000000..e673ad7
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinarySerializer.java
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.polygene.spi.serialization;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.util.Base64;
+import org.apache.polygene.api.common.Optional;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * Base Binary Serializer.
+ *
+ * Implementations work on bytes, this base serializer encode these bytes in Base64 to produce Strings.
+ */
+public abstract class AbstractBinarySerializer extends AbstractSerializer
+{
+    @Override
+    public void serialize( Options options, Writer writer, @Optional Object object )
+    {
+        try
+        {
+            ByteArrayOutputStream output = new ByteArrayOutputStream();
+            serialize( options, output, object );
+            byte[] base64 = Base64.getEncoder().encode( output.toByteArray() );
+            writer.write( new String( base64, UTF_8 ) );
+        }
+        catch( IOException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+    }
+}


Mime
View raw message