http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreTest.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreTest.java b/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreTest.java index e5ef9f8..e654afc 100644 --- a/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreTest.java +++ b/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreTest.java @@ -23,10 +23,9 @@ import org.apache.polygene.api.common.Visibility; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.entitystore.redis.assembly.RedisEntityStoreAssembler; -import org.apache.polygene.test.internal.DockerRule; import org.apache.polygene.test.EntityTestAssembler; import org.apache.polygene.test.entity.AbstractEntityStoreTest; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationAssembler; +import org.apache.polygene.test.internal.DockerRule; import org.junit.ClassRule; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; @@ -46,7 +45,6 @@ public class RedisMapEntityStoreTest super.assemble( module ); ModuleAssembly config = module.layer().module( "config" ); new EntityTestAssembler().assemble( config ); - new OrgJsonValueSerializationAssembler().assemble( module ); // START SNIPPET: assembly new RedisEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module ); // END SNIPPET: assembly
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreWithCacheTest.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreWithCacheTest.java b/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreWithCacheTest.java index f4499a1..1dba76a 100644 --- a/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreWithCacheTest.java +++ b/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreWithCacheTest.java @@ -23,10 +23,9 @@ import org.apache.polygene.api.common.Visibility; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.entitystore.redis.assembly.RedisEntityStoreAssembler; -import org.apache.polygene.test.internal.DockerRule; import org.apache.polygene.test.EntityTestAssembler; import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationAssembler; +import org.apache.polygene.test.internal.DockerRule; import org.junit.ClassRule; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; @@ -44,7 +43,6 @@ public class RedisMapEntityStoreWithCacheTest super.assemble( module ); ModuleAssembly config = module.layer().module( "config" ); new EntityTestAssembler().assemble( config ); - new OrgJsonValueSerializationAssembler().assemble( module ); new RedisEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module ); RedisEntityStoreConfiguration redisConfig = config.forMixin( RedisEntityStoreConfiguration.class ) .declareDefaults(); http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-riak/build.gradle ---------------------------------------------------------------------- diff --git a/extensions/entitystore-riak/build.gradle b/extensions/entitystore-riak/build.gradle index 37672cd..9599c09 100644 --- a/extensions/entitystore-riak/build.gradle +++ b/extensions/entitystore-riak/build.gradle @@ -33,7 +33,6 @@ dependencies { runtime polygene.core.runtime testCompile polygene.internals.testsupport - testCompile polygene.extension( 'valueserialization-orgjson' ) testRuntime libraries.logback } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreMixin.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreMixin.java b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreMixin.java index df18dae..8d38f5e 100644 --- a/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreMixin.java +++ b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreMixin.java @@ -199,8 +199,7 @@ public class RiakMapEntityStoreMixin implements ServiceActivation, MapEntityStor } @Override - public void passivateService() - throws Exception + public void passivateService() throws Exception { riakClient.shutdown(); riakClient = null; @@ -248,7 +247,7 @@ public class RiakMapEntityStoreMixin implements ServiceActivation, MapEntityStor changes.visitMap( new MapChanger() { @Override - public Writer newEntity( final EntityReference ref, EntityDescriptor entityDescriptor ) + public Writer newEntity( EntityReference ref, EntityDescriptor entityDescriptor ) { return new StringWriter( 1000 ) { @@ -272,7 +271,7 @@ public class RiakMapEntityStoreMixin implements ServiceActivation, MapEntityStor } @Override - public Writer updateEntity( final EntityReference ref, EntityDescriptor entityDescriptor ) + public Writer updateEntity( MapChange mapChange ) { return new StringWriter( 1000 ) { @@ -282,12 +281,13 @@ public class RiakMapEntityStoreMixin implements ServiceActivation, MapEntityStor try { super.close(); - Location location = new Location( namespace, ref.identity().toString() ); + EntityReference reference = mapChange.reference(); + Location location = new Location( namespace, reference.identity().toString() ); FetchValue fetch = new FetchValue.Builder( location ).build(); FetchValue.Response response = riakClient.execute( fetch ); if( response.isNotFound() ) { - throw new EntityNotFoundException( ref ); + throw new EntityNotFoundException( reference ); } StoreValue store = new StoreValue.Builder( toString() ) .withLocation( location ) http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreTest.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreTest.java b/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreTest.java index bf4de29..e36b7cf 100644 --- a/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreTest.java +++ b/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreTest.java @@ -24,13 +24,11 @@ import com.basho.riak.client.core.query.Location; import com.basho.riak.client.core.query.Namespace; import java.util.Collections; import org.apache.polygene.api.common.Visibility; -import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.entitystore.riak.assembly.RiakEntityStoreAssembler; import org.apache.polygene.test.EntityTestAssembler; import org.apache.polygene.test.entity.AbstractEntityStoreTest; import org.apache.polygene.test.internal.DockerRule; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationAssembler; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -53,13 +51,11 @@ public class RiakMapEntityStoreTest @Override // START SNIPPET: assembly public void assemble( ModuleAssembly module ) - throws AssemblyException { // END SNIPPET: assembly super.assemble( module ); ModuleAssembly config = module.layer().module( "config" ); new EntityTestAssembler().assemble( config ); - new OrgJsonValueSerializationAssembler().assemble( module ); // START SNIPPET: assembly new RiakEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module ); // END SNIPPET: assembly http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreWithCacheTest.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreWithCacheTest.java b/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreWithCacheTest.java index 50759f9..9dfc38d 100644 --- a/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreWithCacheTest.java +++ b/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreWithCacheTest.java @@ -32,7 +32,6 @@ import org.apache.polygene.entitystore.riak.assembly.RiakEntityStoreAssembler; import org.apache.polygene.test.EntityTestAssembler; import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest; import org.apache.polygene.test.internal.DockerRule; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationAssembler; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -59,7 +58,6 @@ public class RiakMapEntityStoreWithCacheTest super.assemble( module ); ModuleAssembly config = module.layer().module( "config" ); new EntityTestAssembler().assemble( config ); - new OrgJsonValueSerializationAssembler().assemble( module ); new RiakEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module ); RiakEntityStoreConfiguration riakConfig = config.forMixin( RiakEntityStoreConfiguration.class ) .declareDefaults(); http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/build.gradle ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/build.gradle b/extensions/entitystore-sql/build.gradle index c0c5c8d..3c20986 100644 --- a/extensions/entitystore-sql/build.gradle +++ b/extensions/entitystore-sql/build.gradle @@ -27,6 +27,8 @@ jar { manifest { name = "Apache Polygene⢠Extension - EntityStore - SQL" } } dependencies { compile polygene.core.bootstrap compile polygene.library( 'sql' ) + compile polygene.library( 'sql-liquibase' ) + compile libraries.jooq compile libraries.javaSqlGenerator compile( libraries.javaSqlGeneratorImpl ) { exclude group: 'junit' @@ -36,8 +38,7 @@ dependencies { testCompile polygene.internals.testsupport testCompile polygene.library( 'sql-dbcp' ) - testCompile polygene.extension( 'valueserialization-orgjson' ) - testCompile libraries.derby // Needed at compile time for polite test shutdown + testCompile libraries.derby // Needed at compile time for polite test shutdown // TODO Remove dependency testRuntime libraries.logback testRuntime libraries.h2 http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLEntityStoreMixin.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLEntityStoreMixin.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLEntityStoreMixin.java deleted file mode 100644 index d3e3f3f..0000000 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLEntityStoreMixin.java +++ /dev/null @@ -1,624 +0,0 @@ -/* - * 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.entitystore.sql; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.time.Instant; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import org.apache.polygene.api.common.Optional; -import org.apache.polygene.api.common.QualifiedName; -import org.apache.polygene.api.entity.EntityDescriptor; -import org.apache.polygene.api.entity.EntityReference; -import org.apache.polygene.api.identity.Identity; -import org.apache.polygene.api.identity.IdentityGenerator; -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.ServiceActivation; -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.entitystore.sql.internal.DatabaseSQLService; -import org.apache.polygene.entitystore.sql.internal.DatabaseSQLService.EntityValueResult; -import org.apache.polygene.entitystore.sql.internal.SQLEntityState; -import org.apache.polygene.entitystore.sql.internal.SQLEntityState.DefaultSQLEntityState; -import org.apache.polygene.library.sql.common.SQLUtil; -import org.apache.polygene.spi.PolygeneSPI; -import org.apache.polygene.spi.entity.EntityState; -import org.apache.polygene.spi.entity.EntityStatus; -import org.apache.polygene.spi.entitystore.DefaultEntityStoreUnitOfWork; -import org.apache.polygene.spi.entitystore.EntityNotFoundException; -import org.apache.polygene.spi.entitystore.EntityStore; -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.apache.polygene.spi.entitystore.helpers.DefaultEntityState; -import org.apache.polygene.spi.entitystore.helpers.JSONKeys; -import org.apache.polygene.spi.entitystore.helpers.Migration; -import org.apache.polygene.spi.entitystore.helpers.StateStore; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONTokener; -import org.json.JSONWriter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * SQL EntityStore core Mixin. - */ -// TODO Rewrite reusing JSONMapEntityStoreMixin -// Old notes: -// Most of this code is copy-paste from {@link org.apache.polygene.spi.entitystore.helpers.MapEntityStoreMixin}. -// Refactor stuff that has to do with general things than actual MapEntityStore from MapEntityStoreMixin -// so that this class could extend some "AbstractJSONEntityStoreMixin". -public class SQLEntityStoreMixin - implements EntityStore, EntityStoreSPI, StateStore, ServiceActivation -{ - - private static final Logger LOGGER = LoggerFactory.getLogger( SQLEntityStoreMixin.class ); - - @Service - private DatabaseSQLService database; - - @This - private EntityStoreSPI entityStoreSPI; - - @Structure - private PolygeneSPI spi; - - @Structure - private Application application; - - @Service - @Tagged( ValueSerialization.Formats.JSON ) - private ValueSerialization valueSerialization; - - @Optional - @Service - private Migration migration; - - private String uuid; - - private final AtomicInteger count = new AtomicInteger(); - - @Service - private IdentityGenerator identityGenerator; - - @Override - public void activateService() - throws Exception - { - uuid = UUID.randomUUID().toString() + "-"; - count.set( 0 ); - database.startDatabase(); - } - - @Override - public void passivateService() - throws Exception - { - database.stopDatabase(); - } - - @Override - public StateCommitter applyChanges( final EntityStoreUnitOfWork unitofwork, final Iterable<EntityState> states ) - { - return new StateCommitter() - { - @Override - public void commit() - { - Connection connection = null; - PreparedStatement insertPS = null; - PreparedStatement updatePS = null; - PreparedStatement removePS = null; - try - { - connection = database.getConnection(); - connection.setAutoCommit( false ); - insertPS = database.prepareInsertEntityStatement( connection ); - updatePS = database.prepareUpdateEntityStatement( connection ); - removePS = database.prepareRemoveEntityStatement( connection ); - for( EntityState state : states ) - { - EntityStatus status = state.status(); - DefaultEntityState defState = ( (SQLEntityState) state ).getDefaultEntityState(); - Long entityPK = ( (SQLEntityState) state ).getEntityPK(); - if( EntityStatus.REMOVED.equals( status ) ) - { - database.populateRemoveEntityStatement( removePS, entityPK, state.entityReference() ); - removePS.addBatch(); - } - else - { - StringWriter writer = new StringWriter(); - writeEntityState( defState, writer, unitofwork.identity().toString() ); - writer.flush(); - if( EntityStatus.UPDATED.equals( status ) ) - { - Long entityOptimisticLock = ( (SQLEntityState) state ).getEntityOptimisticLock(); - database.populateUpdateEntityStatement( updatePS, entityPK, entityOptimisticLock, - defState.entityReference(), writer.toString(), - unitofwork.currentTime() ); - updatePS.addBatch(); - } - else if( EntityStatus.NEW.equals( status ) ) - { - database.populateInsertEntityStatement( insertPS, defState.entityReference(), - writer.toString(), unitofwork.currentTime() ); - insertPS.addBatch(); - } - } - } - - removePS.executeBatch(); - insertPS.executeBatch(); - updatePS.executeBatch(); - - connection.commit(); - } - catch( SQLException sqle ) - { - SQLUtil.rollbackQuietly( connection ); - throw new EntityStoreException( "Unable to apply state changes", - SQLUtil.withAllSQLExceptions( sqle ) ); - } - catch( RuntimeException re ) - { - SQLUtil.rollbackQuietly( connection ); - throw new EntityStoreException( re ); - } - finally - { - SQLUtil.closeQuietly( insertPS ); - SQLUtil.closeQuietly( updatePS ); - SQLUtil.closeQuietly( removePS ); - SQLUtil.closeQuietly( connection ); - } - } - - @Override - public void cancel() - { - } - }; - } - - @Override - public EntityState entityStateOf( EntityStoreUnitOfWork unitOfWork, - ModuleDescriptor module, - EntityReference entityRef - ) - { - EntityValueResult valueResult = getValue( entityRef ); - DefaultEntityState state = readEntityState( module, valueResult.getReader() ); - return new DefaultSQLEntityState( state, valueResult.getEntityPK(), valueResult.getEntityOptimisticLock() ); - } - - @Override - public String versionOf( EntityStoreUnitOfWork unitOfWork, EntityReference entityRef ) - { - EntityValueResult valueResult = getValue( entityRef ); - Reader entityState = valueResult.getReader(); - try - { - JSONObject jsonObject = new JSONObject( new JSONTokener( entityState ) ); - final String version = jsonObject.getString( JSONKeys.VERSION ); - return version; - } - catch( JSONException e ) - { - throw new EntityStoreException( e ); - } - } - - @Override - public EntityState newEntityState( EntityStoreUnitOfWork unitOfWork, - EntityReference entityRef, - EntityDescriptor entityDescriptor - ) - { - return new DefaultSQLEntityState( - new DefaultEntityState( unitOfWork.currentTime(), entityRef, entityDescriptor ) ); - } - - @Override - public EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecase, Instant currentTime ) - { - return new DefaultEntityStoreUnitOfWork( module, entityStoreSPI, newUnitOfWorkId(), usecase, currentTime ); - } - - @Override - public Stream<EntityState> entityStates( final ModuleDescriptor module ) - { - try - { - Connection connection = database.getConnection(); - PreparedStatement ps = database.prepareGetAllEntitiesStatement( connection ); - database.populateGetAllEntitiesStatement( ps ); - ResultSet rs = ps.executeQuery(); - return StreamSupport.stream( - new Spliterators.AbstractSpliterator<EntityState>( Long.MAX_VALUE, Spliterator.ORDERED ) - { - @Override - public boolean tryAdvance( final Consumer<? super EntityState> action ) - { - try - { - if( !rs.next() ) { return false; } - EntityState entityState = readEntityState( module, - database.getEntityValue( rs ).getReader() ); - action.accept( entityState ); - return true; - } - catch( SQLException ex ) - { - SQLUtil.closeQuietly( rs, ex ); - SQLUtil.closeQuietly( ps, ex ); - SQLUtil.closeQuietly( connection, ex ); - throw new EntityStoreException( "Unable to get next entity state", - SQLUtil.withAllSQLExceptions( ex ) ); - } - } - }, - false - ).onClose( - () -> - { - SQLUtil.closeQuietly( rs ); - SQLUtil.closeQuietly( ps ); - SQLUtil.closeQuietly( connection ); - } - ); - } - catch( SQLException ex ) - { - throw new EntityStoreException( "Unable to get entity states", SQLUtil.withAllSQLExceptions( ex ) ); - } - } - - protected Identity newUnitOfWorkId() - { - return identityGenerator.generate( EntityStore.class ); - } - - protected DefaultEntityState readEntityState( ModuleDescriptor module, Reader entityState ) - throws EntityStoreException - { - try - { - JSONObject jsonObject = new JSONObject( new JSONTokener( entityState ) ); - final EntityStatus[] status = { EntityStatus.LOADED }; - - String version = jsonObject.getString( JSONKeys.VERSION ); - Instant modified = Instant.ofEpochMilli( jsonObject.getLong( JSONKeys.MODIFIED ) ); - String identity = jsonObject.getString( JSONKeys.IDENTITY ); - - // Check if version is correct - String currentAppVersion = jsonObject.optString( JSONKeys.APPLICATION_VERSION, "0.0" ); - if( !currentAppVersion.equals( application.version() ) ) - { - if( migration != null ) - { - migration.migrate( jsonObject, application.version(), this ); - } - else - { - // Do nothing - set version to be correct - jsonObject.put( JSONKeys.APPLICATION_VERSION, application.version() ); - } - - LOGGER.trace( "Updated version nr on {} from {} to {}", - identity, currentAppVersion, application.version() ); - - // State changed - status[ 0 ] = EntityStatus.UPDATED; - } - - String type = jsonObject.getString( JSONKeys.TYPE ); - - EntityDescriptor entityDescriptor = module.entityDescriptor( type ); - if( entityDescriptor == null ) - { - throw new NoSuchEntityTypeException( type, module.name(), module.typeLookup() ); - } - - Map<QualifiedName, Object> properties = new HashMap<>(); - JSONObject props = jsonObject.getJSONObject( JSONKeys.PROPERTIES ); - entityDescriptor.state().properties().forEach( - propertyDescriptor -> - { - Object jsonValue; - try - { - jsonValue = props.get( - propertyDescriptor.qualifiedName().name() ); - if( JSONObject.NULL.equals( jsonValue ) ) - { - properties.put( propertyDescriptor.qualifiedName(), null ); - } - else - { - Object value = valueSerialization.deserialize( module, - propertyDescriptor.valueType(), - jsonValue.toString() ); - properties.put( propertyDescriptor.qualifiedName(), value ); - } - } - 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 - { - 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; - } - } - ); - - JSONObject manyAssocs = jsonObject.getJSONObject( JSONKeys.MANY_ASSOCIATIONS ); - Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>(); - entityDescriptor.state().manyAssociations().forEach( - manyAssociationType -> - { - List<EntityReference> references = new ArrayList<>(); - try - { - JSONArray jsonValues = manyAssocs.getJSONArray( manyAssociationType.qualifiedName().name() ); - for( int i = 0; i < jsonValues.length(); i++ ) - { - Object jsonValue = jsonValues.getString( i ); - EntityReference value = jsonValue == JSONObject.NULL - ? null - : EntityReference.parseEntityReference( (String) jsonValue ); - references.add( value ); - } - manyAssociations.put( manyAssociationType.qualifiedName(), references ); - } - catch( JSONException e ) - { - // ManyAssociation not found, default to empty one - manyAssociations.put( manyAssociationType.qualifiedName(), references ); - } - } ); - - JSONObject namedAssocs = jsonObject.has( JSONKeys.NAMED_ASSOCIATIONS ) - ? jsonObject.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS ) - : new JSONObject(); - Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>(); - entityDescriptor.state().namedAssociations().forEach( - namedAssociationType -> - { - Map<String, EntityReference> references = new LinkedHashMap<>(); - try - { - JSONObject jsonValues = namedAssocs.getJSONObject( namedAssociationType.qualifiedName().name() ); - JSONArray names = jsonValues.names(); - if( names != null ) - { - for( int idx = 0; idx < names.length(); idx++ ) - { - String name = names.getString( idx ); - String jsonValue = jsonValues.getString( name ); - references.put( name, EntityReference.parseEntityReference( jsonValue ) ); - } - } - namedAssociations.put( namedAssociationType.qualifiedName(), references ); - } - catch( JSONException e ) - { - // NamedAssociation not found, default to empty one - namedAssociations.put( namedAssociationType.qualifiedName(), references ); - } - } ); - - return new DefaultEntityState( version, modified, - EntityReference.parseEntityReference( identity ), status[ 0 ], - entityDescriptor, - properties, associations, manyAssociations, namedAssociations ); - } - catch( JSONException e ) - { - throw new EntityStoreException( e ); - } - } - - @Override - public JSONObject jsonStateOf( String id ) - throws IOException - { - JSONObject jsonObject; - try( Reader reader = getValue( EntityReference.parseEntityReference( id ) ).getReader() ) - { - jsonObject = new JSONObject( new JSONTokener( reader ) ); - } - catch( JSONException e ) - { - throw new IOException( e ); - } - return jsonObject; - } - - protected EntityValueResult getValue( EntityReference ref ) - { - Connection connection = null; - PreparedStatement ps = null; - ResultSet rs = null; - try - { - connection = database.getConnection(); - ps = database.prepareGetEntityStatement( connection ); - database.populateGetEntityStatement( ps, ref ); - rs = ps.executeQuery(); - if( !rs.next() ) - { - throw new EntityNotFoundException( ref ); - } - return database.getEntityValue( rs ); - } - catch( SQLException sqle ) - { - throw new EntityStoreException( "Unable to get Entity " + ref, SQLUtil.withAllSQLExceptions( sqle ) ); - } - finally - { - SQLUtil.closeQuietly( rs ); - SQLUtil.closeQuietly( ps ); - SQLUtil.closeQuietly( connection ); - } - } - - protected void writeEntityState( DefaultEntityState state, Writer writer, String version ) - throws EntityStoreException - { - try - { - JSONWriter json = new JSONWriter( writer ); - JSONWriter properties = json.object() - .key( JSONKeys.IDENTITY ) - .value( state.entityReference().identity().toString() ) - .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( state.lastModified().toEpochMilli() ) - .key( JSONKeys.PROPERTIES ) - .object(); - - state.entityDescriptor().state().properties().forEach( - persistentProperty -> - { - try - { - Object value = state.properties().get( persistentProperty.qualifiedName() ); - 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 ) - { - throw new EntityStoreException( - "Could not store EntityState", e ); - } - } ); - - JSONWriter associations = properties.endObject().key( JSONKeys.ASSOCIATIONS ).object(); - for( Map.Entry<QualifiedName, EntityReference> stateNameEntityRefEntry : state.associations().entrySet() ) - { - EntityReference value = stateNameEntityRefEntry.getValue(); - associations.key( stateNameEntityRefEntry.getKey().name() ) - .value( value != null ? value.identity().toString() : null ); - } - - JSONWriter manyAssociations = associations.endObject().key( JSONKeys.MANY_ASSOCIATIONS ).object(); - for( Map.Entry<QualifiedName, List<EntityReference>> stateNameListEntry : state.manyAssociations().entrySet() ) - { - JSONWriter assocs = manyAssociations.key( stateNameListEntry.getKey().name() ).array(); - for( EntityReference entityReference : stateNameListEntry.getValue() ) - { - assocs.value( entityReference.identity().toString() ); - } - assocs.endArray(); - } - - JSONWriter namedAssociations = manyAssociations.endObject().key( JSONKeys.NAMED_ASSOCIATIONS ).object(); - for( Map.Entry<QualifiedName, Map<String, EntityReference>> stateNameMapEntry : state.namedAssociations().entrySet() ) - { - JSONWriter assocs = namedAssociations.key( stateNameMapEntry.getKey().name() ).object(); - for( Map.Entry<String, EntityReference> entry : stateNameMapEntry.getValue().entrySet() ) - { - assocs.key( entry.getKey() ).value( entry.getValue().identity().toString() ); - } - assocs.endObject(); - } - namedAssociations.endObject().endObject(); - } - catch( JSONException e ) - { - throw new EntityStoreException( "Could not store EntityState", e ); - } - } -} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLEntityStoreService.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLEntityStoreService.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLEntityStoreService.java deleted file mode 100644 index fe8c4aa..0000000 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLEntityStoreService.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.entitystore.sql; - -import org.apache.polygene.api.concern.Concerns; -import org.apache.polygene.api.mixin.Mixins; -import org.apache.polygene.api.service.ServiceActivation; -import org.apache.polygene.api.service.ServiceComposite; -import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern; -import org.apache.polygene.spi.entitystore.EntityStateVersions; -import org.apache.polygene.spi.entitystore.EntityStore; -import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern; - -/** - * SQL EntityStore service. - */ -@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } ) -@Mixins( { SQLEntityStoreMixin.class } ) -public interface SQLEntityStoreService - extends EntityStore, EntityStateVersions, ServiceComposite, ServiceActivation -{ -} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMapping.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMapping.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMapping.java new file mode 100644 index 0000000..67f6066 --- /dev/null +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMapping.java @@ -0,0 +1,69 @@ +/* + * 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.entitystore.sql; + +import org.jooq.DataType; +import org.jooq.impl.SQLDataType; + +/** + * Mapping for the entities table. + * + * If you change this once the table is created you'll have to ALTER it yourself. + */ +public interface SQLMapEntityStoreMapping +{ + default String defaultSchemaName() + { + return "POLYGENE_ES"; + } + + default String tableName() + { + return "POLYGENE_ENTITIES"; + } + + default String identityColumnName() + { + return "ENTITY_IDENTITY"; + } + + default String versionColumnName() + { + return "ENTITY_VERSION"; + } + + default String stateColumnName() + { + return "ENTITY_STATE"; + } + + default DataType<String> identityDataType() + { + return SQLDataType.VARCHAR( 64 ); + } + + default DataType<String> versionDataType() + { + return SQLDataType.VARCHAR( 64 ); + } + + default DataType<String> stateDataType() + { + return SQLDataType.VARCHAR( 10 * 1024 ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java new file mode 100644 index 0000000..5298e0f --- /dev/null +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java @@ -0,0 +1,237 @@ +/* + * 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.entitystore.sql; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; +import javax.json.Json; +import javax.sql.DataSource; +import org.apache.polygene.api.common.Optional; +import org.apache.polygene.api.configuration.Configuration; +import org.apache.polygene.api.entity.EntityDescriptor; +import org.apache.polygene.api.entity.EntityReference; +import org.apache.polygene.api.injection.scope.Service; +import org.apache.polygene.api.injection.scope.This; +import org.apache.polygene.api.injection.scope.Uses; +import org.apache.polygene.api.service.ServiceActivation; +import org.apache.polygene.api.service.ServiceDescriptor; +import org.apache.polygene.api.util.NullArgumentException; +import org.apache.polygene.library.sql.common.SQLConfiguration; +import org.apache.polygene.spi.entitystore.EntityNotFoundException; +import org.apache.polygene.spi.entitystore.EntityStoreException; +import org.apache.polygene.spi.entitystore.helpers.JSONKeys; +import org.apache.polygene.spi.entitystore.helpers.MapEntityStore; +import org.jooq.DSLContext; +import org.jooq.Field; +import org.jooq.Query; +import org.jooq.Record; +import org.jooq.SQLDialect; +import org.jooq.Schema; +import org.jooq.Table; +import org.jooq.conf.Settings; +import org.jooq.impl.DSL; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +// TODO Implement optimistic locking! Maybe as a SPI helper +public class SQLMapEntityStoreMixin + implements ServiceActivation, MapEntityStore +{ + private static final Logger LOGGER = LoggerFactory.getLogger( SQLMapEntityStoreService.class ); + + @Service + private DataSource dataSource; + + @Uses + private ServiceDescriptor descriptor; + + @This + @Optional + private Configuration<SQLConfiguration> configuration; + + private Schema schema; + private Table<Record> table; + private Field<String> identityColumn; + private Field<String> versionColumn; + private Field<String> stateColumn; + private DSLContext dsl; + + @Override + public void activateService() throws Exception + { + SQLDialect dialect = descriptor.metaInfo( SQLDialect.class ); + Settings settings = descriptor.metaInfo( Settings.class ); + SQLMapEntityStoreMapping mapping = descriptor.metaInfo( SQLMapEntityStoreMapping.class ); + String schemaName = getConfiguredSchemaName( mapping.defaultSchemaName() ); + if( schemaName == null ) + { + throw new EntityStoreException( "Schema name must not be null." ); + } + schema = DSL.schema( DSL.name( schemaName.toUpperCase() ) ); + table = DSL.table( + dialect.equals( SQLDialect.SQLITE ) + ? DSL.name( mapping.tableName() ) + : DSL.name( schema.getName(), mapping.tableName() ) + ); + identityColumn = DSL.field( mapping.identityColumnName(), String.class ); + versionColumn = DSL.field( mapping.versionColumnName(), String.class ); + stateColumn = DSL.field( mapping.stateColumnName(), String.class ); + + dsl = DSL.using( dataSource, dialect, settings ); + + if( !dialect.equals( SQLDialect.SQLITE ) + && dsl.meta().getSchemas().stream().noneMatch( s -> schema.getName().equals( s.getName() ) ) ) + { + dsl.createSchema( schema ).execute(); + } + + if( dsl.meta().getTables().stream().noneMatch( t -> table.getName().equals( t.getName() ) ) ) + { + dsl.createTable( table ) + .column( identityColumn, mapping.identityDataType().nullable( false ) ) + .column( versionColumn, mapping.versionDataType().nullable( false ) ) + .column( stateColumn, mapping.stateDataType().nullable( false ) ) + .constraint( DSL.constraint( "ENTITY_IDENTITY_CONSTRAINT" ).primaryKey( identityColumn ) ) + .execute(); + } + } + + @Override + public void passivateService() throws Exception + { + dsl = null; + schema = null; + table = null; + identityColumn = null; + versionColumn = null; + stateColumn = null; + } + + @Override + public Reader get( EntityReference entityReference ) + { + String state = dsl.select( stateColumn ) + .from( table ) + .where( identityColumn.equal( entityReference.identity().toString() ) ) + .fetchOptional( stateColumn ) + .orElseThrow( () -> new EntityNotFoundException( entityReference ) ); + return new StringReader( state ); + } + + @Override + public Stream<Reader> entityStates() + { + return dsl.select( stateColumn ) + .from( table ) + .fetch( stateColumn ) + .stream() + .map( StringReader::new ); + } + + @Override + public void applyChanges( MapChanges changes ) throws Exception + { + List<Query> operations = new ArrayList<>(); + changes.visitMap( new MapChanger() + { + @Override + public Writer newEntity( EntityReference ref, EntityDescriptor entityDescriptor ) + { + return new StringWriter( 1000 ) + { + @Override + public void close() throws IOException + { + super.close(); + String state = toString(); + String version = Json.createReader( new StringReader( state ) ).readObject() + .getString( JSONKeys.VERSION ); + operations.add( + dsl.insertInto( table ) + .columns( identityColumn, versionColumn, stateColumn ) + .values( ref.identity().toString(), version, state ) + ); + } + }; + } + + @Override + public Writer updateEntity( MapChange mapChange ) + { + return new StringWriter( 1000 ) + { + @Override + public void close() throws IOException + { + super.close(); + String state = toString(); + operations.add( + dsl.update( table ) + .set( versionColumn, mapChange.newVersion() ) + .set( stateColumn, state ) + .where( identityColumn.equal( mapChange.reference().identity().toString() ) ) + .and( versionColumn.equal( mapChange.previousVersion() ) ) + ); + } + }; + } + + @Override + public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor ) + { + operations.add( + dsl.deleteFrom( table ) + .where( identityColumn.equal( ref.identity().toString() ) ) + ); + } + } ); + dsl.batch( operations ).execute(); + } + + + /** + * Configuration is optional at both assembly and runtime. + */ + protected String getConfiguredSchemaName( String defaultSchemaName ) + { + if( configuration == null ) + { + NullArgumentException.validateNotNull( "default schema name", defaultSchemaName ); + LOGGER.debug( "No configuration, will use default schema name: '{}'", defaultSchemaName ); + return defaultSchemaName; + } + String result = configuration.get().schemaName().get(); + if( result == null ) + { + NullArgumentException.validateNotNull( "default schema name", defaultSchemaName ); + result = defaultSchemaName; + LOGGER.debug( "No database schema name in configuration, will use default: '{}'", defaultSchemaName ); + } + else + { + LOGGER.debug( "Will use configured database schema name: '{}'", result ); + } + return result; + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java new file mode 100644 index 0000000..0ff1e59 --- /dev/null +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java @@ -0,0 +1,45 @@ +/* + * 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.entitystore.sql; + +import org.apache.polygene.api.concern.Concerns; +import org.apache.polygene.api.configuration.Configuration; +import org.apache.polygene.api.mixin.Mixins; +import org.apache.polygene.api.service.ServiceActivation; +import org.apache.polygene.api.service.ServiceComposite; +import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern; +import org.apache.polygene.spi.entitystore.EntityStateVersions; +import org.apache.polygene.spi.entitystore.EntityStore; +import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern; +import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation; +import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin; + +/** + * SQL EntityStore service. + */ +@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } ) +@Mixins( { JSONMapEntityStoreMixin.class, SQLMapEntityStoreMixin.class } ) +public interface SQLMapEntityStoreService + extends ServiceActivation, + JSONMapEntityStoreActivation, + EntityStore, + EntityStateVersions, + ServiceComposite, + Configuration +{ +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/AbstractSQLEntityStoreAssembler.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/AbstractSQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/AbstractSQLEntityStoreAssembler.java deleted file mode 100644 index 1713300..0000000 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/AbstractSQLEntityStoreAssembler.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.entitystore.sql.assembly; - -import java.io.IOException; -import org.apache.polygene.api.common.Visibility; -import org.apache.polygene.api.identity.Identity; -import org.apache.polygene.api.identity.StringIdentity; -import org.apache.polygene.bootstrap.Assemblers; -import org.apache.polygene.bootstrap.AssemblyException; -import org.apache.polygene.bootstrap.ModuleAssembly; -import org.apache.polygene.entitystore.sql.SQLEntityStoreService; -import org.apache.polygene.entitystore.sql.internal.DatabaseSQLService.DatabaseSQLServiceComposite; -import org.apache.polygene.entitystore.sql.internal.DatabaseSQLServiceCoreMixin; -import org.apache.polygene.entitystore.sql.internal.DatabaseSQLServiceSpi; -import org.apache.polygene.entitystore.sql.internal.DatabaseSQLServiceStatementsMixin; -import org.apache.polygene.entitystore.sql.internal.DatabaseSQLStringsBuilder; -import org.apache.polygene.library.sql.common.SQLConfiguration; -import org.sql.generation.api.vendor.SQLVendor; -import org.sql.generation.api.vendor.SQLVendorProvider; - -/** - * Base SQL EntityStore assembly. - */ -@SuppressWarnings( "unchecked" ) -abstract class AbstractSQLEntityStoreAssembler<AssemblerType> - extends Assemblers.VisibilityIdentityConfig<AssemblerType> -{ - - public static final Identity DEFAULT_ENTITYSTORE_IDENTITY = new StringIdentity( "entitystore-sql" ); - - protected SQLVendor getSQLVendor() - throws IOException - { - return SQLVendorProvider.createVendor( SQLVendor.class ); - } - - protected Class<?> getDatabaseStringBuilderMixin() - { - return DatabaseSQLStringsBuilder.CommonMixin.class; - } - - protected abstract Class<?> getDatabaseSQLServiceSpecializationMixin(); - - @Override - public final void assemble( ModuleAssembly module ) - throws AssemblyException - { - try - { - SQLVendor sqlVendor = this.getSQLVendor(); - if( sqlVendor == null ) - { - throw new AssemblyException( "SQL Vendor could not be determined." ); - } - module.services( DatabaseSQLServiceComposite.class ) - .withMixins( DatabaseSQLServiceCoreMixin.class, - DatabaseSQLServiceSpi.CommonMixin.class, - getDatabaseStringBuilderMixin(), - DatabaseSQLServiceStatementsMixin.class, - getDatabaseSQLServiceSpecializationMixin() ) - .identifiedBy( ( hasIdentity() ? identity().toString() : DEFAULT_ENTITYSTORE_IDENTITY ).toString() ). - visibleIn( Visibility.module ). - setMetaInfo( sqlVendor ); - } - catch( IOException ioe ) - { - throw new AssemblyException( ioe ); - } - module.services( SQLEntityStoreService.class ).visibleIn( visibility() ); - if( hasConfig() ) - { - configModule().entities( SQLConfiguration.class ).visibleIn( configVisibility() ); - } - } -} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/AbstractSQLMapEntityStoreAssembler.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/AbstractSQLMapEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/AbstractSQLMapEntityStoreAssembler.java new file mode 100644 index 0000000..4e205d1 --- /dev/null +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/AbstractSQLMapEntityStoreAssembler.java @@ -0,0 +1,85 @@ +/* + * 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.entitystore.sql.assembly; + +import org.apache.polygene.api.identity.Identity; +import org.apache.polygene.api.identity.StringIdentity; +import org.apache.polygene.bootstrap.Assemblers; +import org.apache.polygene.bootstrap.AssemblyException; +import org.apache.polygene.bootstrap.ModuleAssembly; +import org.apache.polygene.entitystore.sql.SQLMapEntityStoreMapping; +import org.apache.polygene.entitystore.sql.SQLMapEntityStoreService; +import org.apache.polygene.library.sql.common.SQLConfiguration; +import org.jooq.SQLDialect; +import org.jooq.conf.Settings; + +/** + * Base SQL EntityStore assembly. + */ +public abstract class AbstractSQLMapEntityStoreAssembler<AssemblerType> + extends Assemblers.VisibilityIdentityConfig<AssemblerType> +{ + public static final Identity DEFAULT_ENTITYSTORE_IDENTITY = new StringIdentity( "entitystore-sql" ); + + @Override + public void assemble( ModuleAssembly module ) + { + SQLDialect dialect = getSQLDialect(); + if( dialect == null ) + { + throw new AssemblyException( "SQLDialect must not be null" ); + } + Settings settings = getSettings(); + if( settings == null ) + { + throw new AssemblyException( "Settings must not be null" ); + } + SQLMapEntityStoreMapping mapping = getMapping(); + if( settings == null ) + { + throw new AssemblyException( "SQLMapEntityStoreSchema must not be null" ); + } + + module.services( SQLMapEntityStoreService.class ) + .identifiedBy( ( hasIdentity() ? identity() : DEFAULT_ENTITYSTORE_IDENTITY ).toString() ) + .visibleIn( visibility() ) + .setMetaInfo( dialect ) + .setMetaInfo( settings ) + .setMetaInfo( mapping ); + + if( hasConfig() ) + { + configModule().entities( SQLConfiguration.class ).visibleIn( configVisibility() ); + } + } + + protected Settings getSettings() + { + return new Settings(); + } + + protected SQLDialect getSQLDialect() + { + return SQLDialect.DEFAULT; + } + + protected SQLMapEntityStoreMapping getMapping() + { + return new SQLMapEntityStoreMapping() {}; + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/DerbySQLEntityStoreAssembler.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/DerbySQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/DerbySQLEntityStoreAssembler.java index dc91d76..6288d85 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/DerbySQLEntityStoreAssembler.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/DerbySQLEntityStoreAssembler.java @@ -19,30 +19,17 @@ */ package org.apache.polygene.entitystore.sql.assembly; -import java.io.IOException; -import org.apache.polygene.entitystore.sql.internal.DerbySQLDatabaseSQLServiceMixin; -import org.sql.generation.api.vendor.DerbyVendor; -import org.sql.generation.api.vendor.SQLVendor; -import org.sql.generation.api.vendor.SQLVendorProvider; +import org.jooq.SQLDialect; /** * Derby EntityStore assembly. */ public class DerbySQLEntityStoreAssembler - extends AbstractSQLEntityStoreAssembler<DerbySQLEntityStoreAssembler> + extends AbstractSQLMapEntityStoreAssembler<DerbySQLEntityStoreAssembler> { - - @Override - protected Class<?> getDatabaseSQLServiceSpecializationMixin() - { - return DerbySQLDatabaseSQLServiceMixin.class; - } - @Override - protected SQLVendor getSQLVendor() - throws IOException + protected SQLDialect getSQLDialect() { - return SQLVendorProvider.createVendor( DerbyVendor.class ); + return SQLDialect.DERBY; } - } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/H2SQLEntityStoreAssembler.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/H2SQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/H2SQLEntityStoreAssembler.java index e596fba..018251e 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/H2SQLEntityStoreAssembler.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/H2SQLEntityStoreAssembler.java @@ -19,30 +19,17 @@ */ package org.apache.polygene.entitystore.sql.assembly; -import java.io.IOException; -import org.apache.polygene.entitystore.sql.internal.H2SQLDatabaseSQLServiceMixin; -import org.sql.generation.api.vendor.H2Vendor; -import org.sql.generation.api.vendor.SQLVendor; -import org.sql.generation.api.vendor.SQLVendorProvider; +import org.jooq.SQLDialect; /** * H2 EntityStore assembly. */ public class H2SQLEntityStoreAssembler - extends AbstractSQLEntityStoreAssembler<H2SQLEntityStoreAssembler> + extends AbstractSQLMapEntityStoreAssembler<H2SQLEntityStoreAssembler> { - - @Override - protected Class<?> getDatabaseSQLServiceSpecializationMixin() - { - return H2SQLDatabaseSQLServiceMixin.class; - } - @Override - protected SQLVendor getSQLVendor() - throws IOException + protected SQLDialect getSQLDialect() { - return SQLVendorProvider.createVendor( H2Vendor.class ); + return SQLDialect.H2; } - } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/MySQLEntityStoreAssembler.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/MySQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/MySQLEntityStoreAssembler.java index e3ea6d1..ff46c82 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/MySQLEntityStoreAssembler.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/MySQLEntityStoreAssembler.java @@ -19,30 +19,17 @@ */ package org.apache.polygene.entitystore.sql.assembly; -import java.io.IOException; -import org.apache.polygene.entitystore.sql.internal.MySQLDatabaseSQLServiceMixin; -import org.sql.generation.api.vendor.MySQLVendor; -import org.sql.generation.api.vendor.SQLVendor; -import org.sql.generation.api.vendor.SQLVendorProvider; +import org.jooq.SQLDialect; /** * MySQL EntityStore assembly. */ public class MySQLEntityStoreAssembler - extends AbstractSQLEntityStoreAssembler<MySQLEntityStoreAssembler> + extends AbstractSQLMapEntityStoreAssembler<MySQLEntityStoreAssembler> { - - @Override - protected Class<?> getDatabaseSQLServiceSpecializationMixin() - { - return MySQLDatabaseSQLServiceMixin.class; - } - @Override - protected SQLVendor getSQLVendor() - throws IOException + protected SQLDialect getSQLDialect() { - return SQLVendorProvider.createVendor( MySQLVendor.class ); + return SQLDialect.MYSQL; } - } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/PostgreSQLEntityStoreAssembler.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/PostgreSQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/PostgreSQLEntityStoreAssembler.java index a7f0a23..4400b8e 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/PostgreSQLEntityStoreAssembler.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/PostgreSQLEntityStoreAssembler.java @@ -19,37 +19,17 @@ */ package org.apache.polygene.entitystore.sql.assembly; -import java.io.IOException; -import org.apache.polygene.entitystore.sql.internal.PostgreSQLDatabaseSQLServiceMixin; -import org.apache.polygene.entitystore.sql.internal.PostgreSQLStringBuilderMixin; -import org.sql.generation.api.vendor.PostgreSQLVendor; -import org.sql.generation.api.vendor.SQLVendor; -import org.sql.generation.api.vendor.SQLVendorProvider; +import org.jooq.SQLDialect; /** * PostgreSQL EntityStore assembly. */ public class PostgreSQLEntityStoreAssembler - extends AbstractSQLEntityStoreAssembler<PostgreSQLEntityStoreAssembler> + extends AbstractSQLMapEntityStoreAssembler<PostgreSQLEntityStoreAssembler> { - - @Override - protected Class<?> getDatabaseSQLServiceSpecializationMixin() - { - return PostgreSQLDatabaseSQLServiceMixin.class; - } - @Override - protected Class<?> getDatabaseStringBuilderMixin() + protected SQLDialect getSQLDialect() { - return PostgreSQLStringBuilderMixin.class; + return SQLDialect.POSTGRES; } - - @Override - protected SQLVendor getSQLVendor() - throws IOException - { - return SQLVendorProvider.createVendor( PostgreSQLVendor.class ); - } - } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/SQLiteEntityStoreAssembler.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/SQLiteEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/SQLiteEntityStoreAssembler.java index 7c043e7..1b7fa5e 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/SQLiteEntityStoreAssembler.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/SQLiteEntityStoreAssembler.java @@ -19,30 +19,17 @@ */ package org.apache.polygene.entitystore.sql.assembly; -import java.io.IOException; -import org.apache.polygene.entitystore.sql.internal.SQLiteDatabaseSQLServiceMixin; -import org.sql.generation.api.vendor.SQLVendor; -import org.sql.generation.api.vendor.SQLVendorProvider; -import org.sql.generation.api.vendor.SQLiteVendor; +import org.jooq.SQLDialect; /** * SQLite EntityStore assembly. */ public class SQLiteEntityStoreAssembler - extends AbstractSQLEntityStoreAssembler<SQLiteEntityStoreAssembler> + extends AbstractSQLMapEntityStoreAssembler<SQLiteEntityStoreAssembler> { - - @Override - protected Class<?> getDatabaseSQLServiceSpecializationMixin() - { - return SQLiteDatabaseSQLServiceMixin.class; - } - @Override - protected SQLVendor getSQLVendor() - throws IOException + protected SQLDialect getSQLDialect() { - return SQLVendorProvider.createVendor( SQLiteVendor.class ); + return SQLDialect.SQLITE; } - } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLService.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLService.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLService.java index 03ce525..fddb19f 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLService.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLService.java @@ -24,59 +24,32 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.time.Instant; import org.apache.polygene.api.entity.EntityReference; import org.apache.polygene.api.service.ServiceComposite; @SuppressWarnings( "PublicInnerClass" ) public interface DatabaseSQLService { - - public interface DatabaseSQLServiceComposite - extends DatabaseSQLService, ServiceComposite + interface DatabaseSQLServiceComposite extends DatabaseSQLService, ServiceComposite { } - public final class EntityValueResult + final class EntityValueResult { - - private final Long entityPK; - - private final Long entityOptimisticLock; - private final Reader reader; - public EntityValueResult( Long entityPK, Long entityOptimisticLock, Reader reader ) + EntityValueResult( Reader reader ) { - this.entityPK = entityPK; - this.entityOptimisticLock = entityOptimisticLock; this.reader = reader; } /** - * @return the entityPK - */ - public Long getEntityPK() - { - return entityPK; - } - - /** - * @return the entityOptimisticLock - */ - public Long getEntityOptimisticLock() - { - return entityOptimisticLock; - } - - /** * @return the reader */ public Reader getReader() { return reader; } - } void startDatabase() @@ -109,16 +82,15 @@ public interface DatabaseSQLService void populateGetAllEntitiesStatement( PreparedStatement ps ) throws SQLException; - void populateInsertEntityStatement( PreparedStatement ps, EntityReference ref, String entity, Instant lastModified ) + void populateInsertEntityStatement( PreparedStatement ps, EntityReference ref, String entity ) throws SQLException; - void populateUpdateEntityStatement( PreparedStatement ps, Long entityPK, Long entityOptimisticLock, EntityReference ref, String entity, Instant lastModified ) + void populateUpdateEntityStatement( PreparedStatement ps, EntityReference ref, String entity ) throws SQLException; - void populateRemoveEntityStatement( PreparedStatement ps, Long entityPK, EntityReference ref ) + void populateRemoveEntityStatement( PreparedStatement ps, EntityReference ref ) throws SQLException; - EntityValueResult getEntityValue( ResultSet rs ) + Reader getEntityStateReader( ResultSet rs ) throws SQLException; - } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLServiceState.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLServiceState.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLServiceState.java index 31c4751..3e3926d 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLServiceState.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLServiceState.java @@ -25,11 +25,9 @@ import org.sql.generation.api.vendor.SQLVendor; public interface DatabaseSQLServiceState { - @Optional - public Property<String> schemaName(); + Property<String> schemaName(); @Optional - public Property<SQLVendor> vendor(); - + Property<SQLVendor> vendor(); } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLServiceStatementsMixin.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLServiceStatementsMixin.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLServiceStatementsMixin.java index 8406e05..cce4568 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLServiceStatementsMixin.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/internal/DatabaseSQLServiceStatementsMixin.java @@ -22,7 +22,6 @@ package org.apache.polygene.entitystore.sql.internal; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.time.Instant; import org.apache.polygene.api.entity.EntityReference; import org.apache.polygene.api.injection.scope.This; @@ -89,30 +88,26 @@ public abstract class DatabaseSQLServiceStatementsMixin } @Override - public void populateInsertEntityStatement( PreparedStatement ps, EntityReference ref, String entity, Instant lastModified ) + public void populateInsertEntityStatement( PreparedStatement ps, EntityReference ref, String entity ) throws SQLException { ps.setString( 1, ref.identity().toString() ); ps.setString( 2, entity ); - ps.setLong( 3, lastModified.toEpochMilli() ); } @Override - public void populateRemoveEntityStatement( PreparedStatement ps, Long entityPK, EntityReference ref ) + public void populateRemoveEntityStatement( PreparedStatement ps, EntityReference ref ) throws SQLException { - ps.setLong( 1, entityPK ); + ps.setString( 1, ref.identity().toString() ); } @Override - public void populateUpdateEntityStatement( PreparedStatement ps, Long entityPK, Long entityOptimisticLock, EntityReference ref, String entity, Instant lastModified ) + public void populateUpdateEntityStatement( PreparedStatement ps, EntityReference ref, String entity ) throws SQLException { - ps.setLong( 1, entityOptimisticLock + 1 ); + ps.setString( 1, ref.identity().toString() ); ps.setString( 2, entity ); - ps.setLong( 3, lastModified.toEpochMilli() ); - ps.setLong( 4, entityPK ); - ps.setLong( 5, entityOptimisticLock ); } }
