New (de)serialization API and SPI & new implementations POLYGENE-191 POLYGENE-153 POLYGENE-137 POLYGENE-102 POLYGENE-157 POLYGENE-53
Breaking changes in org.apache.polygene.: - api.type - api.value - spi.entitystore.helpers New API/SPI in org.apache.polygene: - api.serialization - api.type - spi.serialization - spi.type - Replace org.json with javax.json - JSON serialization SPI & Extension using javax.json types - XML serialization SPI & Extension based on javax.xml types - Binary serialization Extension based on MessagePack - Refine ValueType and promote ValueTypeFactory to SPI Those changes fix a lot of issues and inconsistencies with serialization. SQL EntityStore rewritten along the way to reuse JSONMapEntityStoreMixin. Work in progress Project: http://git-wip-us.apache.org/repos/asf/polygene-java/repo Commit: http://git-wip-us.apache.org/repos/asf/polygene-java/commit/17b11697 Tree: http://git-wip-us.apache.org/repos/asf/polygene-java/tree/17b11697 Diff: http://git-wip-us.apache.org/repos/asf/polygene-java/diff/17b11697 Branch: refs/heads/develop Commit: 17b116974128736e663e979a3df949b3044fd2e0 Parents: c48230e Author: Paul Merlin <[email protected]> Authored: Fri Feb 3 08:56:24 2017 +0100 Committer: Paul Merlin <[email protected]> Committed: Sun Apr 2 19:14:34 2017 +0200 ---------------------------------------------------------------------- .../structure/reports/ReportsPlugin.groovy | 2 +- core/api/build.gradle | 1 - core/api/src/docs/api.txt | 4 + core/api/src/docs/objects.txt | 4 +- core/api/src/docs/serialization.txt | 110 ++ core/api/src/docs/valuecomposite.txt | 107 +- .../StatefulAssociationCompositeDescriptor.java | 31 + .../api/configuration/Configuration.java | 114 +- .../polygene/api/entity/EntityDescriptor.java | 8 +- .../api/serialization/Deserializer.java | 68 ++ .../api/serialization/Serialization.java | 48 + .../serialization/SerializationException.java | 34 + .../polygene/api/serialization/Serializer.java | 247 +++++ .../polygene/api/serialization/package.html | 24 + .../polygene/api/type/CollectionType.java | 62 +- .../org/apache/polygene/api/type/EnumType.java | 5 +- .../api/type/HasAssignableFromType.java | 33 + .../polygene/api/type/HasAssignableToType.java | 29 + .../api/type/HasEqualOrAssignableFromType.java | 25 + .../api/type/HasEqualOrAssignableToType.java | 25 + .../apache/polygene/api/type/HasEqualType.java | 26 + .../polygene/api/type/HasTypesCollectors.java | 408 +++++++ .../polygene/api/type/HasTypesPredicate.java | 60 ++ .../org/apache/polygene/api/type/MapType.java | 45 +- .../api/type/MatchTypeSpecification.java | 51 - .../apache/polygene/api/type/Serialization.java | 62 -- .../polygene/api/type/ValueCompositeType.java | 32 +- .../org/apache/polygene/api/type/ValueType.java | 145 +-- .../apache/polygene/api/util/Collectors.java | 149 ++- .../MissingValueSerializationException.java | 43 - .../polygene/api/value/ValueDescriptor.java | 8 +- .../polygene/api/value/ValueDeserializer.java | 172 --- .../polygene/api/value/ValueSerialization.java | 56 - .../api/value/ValueSerializationException.java | 50 - .../polygene/api/value/ValueSerializer.java | 293 ----- .../api/type/HasTypesCollectorsTest.java | 131 +++ .../api/type/HasTypesPredicatesTest.java | 54 + .../polygene/api/type/ValueTypeFactoryTest.java | 105 ++ .../polygene/api/util/CollectorsTest.java | 106 +- .../api/value/DocumentationSupport.java | 121 +-- .../api/configuration/MyService.properties | 2 +- .../bootstrap/builder/ApplicationBuilder.java | 71 +- .../DefaultSerializationAssembler.java | 42 + .../builder/ApplicationBuilderTest.java | 5 +- .../runtime/bootstrap/ModuleAssemblyImpl.java | 31 +- .../runtime/property/PropertyModel.java | 46 +- .../runtime/structure/ModuleInstance.java | 50 +- .../runtime/structure/TypeLookupImpl.java | 289 +---- .../runtime/type/ValueTypeFactoryInstance.java | 147 +++ .../runtime/types/ValueTypeFactory.java | 233 ---- .../polygene/runtime/value/ValueInstance.java | 2 +- .../polygene/runtime/value/ValueModel.java | 2 +- .../bootstrap/ApplicationAssemblerTest.java | 5 +- .../polygene/regression/qi382/Qi382Test.java | 3 - .../polygene/regression/qi383/Qi383Test.java | 9 +- .../association/AssociationAssignmentTest.java | 4 - .../runtime/defaults/UseDefaultsTest.java | 20 +- .../polygene/runtime/mixin/JDKMixinTest.java | 88 +- .../property/ValueNestedBuilderTest.java | 3 - .../runtime/value/AssociationToValueTest.java | 3 - .../runtime/value/NestedValueBuilderTest.java | 16 +- .../runtime/value/ValueCompositeBasicsTest.java | 6 +- .../value/ValueSerializationRegressionTest.java | 9 +- .../runtime/value/ValueWithAssociationTest.java | 11 +- .../visibility/VisibilityInUnitOfWorkTest.java | 5 - .../memory/MemoryEntityStoreTest.java | 3 - core/spi/build.gradle | 4 +- core/spi/src/docs/serialization.txt | 83 ++ core/spi/src/docs/spi.txt | 4 +- core/spi/src/docs/valueserialization.txt | 83 -- .../memory/MemoryMapEntityStoreMixin.java | 49 +- .../serialization/javaxjson/JavaxJson.java | 139 +++ .../javaxjson/JavaxJsonAdapter.java | 54 + .../javaxjson/JavaxJsonAdapters.java | 64 ++ .../javaxjson/JavaxJsonDeserializer.java | 273 +++++ .../javaxjson/JavaxJsonSerialization.java | 26 + .../JavaxJsonSerializationService.java | 533 ++++++++++ .../javaxjson/JavaxJsonSerializer.java | 216 ++++ .../javaxjson/JavaxJsonSettings.java | 73 ++ .../serialization/javaxjson/package.html | 24 + .../entitystore/helpers/JSONEntityState.java | 395 ++++--- .../helpers/JSONManyAssociationState.java | 94 +- .../helpers/JSONMapEntityStoreMixin.java | 327 +++--- .../helpers/JSONNamedAssociationState.java | 77 +- .../spi/entitystore/helpers/MapEntityStore.java | 78 +- .../helpers/MapEntityStoreMixin.java | 560 +++++----- .../spi/entitystore/helpers/Migration.java | 8 +- .../spi/entitystore/helpers/StateStore.java | 7 +- .../apache/polygene/spi/module/ModuleSpi.java | 10 +- .../AbstractBinaryDeserializer.java | 48 + .../serialization/AbstractBinarySerializer.java | 51 + .../spi/serialization/AbstractDeserializer.java | 155 +++ .../spi/serialization/AbstractSerializer.java | 147 +++ .../serialization/AbstractTextDeserializer.java | 34 + .../serialization/AbstractTextSerializer.java | 48 + .../spi/serialization/JsonDeserializer.java | 164 +++ .../spi/serialization/JsonSerialization.java | 24 + .../spi/serialization/JsonSerializer.java | 106 ++ .../spi/serialization/XmlDeserializer.java | 107 ++ .../spi/serialization/XmlSerialization.java | 24 + .../spi/serialization/XmlSerializer.java | 123 +++ .../polygene/spi/serialization/package.html | 24 + .../polygene/spi/type/ValueTypeFactory.java | 11 + .../spi/value/ValueDeserializerAdapter.java | 1001 ------------------ .../spi/value/ValueSerializerAdapter.java | 570 ---------- .../org/apache/polygene/spi/value/package.html | 24 - .../orgjson/OrgJsonValueDeserializer.java | 485 --------- .../OrgJsonValueSerializationService.java | 32 - .../orgjson/OrgJsonValueSerializer.java | 114 -- .../valueserialization/orgjson/package.html | 24 - .../spi/entitystore/Polygene142Test.java | 15 +- .../helpers/JSONManyAssociationStateTest.java | 34 +- .../helpers/JsonNamedAssociationStateTest.java | 104 ++ .../polygene/test/EntityTestAssembler.java | 5 +- ...bstractConfigurationDeserializationTest.java | 9 +- .../test/model/assembly/PersistenceModule.java | 3 - .../AbstractCollectionSerializationTest.java | 481 +++++++++ .../AbstractDateFormatSerializationTest.java | 142 +++ .../AbstractPlainValueSerializationTest.java | 259 +++++ ...AbstractValueCompositeSerializationTest.java | 521 +++++++++ .../polygene/test/serialization/package.html | 24 + .../apache/polygene/test/util/JSONAssert.java | 130 --- .../AbstractCollectionSerializationTest.java | 433 -------- .../test/value/AbstractJsonDateFormatTest.java | 151 --- .../AbstractPlainValueSerializationTest.java | 211 ---- ...AbstractValueCompositeSerializationTest.java | 431 -------- .../org/apache/polygene/test/value/package.html | 24 - dependencies.gradle | 14 +- extensions/cache-ehcache/build.gradle | 1 - extensions/cache-memcache/build.gradle | 1 - extensions/entitystore-cassandra/build.gradle | 1 - .../cassandra/CassandraEntityStoreMixin.java | 10 +- .../cassandra/CassandraMapEntityStoreTest.java | 2 - extensions/entitystore-file/build.gradle | 2 - .../entitystore/file/FileEntityStoreMixin.java | 6 +- .../entitystore/file/FileEntityStoreTest.java | 2 - .../file/FileEntityStoreWithCacheTest.java | 2 - extensions/entitystore-geode/build.gradle | 1 - .../geode/GeodeEntityStoreMixin.java | 6 +- .../entitystore/geode/GeodeEntityStoreTest.java | 2 - .../geode/GeodeEntityStoreWithCacheTest.java | 2 - extensions/entitystore-hazelcast/build.gradle | 1 - .../hazelcast/HazelcastEntityStoreMixin.java | 6 +- .../hazelcast/HazelcastEntityStoreTest.java | 6 +- .../HazelcastEntityStoreWithCacheTest.java | 2 - extensions/entitystore-jclouds/build.gradle | 1 - .../jclouds/JCloudsMapEntityStoreMixin.java | 11 +- .../jclouds/JCloudsFilesystemTest.java | 4 - .../entitystore/jclouds/JCloudsS3Test.java | 2 - .../jclouds/JCloudsTransientTest.java | 6 - .../jclouds/JCloudsWithCacheTest.java | 2 - extensions/entitystore-jdbm/build.gradle | 1 - .../entitystore/jdbm/JdbmEntityStoreMixin.java | 6 +- .../entitystore/jdbm/JdbmEntityStoreTest.java | 2 - .../jdbm/JdbmEntityStoreWithCacheTest.java | 2 - extensions/entitystore-leveldb/build.gradle | 1 - .../leveldb/LevelDBEntityStoreMixin.java | 9 +- .../leveldb/JavaLevelDBEntityStoreTest.java | 2 - .../leveldb/JniLevelDBEntityStoreTest.java | 2 - .../LevelDBEntityStoreWithCacheTest.java | 2 - extensions/entitystore-memory/build.gradle | 1 - .../memory/MemoryEntityStoreTest.java | 5 - .../memory/MemoryEntityStoreWithCacheTest.java | 2 - extensions/entitystore-mongodb/build.gradle | 1 - .../mongodb/MongoMapEntityStoreMixin.java | 10 +- .../mongodb/EmbedMongoMapEntityStoreTest.java | 3 - .../mongodb/MongoMapEntityStoreTest.java | 7 +- .../MongoMapEntityStoreWithCacheTest.java | 7 +- extensions/entitystore-preferences/build.gradle | 1 - .../PreferencesEntityStoreMixin.java | 48 +- .../preferences/PreferencesEntityStoreTest.java | 2 - extensions/entitystore-redis/build.gradle | 1 - .../redis/RedisMapEntityStoreMixin.java | 12 +- .../redis/RedisMapEntityStoreTest.java | 4 +- .../redis/RedisMapEntityStoreWithCacheTest.java | 4 +- extensions/entitystore-riak/build.gradle | 1 - .../riak/RiakMapEntityStoreMixin.java | 12 +- .../riak/RiakMapEntityStoreTest.java | 2 - .../riak/RiakMapEntityStoreWithCacheTest.java | 2 - extensions/entitystore-sql/build.gradle | 3 +- .../entitystore/sql/SQLEntityStoreMixin.java | 624 ----------- .../entitystore/sql/SQLEntityStoreService.java | 39 - .../sql/SQLMapEntityStoreMapping.java | 69 ++ .../entitystore/sql/SQLMapEntityStoreMixin.java | 237 +++++ .../sql/SQLMapEntityStoreService.java | 45 + .../AbstractSQLEntityStoreAssembler.java | 93 -- .../AbstractSQLMapEntityStoreAssembler.java | 85 ++ .../assembly/DerbySQLEntityStoreAssembler.java | 21 +- .../sql/assembly/H2SQLEntityStoreAssembler.java | 21 +- .../sql/assembly/MySQLEntityStoreAssembler.java | 21 +- .../PostgreSQLEntityStoreAssembler.java | 28 +- .../assembly/SQLiteEntityStoreAssembler.java | 21 +- .../sql/internal/DatabaseSQLService.java | 42 +- .../sql/internal/DatabaseSQLServiceState.java | 6 +- .../DatabaseSQLServiceStatementsMixin.java | 15 +- .../sql/internal/DatabaseSQLStringsBuilder.java | 248 ++--- .../DerbySQLDatabaseSQLServiceMixin.java | 17 +- .../internal/H2SQLDatabaseSQLServiceMixin.java | 25 +- .../internal/MySQLDatabaseSQLServiceMixin.java | 18 +- .../PostgreSQLDatabaseSQLServiceMixin.java | 30 +- .../internal/SQLiteDatabaseSQLServiceMixin.java | 25 +- .../polygene/entitystore/sql/internal/SQLs.java | 20 +- .../sql/DerbySQLEntityStoreTest.java | 41 +- .../entitystore/sql/H2SQLEntityStoreTest.java | 49 +- .../entitystore/sql/MySQLEntityStoreTest.java | 32 +- .../sql/PostgreSQLEntityStoreTest.java | 38 +- .../entitystore/sql/SQLiteEntityStoreTest.java | 51 +- extensions/indexing-elasticsearch/build.gradle | 1 - .../elasticsearch/ElasticSearchIndexer.java | 240 ++--- .../assembly/ESClientIndexQueryAssembler.java | 5 - .../assembly/ESClusterIndexQueryAssembler.java | 5 - .../ESFilesystemIndexQueryAssembler.java | 2 - .../elasticsearch/ElasticSearchQueryTest.java | 4 - extensions/indexing-rdf/build.gradle | 1 - .../index/rdf/query/RdfQueryParserFactory.java | 11 +- .../rdf/query/internal/RdfQueryParserImpl.java | 18 +- .../polygene/index/rdf/ContainsAllTest.java | 118 +-- .../apache/polygene/index/rdf/ContainsTest.java | 50 +- .../polygene/index/rdf/RdfComplexQueryTest.java | 5 +- .../polygene/index/rdf/RdfEntityFinderTest.java | 3 - .../index/rdf/RdfNamedQueryMultimoduleTest.java | 2 - .../polygene/index/rdf/RdfNamedQueryTest.java | 2 - .../index/rdf/RdfQueryMultimoduleTest.java | 2 - .../polygene/index/rdf/qi66/Qi66IssueTest.java | 7 +- .../polygene/index/rdf/qi95/Qi95IssueTest.java | 22 +- extensions/indexing-solr/build.gradle | 1 - .../solr/assembly/SolrIndexingAssembler.java | 25 +- .../solr/internal/SolrEntityIndexerMixin.java | 95 +- extensions/indexing-sql/build.gradle | 1 - .../skeletons/SQLCompatEntityStateWrapper.java | 1 + .../polygene/migration/MigrationService.java | 549 +++++++--- .../org/apache/polygene/migration/Migrator.java | 56 +- .../assembly/AbstractMigrationRule.java | 6 + .../assembly/EntityMigrationOperation.java | 12 +- .../migration/assembly/EntityMigrationRule.java | 27 +- .../migration/assembly/MigrationContext.java | 60 ++ .../migration/operation/AddAssociation.java | 14 +- .../migration/operation/AddManyAssociation.java | 14 +- .../operation/AddNamedAssociation.java | 14 +- .../migration/operation/AddProperty.java | 14 +- .../migration/operation/RemoveAssociation.java | 14 +- .../operation/RemoveManyAssociation.java | 14 +- .../operation/RemoveNamedAssociation.java | 14 +- .../migration/operation/RemoveProperty.java | 14 +- .../migration/operation/RenameAssociation.java | 14 +- .../migration/operation/RenameEntity.java | 35 +- .../operation/RenameManyAssociation.java | 14 +- .../operation/RenameNamedAssociation.java | 14 +- .../migration/operation/RenameProperty.java | 14 +- .../polygene/migration/MigrationTest.java | 37 +- extensions/reindexer/build.gradle | 1 - .../polygene/index/reindexer/ReindexerTest.java | 2 - extensions/serialization-javaxjson/build.gradle | 34 + .../serialization-javaxjson/dev-status.xml | 38 + .../src/docs/serialization-javaxjson.txt | 31 + .../JavaxJsonSerializationAssembler.java | 58 + .../serialization/javaxjson/package.html | 24 + .../javaxjson/CustomJsonAdapterTest.java | 180 ++++ .../JavaxJsonCollectionSerializationTest.java | 24 + ...vaxJsonConfigurationDeserializationTest.java | 24 + .../JavaxJsonDateFormatSerializationTest.java | 24 + .../JavaxJsonPlainValueSerializationTest.java | 26 + ...avaxJsonValueCompositeSerializationTest.java | 60 ++ .../src/test/resources/configtest.json | 8 + extensions/serialization-javaxxml/build.gradle | 34 + .../serialization-javaxxml/dev-status.xml | 38 + .../src/docs/serialization-javaxxml.txt | 30 + .../serialization/javaxxml/JavaxXml.java | 161 +++ .../serialization/javaxxml/JavaxXmlAdapter.java | 56 + .../javaxxml/JavaxXmlAdapters.java | 64 ++ .../javaxxml/JavaxXmlDeserializer.java | 325 ++++++ .../javaxxml/JavaxXmlSerialization.java | 88 ++ .../JavaxXmlSerializationAssembler.java | 58 + .../javaxxml/JavaxXmlSerializationService.java | 372 +++++++ .../javaxxml/JavaxXmlSerializer.java | 271 +++++ .../javaxxml/JavaxXmlSettings.java | 134 +++ .../serialization/javaxxml/package.html | 24 + .../javaxxml/JavaxXmlAdaptersTest.java | 39 + .../javaxxml/JavaxXmlCollectionTest.java | 31 + .../javaxxml/JavaxXmlDateFormatTest.java | 33 + .../javaxxml/JavaxXmlPlainValueTest.java | 35 + .../javaxxml/JavaxXmlValueCompositeTest.java | 68 ++ extensions/serialization-msgpack/build.gradle | 36 + extensions/serialization-msgpack/dev-status.xml | 38 + .../src/docs/serialization-msgpack.txt | 30 + .../msgpack/MessagePackAdapter.java | 57 + .../msgpack/MessagePackAdapters.java | 64 ++ .../msgpack/MessagePackDeserializer.java | 295 ++++++ .../msgpack/MessagePackSerialization.java | 22 + .../MessagePackSerializationAssembler.java | 52 + .../MessagePackSerializationService.java | 414 ++++++++ .../msgpack/MessagePackSerializer.java | 187 ++++ .../msgpack/MessagePackSettings.java | 44 + .../polygene/serialization/msgpack/package.html | 24 + .../MessagePackCollectionSerializationTest.java | 31 + .../MessagePackDateFormatSerializationTest.java | 33 + .../MessagePackPlainValueSerializationTest.java | 35 + ...sagePackValueCompositeSerializationTest.java | 31 + .../valueserialization-jackson/build.gradle | 37 - .../valueserialization-jackson/dev-status.xml | 36 - .../src/docs/vs-jackson.txt | 43 - .../jackson/JacksonValueDeserializer.java | 379 ------- .../JacksonValueSerializationService.java | 32 - .../jackson/JacksonValueSerializer.java | 92 -- .../JacksonValueSerializationAssembler.java | 42 - .../valueserialization/jackson/package.html | 24 - .../JacksonCollectionSerializationTest.java | 38 - ...JacksonConfigurationDeserializationTest.java | 39 - .../jackson/JacksonJsonDateFormatTest.java | 38 - .../JacksonPlainValueSerializationTest.java | 36 - .../JacksonValueCompositeSerializationTest.java | 38 - .../src/test/resources/configtest.json | 8 - .../valueserialization-orgjson/build.gradle | 35 - .../valueserialization-orgjson/dev-status.xml | 36 - .../src/docs/vs-orgjson.txt | 43 - .../OrgJsonValueSerializationAssembler.java | 41 - .../valueserialization/orgjson/package.html | 24 - .../OrgJsonCollectionSerializationTest.java | 37 - ...OrgJsonConfigurationDeserializationTest.java | 38 - .../orgjson/OrgJsonDateFormatTest.java | 37 - .../OrgJsonPlainValueSerializationTest.java | 35 - .../OrgJsonValueCompositeSerializationTest.java | 37 - .../src/test/resources/configtest.json | 8 - extensions/valueserialization-stax/build.gradle | 37 - .../valueserialization-stax/dev-status.xml | 36 - .../src/docs/vs-stax.txt | 43 - .../stax/StaxValueDeserializer.java | 522 --------- .../stax/StaxValueSerializationService.java | 32 - .../stax/StaxValueSerializer.java | 134 --- .../StaxValueSerializationAssembler.java | 42 - .../valueserialization/stax/package.html | 24 - .../stax/StaxCollectionSerializationTest.java | 47 - .../StaxConfigurationDeserializationTest.java | 69 -- .../stax/StaxPlainValueSerializationTest.java | 45 - .../StaxValueCompositeSerializationTest.java | 47 - .../src/test/resources/configtest.xml | 50 - internals/testsupport-internal/build.gradle | 5 + .../library/appbrowser/AppBrowserTest.java | 2 - .../library/constraints/ConstraintTest.java | 10 +- libraries/rdf/build.gradle | 1 - .../rdf/entity/EntityStateSerializer.java | 176 +-- .../rdf/entity/EntitySerializerTest.java | 16 +- libraries/rest-client/build.gradle | 1 - .../ValueCompositeRequestWriter.java | 17 +- .../responsereader/DefaultResponseReader.java | 56 +- .../responsereader/JSONResponseReader.java | 88 +- .../responsereader/TableResponseReader.java | 137 +-- .../ContextResourceClientFactoryTest.java | 16 +- .../rest/client/ContinuousIntegrationTest.java | 20 +- .../library/rest/client/RssReaderTest.java | 6 +- .../polygene/library/rest/common/Resource.java | 2 +- .../rest/server/api/ContextResource.java | 2 +- .../requestreader/DefaultRequestReader.java | 14 +- .../responsewriter/AbstractResponseWriter.java | 3 +- .../responsewriter/DefaultResponseWriter.java | 4 +- .../responsewriter/FormResponseWriter.java | 21 +- .../responsewriter/JSONResponseWriter.java | 22 +- .../responsewriter/LinksResponseWriter.java | 3 +- .../responsewriter/TableResponseWriter.java | 92 +- .../ValueCompositeResponseWriter.java | 10 +- .../ValueDescriptorResponseWriter.java | 51 +- libraries/rest/build.gradle | 4 +- .../library/rest/admin/EntitiesResource.java | 7 +- .../library/rest/admin/EntityResource.java | 13 +- .../library/rest/admin/RDFAssembler.java | 2 - libraries/restlet/build.gradle | 3 +- .../RestletCrudConnectivityAssembler.java | 2 - .../configuration/ConfigurationModule.java | 2 - .../infrastructue/SerializationModule.java | 5 - .../serialization/JsonRepresentation.java | 15 +- libraries/sql-liquibase/build.gradle | 1 + .../sql/liquibase/LiquibaseServiceTest.java | 124 +-- .../polygene/library/sql/common/Databases.java | 1 + .../ConcurrentUoWFileModificationException.java | 2 +- manual/src/docs/userguide/extensions.txt | 24 +- samples/forum/build.gradle | 1 - .../sample/forum/assembler/ForumAssembler.java | 17 +- samples/rental/build.gradle | 1 - .../rental/web/assembly/StorageModule.java | 5 - .../sample/sqlsupport/AppAssembler.java | 7 - settings.gradle | 6 +- tests/performance/build.gradle | 1 - .../jdbm/JdbmEntityStorePerformanceTest.java | 2 - .../MemoryEntityStorePerformanceTest.java | 4 +- .../sql/DerbySQLEntityStorePerformanceTest.java | 3 - .../indexing/rdf/QueryPerformanceTest.java | 14 +- tools/generator-polygene/app/index.js | 5 +- .../ConfigModule/bootstrap.tmpl | 2 - .../SerializationModule/bootstrap.tmpl | 6 +- .../SerializationModule/module.js | 2 +- .../InfrastructureLayer/bootstrap.tmpl | 2 +- .../templates/buildtool/gradle-bootstrap.tmpl | 2 +- tools/generator-polygene/test/generator_test.js | 15 +- .../tools/model/VisitableDetailTest.java | 2 + 394 files changed, 13361 insertions(+), 11342 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/reports/ReportsPlugin.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/reports/ReportsPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/reports/ReportsPlugin.groovy index 862e2ec..346005f 100644 --- a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/reports/ReportsPlugin.groovy +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/reports/ReportsPlugin.groovy @@ -120,7 +120,7 @@ class ReportsPlugin implements Plugin<Project> "Core SPI" : [ "org.apache.polygene.spi", "org.apache.polygene.spi.*" ], "Libraries" : [ "org.apache.polygene.library.*" ], - "Extensions" : [ "org.apache.polygene.valueserialization.*", + "Extensions" : [ "org.apache.polygene.serialization.*", "org.apache.polygene.entitystore.*", "org.apache.polygene.index.*", "org.apache.polygene.metrics.*", http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/build.gradle ---------------------------------------------------------------------- diff --git a/core/api/build.gradle b/core/api/build.gradle index b210fac..67c5f96 100644 --- a/core/api/build.gradle +++ b/core/api/build.gradle @@ -25,7 +25,6 @@ jar { manifest { name = "Apache Polygene⢠Core API" } } dependencies { testImplementation polygene.core.testsupport testImplementation polygene.library( 'constraints' ) - testImplementation polygene.extension( 'valueserialization-orgjson' ) testRuntimeOnly polygene.core.runtime } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/docs/api.txt ---------------------------------------------------------------------- diff --git a/core/api/src/docs/api.txt b/core/api/src/docs/api.txt index d601b8a..fa7188e 100644 --- a/core/api/src/docs/api.txt +++ b/core/api/src/docs/api.txt @@ -94,6 +94,10 @@ include::decoratormixin.txt[] :leveloffset: {level3} +include::serialization.txt[] + +:leveloffset: {level3} + // include::indexing.txt[] :leveloffset: {level3} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/docs/objects.txt ---------------------------------------------------------------------- diff --git a/core/api/src/docs/objects.txt b/core/api/src/docs/objects.txt index 6269ca7..4b5d546 100644 --- a/core/api/src/docs/objects.txt +++ b/core/api/src/docs/objects.txt @@ -28,9 +28,9 @@ The characteristics of an Object compared to Composite meta types are; * Can not have Property instances managed by the Polygene runtime. == Serialization == -Objects can be serialized and deserialized using the ValueSerialization API, if and only +Objects can be serialized and deserialized using the Serialization API, if and only if they are used as types in Properties in Values or Entities. It depends on the -ValueSerialization implementation on how the objects are serialized, and +Serialization implementation on how the objects are serialized, and what the requirements are to allow for deserialization. In general, the Spring POJO setter/getter approach will always work, a default constructor is needed, and to be safe, make it into +java.io.Serializable+. http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/docs/serialization.txt ---------------------------------------------------------------------- diff --git a/core/api/src/docs/serialization.txt b/core/api/src/docs/serialization.txt new file mode 100644 index 0000000..e789125 --- /dev/null +++ b/core/api/src/docs/serialization.txt @@ -0,0 +1,110 @@ +////////////////////// + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. +////////////////////// + +[[core-api-serialization,Serialization]] += Serialization = + +// TODO Reword with the following outline +// Preamble - What is it for? What can I use it with?, see <<extensions>> +// Use cases - Value, collections/streams & arrays of values + +State can be serialized and deserialized using the Serialization API which is a Service API implemented +by SPI and extensions. + +TIP: +Serialization extends Serializer, Deserializer+. See the <<javadocs>> for interfaces detail. + +The Serialization mechanism apply to the following object types : + + * ValueComposite, + * EntityReference, + * Iterable & Stream, + * Map, + * Plain Value. + +Nested Plain Values, EntityReferences, Iterables, Streams, Maps, ValueComposites are supported. +EntityComposites and EntityReferences are serialized as their identity string. + +Plain Values can be one of : + + * String, + * Character or char, + * Boolean or boolean, + * Integer or int, + * Long or long, + * Short or short, + * Byte or byte, + * Float or float, + * Double or double, + * BigInteger, + * BigDecimal, + * Date, + * DateTime (JodaTime), + * LocalDateTime (JodaTime), + * LocalDate (JodaTime). + +TIP: Serialization behaviour can be tuned with options. +Every +Serializer+ methods can take a +Serializer.Options+ object that contains flags to change how some +values are serialized. See the <<javadocs>> for more details. + +Values of unknown types and all arrays are considered as +java.io.Serializable+ and by so are (de)serialized to (from) +base64 encoded bytes using pure Java serialization. If it happens that the value is not Serializable or the input to +deserialize is invalid, a +SerializationException+ is thrown. + +Methods of +Serializer+ allow to specify if the serialized state should contain extra type information about the +serialized value. Having type information in the serialized payload allows to keep actual ValueComposite types and by so +circumvent +AmbiguousTypeException+ when deserializing. + +Core Runtime provides a default Serialization system based on the +https://github.com/douglascrockford/JSON-java[org.json] Java library producing and consuming JSON. + +Let's see how it works in practice. + +[snippet,java] +---- +source=core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java +tag=default +---- + +Reading this first example step by step we ; + + . declare a ValueComposite, + . assemble it, + . create a new Value instance, + . use the +ValueComposite#toString()+ method to get a JSON representation of the Value, + . and finally, use the +Module#newValueFromSerializedState()+ method to create a new Value instance from the JSON + state. + ++ValueComposite#toString()+ method leverage Value Serialization and by so provide JSON based representation. The Module +API allows to create new Value instances from serialized state. + +On top of that, Application assemblies can register different implementation of Serialization as Services to +support more formats, see the <<extensions>> section. Note that the default behaviour described above is overriden if a +Serialization Service is visible. + +Let's see how to use the Serialization Services. + +[snippet,java] +---- +source=core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java +tag=service +---- + +In this second example, we ; + + . declare a ValueComposite, + . assemble it, + . assemble a Serialization Service backed by the +org.json+ package, + . get the +Serializer+ and +Deserializer+ Services injected, + . create a new Value instance, + . use the +Serializer#serialize()+ method to get a JSON representation of the Value, + . and finally, use the +Deserializer#deserialize()+ method to create a new Value instance from the JSON state. http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/docs/valuecomposite.txt ---------------------------------------------------------------------- diff --git a/core/api/src/docs/valuecomposite.txt b/core/api/src/docs/valuecomposite.txt index c3de8b5..1903c2c 100644 --- a/core/api/src/docs/valuecomposite.txt +++ b/core/api/src/docs/valuecomposite.txt @@ -27,109 +27,4 @@ The characteristics of a ValueComposite compared to other Composite meta types a * It is Immutable. * Its equals/hashCode works on both the descriptor and the values of the ValueComposite. * Can be used as Property types. - * Can be serialized and deserialized. - -== Value Serialization == -Value objects can be serialized and deserialized using the ValueSerialization API which is a Service API implemented -by SPI and extensions. - -TIP: +ValueSerialization extends ValueSerializer, ValueDeserializer+. See the <<javadocs>> for interfaces detail. - -The ValueSerialization mechanism apply to the following object types : - - * ValueComposite, - * EntityReference, - * Iterable, - * Map, - * Plain Value. - -Nested Plain Values, EntityReferences, Iterables, Maps, ValueComposites are supported. -EntityComposites and EntityReferences are serialized as their identity string. - -Plain Values can be one of : - - * String, - * Character or char, - * Boolean or boolean, - * Integer or int, - * Long or long, - * Short or short, - * Byte or byte, - * Float or float, - * Double or double, - * BigInteger, - * BigDecimal, - * Date, - * DateTime (JodaTime), - * LocalDateTime (JodaTime), - * LocalDate (JodaTime). - -TIP: Serialization behaviour can be tuned with options. -Every +ValueSerializer+ methods can take a +ValueSerializer.Options+ object that contains flags to change how some -values are serialized. See the <<javadocs>> for more details. - -Values of unknown types and all arrays are considered as +java.io.Serializable+ and by so are (de)serialized to (from) -base64 encoded bytes using pure Java serialization. If it happens that the value is not Serializable or the input to -deserialize is invalid, a +ValueSerializationException+ is thrown. - -Methods of +ValueSerializer+ allow to specify if the serialized state should contain extra type information about the -serialized value. Having type information in the serialized payload allows to keep actual ValueComposite types and by so -circumvent +AmbiguousTypeException+ when deserializing. - -Core Runtime provides a default ValueSerialization system based on the -https://github.com/douglascrockford/JSON-java[org.json] Java library producing and consuming JSON. - -Let's see how it works in practice. - -[snippet,java] ----- -source=core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java -tag=default ----- - -Reading this first example step by step we ; - - . declare a ValueComposite, - . assemble it, - . create a new Value instance, - . use the +ValueComposite#toString()+ method to get a JSON representation of the Value, - . and finally, use the +Module#newValueFromSerializedState()+ method to create a new Value instance from the JSON - state. - -+ValueComposite#toString()+ method leverage Value Serialization and by so provide JSON based representation. The Module -API allows to create new Value instances from serialized state. - -On top of that, Application assemblies can register different implementation of ValueSerialization as Services to -support more formats, see the <<extensions>> section. Note that the default behaviour described above is overriden if a -ValueSerialization Service is visible. - -Let's see how to use the ValueSerialization Services. - -[snippet,java] ----- -source=core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java -tag=service ----- - -In this second example, we ; - - . declare a ValueComposite, - . assemble it, - . assemble a ValueSerialization Service backed by the +org.json+ package, - . get the +ValueSerializer+ and +ValueDeserializer+ Services injected, - . create a new Value instance, - . use the +ValueSerializer#serialize()+ method to get a JSON representation of the Value, - . and finally, use the +ValueDeserializer#eserialize()+ method to create a new Value instance from the JSON state. - -Many applications need to stream data. The ValueSerialization API support such use cases using classic streams: - -[snippet,java] ----- -source=core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java -tag=stream ----- - - . get a handle on a source of values and an +OutputStream+, - . serialize data into the +OutputStream+, - . get a handle on an +InputStream+, - . deserialize data from the +InputStream+. + * Can be serialized and deserialized, see <<core-api-serialization>>. http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/composite/StatefulAssociationCompositeDescriptor.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/StatefulAssociationCompositeDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/StatefulAssociationCompositeDescriptor.java new file mode 100644 index 0000000..c3c5a61 --- /dev/null +++ b/core/api/src/main/java/org/apache/polygene/api/composite/StatefulAssociationCompositeDescriptor.java @@ -0,0 +1,31 @@ +/* + * 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.api.composite; + +import org.apache.polygene.api.association.AssociationStateDescriptor; + +/** + * Stateful Association Composite Descriptor. + */ +public interface StatefulAssociationCompositeDescriptor extends StatefulCompositeDescriptor +{ + @Override + AssociationStateDescriptor state(); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/configuration/Configuration.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/configuration/Configuration.java b/core/api/src/main/java/org/apache/polygene/api/configuration/Configuration.java index 96822a0..21eb05f 100644 --- a/core/api/src/main/java/org/apache/polygene/api/configuration/Configuration.java +++ b/core/api/src/main/java/org/apache/polygene/api/configuration/Configuration.java @@ -22,6 +22,7 @@ package org.apache.polygene.api.configuration; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import org.apache.polygene.api.PolygeneAPI; import org.apache.polygene.api.composite.Composite; import org.apache.polygene.api.composite.PropertyMapper; @@ -37,15 +38,16 @@ import org.apache.polygene.api.service.ServiceComposite; import org.apache.polygene.api.service.ServiceDescriptor; import org.apache.polygene.api.service.ServiceReference; import org.apache.polygene.api.service.qualifier.ServiceTags; +import org.apache.polygene.api.serialization.Deserializer; +import org.apache.polygene.api.serialization.Serialization; import org.apache.polygene.api.structure.Module; -import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException; import org.apache.polygene.api.unitofwork.NoSuchEntityException; +import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException; import org.apache.polygene.api.unitofwork.UnitOfWork; import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException; import org.apache.polygene.api.unitofwork.UnitOfWorkFactory; import org.apache.polygene.api.usecase.Usecase; import org.apache.polygene.api.usecase.UsecaseBuilder; -import org.apache.polygene.api.value.ValueSerialization; /** * Provide Configurations for Services. A Service that wants to be configurable @@ -175,8 +177,7 @@ public interface Configuration<T> private UnitOfWorkFactory uowf; @Service - private Iterable<ServiceReference<ValueSerialization>> valueSerialization; - + private Iterable<ServiceReference<Deserializer>> stateDeserializers; public ConfigurationMixin() { @@ -247,16 +248,17 @@ public interface Configuration<T> } catch( NoSuchEntityException | NoSuchEntityTypeException e ) { - return (V) initializeConfigurationInstance( serviceComposite, uow, serviceModel, serviceComposite.identity().get() ); + return (V) initializeConfigurationInstance( serviceComposite, uow, serviceModel, + serviceComposite.identity().get() ); } return configuration; } @SuppressWarnings( "unchecked" ) - private <V extends HasIdentity> V initializeConfigurationInstance(ServiceComposite serviceComposite, - UnitOfWork uow, - ServiceDescriptor serviceModel, - Identity identity + private <V extends HasIdentity> V initializeConfigurationInstance( ServiceComposite serviceComposite, + UnitOfWork uow, + ServiceDescriptor serviceModel, + Identity identity ) throws InstantiationException { @@ -282,7 +284,8 @@ public interface Configuration<T> { try { - EntityBuilder<V> configBuilder = buildUow.newEntityBuilder( serviceModel.<V>configurationType(), identity ); + EntityBuilder<V> configBuilder = buildUow.newEntityBuilder( + serviceModel.<V>configurationType(), identity ); configBuilder.newInstance(); } catch( ConstraintViolationException e ) @@ -304,7 +307,8 @@ public interface Configuration<T> catch( Exception e1 ) { InstantiationException ex = new InstantiationException( - "Could not instantiate configuration, and no configuration initialization file was found (" + identity + ")" ); + "Could not instantiate configuration, and no configuration initialization file was found (" + + identity + ")" ); ex.initCause( e1 ); throw ex; } @@ -319,23 +323,29 @@ public interface Configuration<T> { EntityBuilder<V> configBuilder = buildUow.newEntityBuilder( configType, identity ); String resourceName = identity + ".properties"; - InputStream asStream = getResource( compositeType, resourceName ); - if( asStream != null ) + try( InputStream asStream = getResource( compositeType, resourceName ) ) { - try - { - PropertyMapper.map( asStream, (Composite) configBuilder.instance() ); - return configBuilder.newInstance(); - } - catch( IOException e1 ) + if( asStream != null ) { - InstantiationException exception = new InstantiationException( - "Could not read underlying Properties file." ); - exception.initCause( e1 ); - throw exception; + try + { + PropertyMapper.map( asStream, (Composite) configBuilder.instance() ); + return configBuilder.newInstance(); + } + catch( IOException e1 ) + { + InstantiationException exception = new InstantiationException( + "Could not read underlying Properties file." ); + exception.initCause( e1 ); + throw exception; + } } + return null; + } + catch( IOException ignored ) + { + return null; } - return null; } private InputStream getResource( Class<?> type, String resourceName ) @@ -348,53 +358,57 @@ public interface Configuration<T> return type.getResourceAsStream( resourceName ); } - private <C, V extends HasIdentity> V tryLoadJsonFile(UnitOfWork uow, - Class<C> compositeType, - Class<V> configType, - Identity identity + private <C, V extends HasIdentity> V tryLoadJsonFile( UnitOfWork uow, + Class<C> compositeType, + Class<V> configType, + Identity identity ) { - return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.JSON, ".json" ); + return readConfig( uow, compositeType, configType, identity, Serialization.Formats.JSON, ".json" ); } - private <C, V extends HasIdentity> V tryLoadYamlFile(UnitOfWork uow, - Class<C> compositeType, - Class<V> configType, - Identity identity + private <C, V extends HasIdentity> V tryLoadYamlFile( UnitOfWork uow, + Class<C> compositeType, + Class<V> configType, + Identity identity ) { - return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.YAML, ".yaml" ); + return readConfig( uow, compositeType, configType, identity, Serialization.Formats.YAML, ".yaml" ); } - private <C, V extends HasIdentity> V tryLoadXmlFile(UnitOfWork uow, - Class<C> compositeType, - Class<V> configType, - Identity identity + private <C, V extends HasIdentity> V tryLoadXmlFile( UnitOfWork uow, + Class<C> compositeType, + Class<V> configType, + Identity identity ) { - return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.XML, ".xml" ); + return readConfig( uow, compositeType, configType, identity, Serialization.Formats.XML, ".xml" ); } - private <C, V extends HasIdentity> V readConfig(UnitOfWork uow, - Class<C> compositeType, - Class<V> configType, - Identity identity, - String format, - String extension + private <C, V extends HasIdentity> V readConfig( UnitOfWork uow, + Class<C> compositeType, + Class<V> configType, + Identity identity, + String format, + String extension ) { - for( ServiceReference<ValueSerialization> serializerRef : valueSerialization ) + for( ServiceReference<Deserializer> serializerRef : stateDeserializers ) { ServiceTags serviceTags = serializerRef.metaInfo( ServiceTags.class ); if( serviceTags.hasTag( format ) ) { String resourceName = identity + extension; - InputStream asStream = getResource( compositeType, resourceName ); - if( asStream != null ) + try( InputStream asStream = getResource( compositeType, resourceName ) ) { - V configObject = serializerRef.get().deserialize( uow.module(), configType, asStream ); - return uow.toEntity( configType, configObject ); + if( asStream != null ) + { + V configObject = serializerRef.get().deserialize( uow.module(), configType, + new InputStreamReader( asStream ) ); + return uow.toEntity( configType, configObject ); + } } + catch( IOException ignored ) {} } } return null; http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/entity/EntityDescriptor.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/entity/EntityDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/entity/EntityDescriptor.java index 1ff6180..bac90e1 100644 --- a/core/api/src/main/java/org/apache/polygene/api/entity/EntityDescriptor.java +++ b/core/api/src/main/java/org/apache/polygene/api/entity/EntityDescriptor.java @@ -20,18 +20,14 @@ package org.apache.polygene.api.entity; -import org.apache.polygene.api.association.AssociationStateDescriptor; import org.apache.polygene.api.composite.CompositeDescriptor; -import org.apache.polygene.api.composite.StatefulCompositeDescriptor; +import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor; /** * Entity Descriptor. */ public interface EntityDescriptor - extends CompositeDescriptor, StatefulCompositeDescriptor + extends CompositeDescriptor, StatefulAssociationCompositeDescriptor { - @Override - AssociationStateDescriptor state(); - boolean queryable(); } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/serialization/Deserializer.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/Deserializer.java b/core/api/src/main/java/org/apache/polygene/api/serialization/Deserializer.java new file mode 100644 index 0000000..7ab1c44 --- /dev/null +++ b/core/api/src/main/java/org/apache/polygene/api/serialization/Deserializer.java @@ -0,0 +1,68 @@ +/* + * 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.api.serialization; + +import java.io.InputStream; +import java.io.Reader; +import java.util.function.Function; +import java.util.stream.Stream; +import org.apache.polygene.api.structure.ModuleDescriptor; +import org.apache.polygene.api.type.ValueType; + +public interface Deserializer +{ + <T> T deserialize( ModuleDescriptor module, ValueType valueType, InputStream state ); + + <T> T deserialize( ModuleDescriptor module, ValueType valueType, Reader state ); + + <T> T deserialize( ModuleDescriptor module, ValueType valueType, String state ); + + <T> Function<String, T> deserializeFunction( ModuleDescriptor module, ValueType valueType ); + + <T> Stream<T> deserializeEach( ModuleDescriptor module, ValueType valueType, Iterable<String> states ); + + <T> Stream<T> deserializeEach( ModuleDescriptor module, ValueType valueType, String... states ); + + <T> T fromBytes( ModuleDescriptor module, ValueType valueType, byte[] bytes ); + + <T> Function<byte[], T> fromBytesFunction( ModuleDescriptor module, ValueType valueType ); + + <T> Stream<T> fromBytesEach( ModuleDescriptor module, ValueType valueType, Iterable<byte[]> states ); + + <T> Stream<T> fromBytesEach( ModuleDescriptor module, ValueType valueType, byte[]... states ); + + <T> T deserialize( ModuleDescriptor module, Class<T> type, InputStream state ); + + <T> T deserialize( ModuleDescriptor module, Class<T> type, Reader state ); + + <T> T deserialize( ModuleDescriptor module, Class<T> type, String state ); + + <T> Function<String, T> deserializeFunction( ModuleDescriptor module, Class<T> type ); + + <T> Stream<T> deserializeEach( ModuleDescriptor module, Class<T> type, Iterable<String> states ); + + <T> Stream<T> deserializeEach( ModuleDescriptor module, Class<T> type, String... states ); + + <T> T fromBytes( ModuleDescriptor module, Class<T> type, byte[] bytes ); + + <T> Function<byte[], T> fromBytesFunction( ModuleDescriptor module, Class<T> type ); + + <T> Stream<T> fromBytesEach( ModuleDescriptor module, Class<T> type, Iterable<byte[]> states ); + + <T> Stream<T> fromBytesEach( ModuleDescriptor module, Class<T> type, byte[]... states ); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/serialization/Serialization.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/Serialization.java b/core/api/src/main/java/org/apache/polygene/api/serialization/Serialization.java new file mode 100644 index 0000000..ff1d32f --- /dev/null +++ b/core/api/src/main/java/org/apache/polygene/api/serialization/Serialization.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.api.serialization; + +/** + * + */ +public interface Serialization extends Serializer, Deserializer +{ + /** + * Serialization format @Service tags. + * + * <p> + * Serialization implementations should be tagged with theses at assembly time so that consumers can + * specify which format they need. + * </p> + */ + interface Formats + { + /** + * Tag a Serialization service that support the JSON format. + */ + String JSON = "json"; + /** + * Tag a Serialization service that support the XML format. + */ + String XML = "xml"; + /** + * Tag a Serialization service that support the YAML format. + */ + String YAML = "yaml"; + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/serialization/SerializationException.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/SerializationException.java b/core/api/src/main/java/org/apache/polygene/api/serialization/SerializationException.java new file mode 100644 index 0000000..aeb0bfa --- /dev/null +++ b/core/api/src/main/java/org/apache/polygene/api/serialization/SerializationException.java @@ -0,0 +1,34 @@ +/* + * 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.api.serialization; + +/** + * Serialization Exception. + */ +public class SerializationException extends RuntimeException +{ + public SerializationException( String message ) + { + super( message ); + } + + public SerializationException( String message, Throwable cause ) + { + super( message, cause ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/serialization/Serializer.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/Serializer.java b/core/api/src/main/java/org/apache/polygene/api/serialization/Serializer.java new file mode 100644 index 0000000..9f9f47d --- /dev/null +++ b/core/api/src/main/java/org/apache/polygene/api/serialization/Serializer.java @@ -0,0 +1,247 @@ +/* + * 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.api.serialization; + +import java.io.OutputStream; +import java.io.Writer; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Stream; +import org.apache.polygene.api.common.Optional; + +// TODO QUID Remove Optional? +public interface Serializer +{ + void serialize( Options options, Writer writer, @Optional Object object ); + + void serialize( Options options, OutputStream output, @Optional Object object ); + + void serialize( Writer writer, @Optional Object object ); + + void serialize( OutputStream output, @Optional Object object ); + + String serialize( Options options, @Optional Object object ); + + String serialize( @Optional Object object ); + + <T> Function<T, String> serializeFunction( Options options ); + + <T> Function<T, String> serializeFunction(); + + Stream<String> serializeEach( Options options, Iterable<Object> objects ); + + Stream<String> serializeEach( Iterable<Object> objects ); + + Stream<String> serializeEach( Options options, Object... objects ); + + Stream<String> serializeEach( Object... objects ); + + byte[] toBytes( Options options, @Optional Object object ); + + byte[] toBytes( @Optional Object object ); + + <T> Function<T, byte[]> toBytesFunction( Options options ); + + <T> Function<T, byte[]> toBytesFunction(); + + Stream<byte[]> toBytesEach( Options options, Iterable<Object> objects ); + + Stream<byte[]> toBytesEach( Iterable<Object> objects ); + + Stream<byte[]> toBytesEach( Options options, Object... objects ); + + Stream<byte[]> toBytesEach( Object... objects ); + + /** + * State serializer options. + * + * Use {@link #builder()} to create new instances. + * + * All options provided by the builder are safe to use with all serialization extensions. Serialization extensions + * might provide more options, see {@link #option(String)} and the respective extension documentation. + */ + // TODO rootTypeInfo / nestedTypeInfo + interface Options + { + /** + * Default state serializer options. + * + * {@link #includeTypeInfo()} set to {@literal true}. + */ + Options DEFAULT = builder().build(); + + /** + * Default state serializer options with {@link #includeTypeInfo()} set to {@literal false}. + */ + Options NO_TYPE_INFO = builder().withoutTypeInfo().build(); + + /** + * Include type information in the serialized form of nested values. + * + * Boolean flag to include type information in the serialized form of nested values types. + * Each serialization extension is free to chose how to represent this type information. + * + * This is enabled by default to allow for polymorphic deserialization. + * + * Let's say you have a type hierarchy of values as follows ; + * <code> + * interface Parent { Property<String> something(); } + * interface Child1 { Property<Long> number(); } + * interface Child2 { Property<Duration> duration(); } + * </code> + * and want to serialize and deserialize a set of values like this one ; + * <code> + * interface MyValue { Property<Parent> polymorphicValue(); } + * </code> + * that is a view of a value composite that also has the following fragments ; + * <code> + * interface MyValueWithNumber { Property<Child1> polymorphicValue(); } + * interface MyValueWithDuration { Property<Child2> polymorphicValue(); } + * </code> + * when deserializing, the {@link Deserializer} needs a way to know which specialization + * type to use to deserialize the value state, {@literal Child1} or {@literal Child2} in our example. + * + * If the deserializer can't know it use the type information from the + * {@link org.apache.polygene.api.type.ValueType} provided at deserialization time. + * + * Disable it using {@link Builder#withoutTypeInfo()} if you are sure you don't need this. + * + * @return {@literal true} if type information must be included in the serialized form of nested values, + * {@literal false} otherwise + */ + boolean includeTypeInfo(); + + /** + * Query for an option's value. + * + * @param option the option + * @return the option's value, {@literal} null if absent + */ + String option( String option ); + + /** + * Create a new builder of {@link Options} + * + * @return a new builder + */ + static Builder builder() + { + return new Builder(); + } + + /** + * Builder for {@link Options}. + * + * This builder is mutable, built instances are not. + */ + final class Builder + { + private static final String INCLUDE_TYPE_INFO = "includeTypeInfo"; + + private static class Instance implements Options + { + private final Map<String, String> options; + + private Instance( Map<String, String> options ) + { + this.options = options; + } + + @Override + public boolean includeTypeInfo() + { + return "true".equals( options.get( INCLUDE_TYPE_INFO ) ); + } + + @Override + public String option( String option ) + { + return options.get( option ); + } + } + + private final Map<String, String> options = new HashMap<String, String>() + {{ + put( INCLUDE_TYPE_INFO, "true" ); + }}; + + /** + * Include type information in the serialized form of nested values. + * + * @return this builder + */ + public Builder withTypeInfo() + { + return withOption( INCLUDE_TYPE_INFO, "true" ); + } + + /** + * Do not include type information in the serialized form of nested values. + * + * <strong>WARNING</strong> + * Without this, {@link Deserializer}s will use the provided + * {@link org.apache.polygene.api.type.ValueType} for instantiation potentially breaking polymorphism, + * see {@link Options#includeTypeInfo()}. + * + * @return this builder + * @see Builder#withTypeInfo() + */ + public Builder withoutTypeInfo() + { + return withOption( INCLUDE_TYPE_INFO, "false" ); + } + + /** + * Set extension specific option. + * + * @param option the option to add + * @param value it's value + * @return this builder + */ + public Builder withOption( String option, String value ) + { + options.put( option, value ); + return this; + } + + /** + * Remove extension specific option. + * + * @param option the option to remove + * @return this builder + */ + public Builder withoutOption( String option ) + { + options.remove( option ); + return this; + } + + /** + * Build the options. + * + * @return a new immutable instance of {@link Options}. + */ + public Options build() + { + return new Instance( Collections.unmodifiableMap( options ) ); + } + } + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/serialization/package.html ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/package.html b/core/api/src/main/java/org/apache/polygene/api/serialization/package.html new file mode 100644 index 0000000..fc2a3bd --- /dev/null +++ b/core/api/src/main/java/org/apache/polygene/api/serialization/package.html @@ -0,0 +1,24 @@ +<!-- + ~ 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. + ~ + ~ + --> +<html> +<body> +<h2>Serialization API.</h2> +</body> +</html> http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java b/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java index faf19c5..09a0aeb 100644 --- a/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java +++ b/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java @@ -22,6 +22,7 @@ package org.apache.polygene.api.type; import java.lang.reflect.Type; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Set; import org.apache.polygene.api.util.Classes; @@ -32,27 +33,52 @@ import org.apache.polygene.api.util.Classes; public final class CollectionType extends ValueType { - public static boolean isCollection( Type type ) { Class<?> cl = Classes.RAW_CLASS.apply( type ); - return cl.equals( Collection.class ) || cl.equals( List.class ) || cl.equals( Set.class ); + return Collection.class.isAssignableFrom( cl ); + } + + public static CollectionType of( Class<?> type, ValueType collectedType ) + { + return new CollectionType( type, collectedType ); + } + + public static CollectionType of( Class<?> type, Class<?> collectedType ) + { + return of( type, ValueType.of( collectedType ) ); + } + + public static CollectionType collectionOf( ValueType collectedType ) + { + return of( Collection.class, collectedType ); } public static CollectionType collectionOf( Class<?> collectedType ) { - return new CollectionType( Collection.class, ValueType.of( collectedType ) ); + return of( Collection.class, collectedType ); + } + + public static CollectionType listOf( ValueType collectedType ) + { + return of( List.class, collectedType ); } public static CollectionType listOf( Class<?> collectedType ) { - return new CollectionType( List.class, ValueType.of( collectedType ) ); + return of( List.class, collectedType ); + } + + public static CollectionType setOf( ValueType collectedType ) + { + return of( Set.class, collectedType ); } public static CollectionType setOf( Class<?> collectedType ) { - return new CollectionType( Set.class, ValueType.of( collectedType ) ); + return of( Set.class, collectedType ); } + private ValueType collectedType; public CollectionType( Class<?> type, ValueType collectedType ) @@ -70,6 +96,32 @@ public final class CollectionType return collectedType; } + public boolean isSet() + { + return Set.class.isAssignableFrom( primaryType() ); + } + + public boolean isList() + { + return List.class.isAssignableFrom( primaryType() ); + } + + @Override + public boolean equals( final Object o ) + { + if( this == o ) { return true; } + if( o == null || getClass() != o.getClass() ) { return false; } + if( !super.equals( o ) ) { return false; } + CollectionType that = (CollectionType) o; + return Objects.equals( collectedType, that.collectedType ); + } + + @Override + public int hashCode() + { + return Objects.hash( super.hashCode(), collectedType ); + } + @Override public String toString() { http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java b/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java index ba7dc5a..9ae6feb 100644 --- a/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java +++ b/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java @@ -27,13 +27,12 @@ import java.lang.reflect.Type; public final class EnumType extends ValueType { - public static boolean isEnum( Type type ) { if( type instanceof Class ) { Class<?> typeClass = (Class) type; - return ( typeClass.isEnum() ); + return typeClass.isEnum(); } return false; } @@ -43,7 +42,7 @@ public final class EnumType return new EnumType( type ); } - public EnumType( Class<?> type ) + private EnumType( Class<?> type ) { super( type ); if( !isEnum( type ) ) http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableFromType.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableFromType.java b/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableFromType.java new file mode 100644 index 0000000..bfa7763 --- /dev/null +++ b/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableFromType.java @@ -0,0 +1,33 @@ +package org.apache.polygene.api.type; + +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.function.Predicate; + +import static java.util.stream.Collectors.toList; + +public class HasAssignableFromType<T extends HasTypes> extends HasTypesPredicate<T> +{ + public HasAssignableFromType( Type type ) + { + super( Collections.singletonList( type ) ); + } + + public HasAssignableFromType( T hasTypes ) + { + super( hasTypes.types().collect( toList() ) ); + } + + @Override + protected Predicate<Type> matchPredicate( Type candidate ) + { + // TODO; what to do if there is ParameterizedType here?? + // Now set to ClassCastException and see if anything surfaces + //if( candidate instanceof Class ) + { + Class<?> clazz = (Class<?>) candidate; + return input -> !input.equals( candidate ) && clazz.isAssignableFrom( (Class<?>) input ); + } + //return input -> input.equals( candidate ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableToType.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableToType.java b/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableToType.java new file mode 100644 index 0000000..0a8e3df --- /dev/null +++ b/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableToType.java @@ -0,0 +1,29 @@ +package org.apache.polygene.api.type; + +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.function.Predicate; + +import static java.util.stream.Collectors.toList; + +public class HasAssignableToType<T extends HasTypes> extends HasTypesPredicate<T> +{ + public HasAssignableToType( Type type ) + { + super( Collections.singletonList( type ) ); + } + + public HasAssignableToType( T hasTypes ) + { + super( hasTypes.types().collect( toList() ) ); + } + + @Override + protected Predicate<Type> matchPredicate( Type candidate ) + { + // TODO; what to do if there is ParameterizedType here?? + // Now set to ClassCastException and see if anything surfaces + Class<?> clazz = (Class<?>) candidate; + return input -> !input.equals( candidate ) && ( (Class<?>) input ).isAssignableFrom( clazz ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableFromType.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableFromType.java b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableFromType.java new file mode 100644 index 0000000..190512e --- /dev/null +++ b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableFromType.java @@ -0,0 +1,25 @@ +package org.apache.polygene.api.type; + +import java.lang.reflect.Type; +import java.util.function.Predicate; + +public class HasEqualOrAssignableFromType<T extends HasTypes> implements Predicate<T> +{ + private final Predicate<T> composedPredicate; + + public HasEqualOrAssignableFromType( Type type ) + { + composedPredicate = new HasEqualType<T>( type ).or( new HasAssignableFromType<>( type ) ); + } + + public HasEqualOrAssignableFromType( T hasTypes ) + { + composedPredicate = new HasEqualType<>( hasTypes ).or( new HasAssignableFromType<>( hasTypes ) ); + } + + @Override + public boolean test( T hasTypes ) + { + return composedPredicate.test( hasTypes ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableToType.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableToType.java b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableToType.java new file mode 100644 index 0000000..e54bf35 --- /dev/null +++ b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableToType.java @@ -0,0 +1,25 @@ +package org.apache.polygene.api.type; + +import java.lang.reflect.Type; +import java.util.function.Predicate; + +public class HasEqualOrAssignableToType<T extends HasTypes> implements Predicate<T> +{ + private final Predicate<T> composedPredicate; + + public HasEqualOrAssignableToType( Type type ) + { + composedPredicate = new HasEqualType<T>( type ).or( new HasAssignableToType<>( type ) ); + } + + public HasEqualOrAssignableToType( T hasTypes ) + { + composedPredicate = new HasEqualType<>( hasTypes ).or( new HasAssignableToType<>( hasTypes ) ); + } + + @Override + public boolean test( T hasTypes ) + { + return composedPredicate.test( hasTypes ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/17b11697/core/api/src/main/java/org/apache/polygene/api/type/HasEqualType.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasEqualType.java b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualType.java new file mode 100644 index 0000000..18ebce7 --- /dev/null +++ b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualType.java @@ -0,0 +1,26 @@ +package org.apache.polygene.api.type; + +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.function.Predicate; + +import static java.util.stream.Collectors.toList; + +public class HasEqualType<T extends HasTypes> extends HasTypesPredicate<T> +{ + public HasEqualType( Type type ) + { + super( Collections.singletonList( type ) ); + } + + public HasEqualType( T hasTypes ) + { + super( hasTypes.types().collect( toList() ) ); + } + + @Override + protected Predicate<Type> matchPredicate( Type candidate ) + { + return candidate::equals; + } +}
