You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by ni...@apache.org on 2015/04/17 18:05:35 UTC
[15/50] [abbrv] zest-qi4j git commit: Merge branch
'feature/valueserialization-spi' into develop
Merge branch 'feature/valueserialization-spi' into develop
Conflicts:
core/api/src/main/java/org/qi4j/api/composite/PropertyMapper.java
core/api/src/main/java/org/qi4j/api/json/JSONDeserializer.java
core/api/src/main/java/org/qi4j/api/json/JSONObjectSerializer.java
core/api/src/main/java/org/qi4j/api/json/JSONSerializer.java
core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithPrototype.java
core/runtime/src/main/java/org/qi4j/runtime/value/ValueInstance.java
core/runtime/src/test/java/org/qi4j/runtime/types/JodaDateTimeTypeTest.java
core/runtime/src/test/java/org/qi4j/runtime/types/JodaLocalDateTimeTypeTest.java
core/runtime/src/test/java/org/qi4j/runtime/types/JodaLocalDateTypeTest.java
core/runtime/src/test/java/org/qi4j/runtime/value/CollectionTypeTest.java
core/spi/src/docs/spi.txt
core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONEntityState.java
extensions/entitystore-gae/src/main/java/org/qi4j/entitystore/gae/GaeEntityState.java
extensions/entitystore-neo4j/src/main/java/org/qi4j/entitystore/neo4j/NeoEntityState.java
extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/PreferencesEntityStoreMixin.java
extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchIndexer.java
extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/RdfQueryParserImpl2.java
libraries/rdf/src/main/java/org/qi4j/library/rdf/entity/EntityStateSerializer.java
libraries/rest-client/src/main/java/org/qi4j/library/rest/client/requestwriter/ValueCompositeRequestWriter.java
libraries/rest/src/main/java/org/qi4j/library/rest/admin/EntityResource.java
samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/JSONModel.java
samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/JSONModel.java
Project: http://git-wip-us.apache.org/repos/asf/zest-qi4j/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-qi4j/commit/e2ea757e
Tree: http://git-wip-us.apache.org/repos/asf/zest-qi4j/tree/e2ea757e
Diff: http://git-wip-us.apache.org/repos/asf/zest-qi4j/diff/e2ea757e
Branch: refs/heads/master
Commit: e2ea757e55ca76702d92b5cfeb62247b9bc6bb41
Parents: 59959ca e428fa9
Author: Paul Merlin <pa...@nosphere.org>
Authored: Wed Feb 13 11:47:48 2013 +0100
Committer: Paul Merlin <pa...@nosphere.org>
Committed: Wed Feb 13 11:47:48 2013 +0100
----------------------------------------------------------------------
build.gradle | 2 +-
core/api/build.gradle | 1 +
core/api/src/docs/valuecomposite.txt | 121 +-
core/api/src/main/java/org/json/JSONArray.java | 1195 -----------
.../src/main/java/org/json/JSONException.java | 45 -
core/api/src/main/java/org/json/JSONObject.java | 1904 ------------------
core/api/src/main/java/org/json/JSONString.java | 34 -
.../src/main/java/org/json/JSONStringer.java | 95 -
.../api/src/main/java/org/json/JSONTokener.java | 501 -----
core/api/src/main/java/org/json/JSONWriter.java | 429 ----
core/api/src/main/java/org/json/package.html | 8 -
.../org/qi4j/api/composite/PropertyMapper.java | 3 +-
.../java/org/qi4j/api/json/Base64Encoder.java | 224 ---
.../org/qi4j/api/json/JSONDeserializer.java | 528 -----
.../org/qi4j/api/json/JSONObjectSerializer.java | 92 -
.../java/org/qi4j/api/json/JSONSerializer.java | 335 ---
.../org/qi4j/api/json/JSONWriterSerializer.java | 83 -
.../main/java/org/qi4j/api/json/package.html | 5 -
.../java/org/qi4j/api/type/CollectionType.java | 22 +-
.../main/java/org/qi4j/api/type/EnumType.java | 13 +-
.../main/java/org/qi4j/api/type/MapType.java | 16 +-
.../main/java/org/qi4j/api/type/ValueType.java | 97 +-
.../java/org/qi4j/api/util/Base64Encoder.java | 224 +++
.../org/qi4j/api/value/ValueBuilderFactory.java | 6 +-
.../org/qi4j/api/value/ValueDeserializer.java | 151 ++
.../org/qi4j/api/value/ValueSerialization.java | 48 +
.../api/value/ValueSerializationException.java | 46 +
.../org/qi4j/api/value/ValueSerializer.java | 129 ++
.../api/configuration/ConfigurationTest.java | 4 +-
.../DeclareConfigurationDefaultsTest.java | 7 +-
.../dataset/iterable/IterableDataSetTest.java | 2 +-
.../api/injection/scope/StateFieldTest.java | 5 +-
.../qi4j/api/property/PropertyErrorTest.java | 5 +-
.../org/qi4j/api/unitofwork/RemovalTest.java | 7 +-
.../qi4j/api/value/DocumentationSupport.java | 298 +++
.../org/qi4j/api/value/ValueCompositeTest.java | 2 +-
core/io/src/main/java/org/qi4j/io/Inputs.java | 74 +
.../qi4j/runtime/structure/ModuleInstance.java | 41 +-
.../value/ValueBuilderWithPrototype.java | 40 +-
.../org/qi4j/runtime/value/ValueInstance.java | 28 +-
.../java/org/qi4j/api/common/OptionalTest.java | 6 +-
.../org/qi4j/api/common/PropertyErrorTest.java | 5 +-
.../org/qi4j/api/common/PropertyTypeTest.java | 5 +-
.../java/org/qi4j/api/common/RemovalTest.java | 7 +-
.../common/UnitOfWorkCallbackEntityTest.java | 5 +-
.../org/qi4j/runtime/entity/AggregatedTest.java | 5 +-
.../entity/EntityCompositeEqualityTest.java | 6 +-
.../qi4j/runtime/entity/EntityCreationTest.java | 5 +-
.../org/qi4j/runtime/entity/EntityTypeTest.java | 4 +-
.../runtime/entity/EntityVisibilityTest.java | 8 +-
.../java/org/qi4j/runtime/entity/QI273Test.java | 5 +-
.../entity/associations/AssociationTest.java | 5 +-
.../associations/ImmutableAssociationTest.java | 5 +-
.../IllegalUnitOfWorkInjectionTest.java | 4 +-
.../injection/UnitOfWorkInjectionTest.java | 4 +-
.../ServiceInstantiationTests.java | 4 +-
.../instantiation/ValueInstantiationTests.java | 4 +-
.../org/qi4j/runtime/mixin/JDKMixinTest.java | 38 +-
.../runtime/objects/ObjectVisibilityTest.java | 10 +-
.../qi4j/runtime/service/ConfigurationTest.java | 5 +-
.../runtime/service/ServiceVisibilityTest.java | 6 +-
.../transients/TransientVisibilityTest.java | 6 +-
.../runtime/types/JodaDateTimeTypeTest.java | 41 -
.../types/JodaLocalDateTimeTypeTest.java | 41 -
.../runtime/types/JodaLocalDateTypeTest.java | 40 -
.../org/qi4j/runtime/types/ValueLookupTest.java | 69 -
.../qi4j/runtime/unitofwork/RemovalTest.java | 4 +-
.../qi4j/runtime/value/CollectionTypeTest.java | 443 ----
.../ValueInjectionDeserializationTest.java | 5 +-
.../value/ValueTypeSerializationTest.java | 315 ---
.../qi4j/runtime/value/ValueVisibilityTest.java | 6 +-
.../memory/MemoryEntityStoreTest.java | 3 +
core/spi/build.gradle | 8 +-
core/spi/src/docs/metrics.txt | 2 +-
core/spi/src/docs/spi.txt | 9 +-
core/spi/src/docs/valueserialization.txt | 52 +
.../entitystore/helpers/JSONEntityState.java | 96 +-
.../helpers/JSONManyAssociationState.java | 99 +-
.../helpers/JSONMapEntityStoreMixin.java | 31 +-
.../helpers/MapEntityStoreMixin.java | 36 +-
.../spi/value/ValueDeserializerAdapter.java | 1042 ++++++++++
.../qi4j/spi/value/ValueSerializerAdapter.java | 519 +++++
.../main/java/org/qi4j/spi/value/package.html | 5 +
.../orgjson/OrgJsonValueDeserializer.java | 452 +++++
.../orgjson/OrgJsonValueSerialization.java | 144 ++
.../OrgJsonValueSerializationService.java | 28 +
.../orgjson/OrgJsonValueSerializer.java | 112 ++
.../valueserialization/orgjson/package.html | 5 +
.../helpers/JSONManyAssociationStateTest.java | 137 ++
core/spi/src/test/resources/logback-test.xml | 16 +
.../java/org/qi4j/test/EntityTestAssembler.java | 4 +-
.../java/org/qi4j/test/util/JSONAssert.java | 63 +-
.../AbstractCollectionSerializationTest.java | 416 ++++
.../test/value/AbstractJsonDateFormatTest.java | 88 +
.../AbstractPlainValueSerializationTest.java | 208 ++
...AbstractValueCompositeSerializationTest.java | 408 ++++
.../main/java/org/qi4j/test/value/package.html | 5 +
.../org/qi4j/cache/ehcache/EhCacheTest.java | 6 +-
extensions/entitystore-file/build.gradle | 17 +-
.../file/assembly/FileEntityStoreAssembler.java | 6 +
.../entitystore/file/FileEntityStoreTest.java | 14 +-
.../qi4j/entitystore/gae/GaeEntityState.java | 57 +-
.../entitystore/gae/GaeEntityStoreMixin.java | 19 +-
.../gae/GaeEntityStoreUnitOfWork.java | 27 +-
extensions/entitystore-hazelcast/build.gradle | 22 +-
.../assembly/HazelcastEntityStoreAssembler.java | 10 +-
.../hazelcast/HazelcastEntityStoreTest.java | 17 +-
extensions/entitystore-jclouds/build.gradle | 19 +-
.../jclouds/JCloudsMapEntityStoreAssembler.java | 14 +-
.../jclouds/JCloudsFilesystemTest.java | 11 +-
.../jclouds/JCloudsTransientTest.java | 6 +-
extensions/entitystore-jdbm/build.gradle | 1 +
.../jdbm/assembly/JdbmEntityStoreAssembler.java | 25 +-
.../entitystore/jdbm/JdbmEntityStoreTest.java | 93 +-
extensions/entitystore-leveldb/build.gradle | 1 +
.../leveldb/LevelDBEntityStoreAssembler.java | 1 -
.../leveldb/JavaLevelDBEntityStoreTest.java | 4 +-
.../leveldb/JniLevelDBEntityStoreTest.java | 3 +-
extensions/entitystore-mongodb/build.gradle | 3 +
.../mongodb/MongoEntityStoreConfiguration.java | 2 +-
.../mongodb/MongoMapEntityStoreAssembler.java | 39 +-
.../mongodb/MongoMapEntityStoreMixin.java | 11 -
.../mongodb/MongoMapEntityStoreTest.java | 14 +-
extensions/entitystore-neo4j/build.gradle | 1 +
.../qi4j/entitystore/neo4j/NeoEntityState.java | 100 +-
.../entitystore/neo4j/NeoEntityStoreMixin.java | 11 +-
.../neo4j/NeoEntityStoreUnitOfWork.java | 9 +-
.../neo4j/test/SimpleNeoStoreTest.java | 40 +-
extensions/entitystore-preferences/build.gradle | 11 +-
.../prefs/PreferencesEntityStoreMixin.java | 62 +-
.../PreferenceEntityStoreAssembler.java | 1 +
.../entitystore/PreferencesEntityStoreTest.java | 11 +-
extensions/entitystore-redis/build.gradle | 15 +-
.../redis/RedisMapEntityStoreAssembler.java | 1 -
.../redis/RedisMapEntityStoreTest.java | 23 +-
extensions/entitystore-riak/build.gradle | 19 +-
.../riak/RiakHttpMapEntityStoreAssembler.java | 1 -
.../RiakProtobufMapEntityStoreAssembler.java | 1 -
.../riak/RiakHttpMapEntityStoreTest.java | 20 +-
.../riak/RiakProtobufMapEntityStoreTest.java | 20 +-
extensions/entitystore-sql/build.gradle | 1 +
.../entitystore/sql/SQLEntityStoreMixin.java | 33 +-
.../AbstractSQLEntityStoreAssembler.java | 58 +-
.../sql/DerbySQLEntityStoreTest.java | 6 +-
.../entitystore/sql/H2SQLEntityStoreTest.java | 6 +-
.../entitystore/sql/MySQLEntityStoreTest.java | 6 +-
.../sql/PostgreSQLEntityStoreTest.java | 6 +-
.../entitystore/sql/SQLiteEntityStoreTest.java | 6 +-
extensions/entitystore-voldemort/build.gradle | 40 +-
.../voldemort/assembly/VoldemortAssembler.java | 9 +-
.../entitystore/voldemort/VoldemortTest.java | 17 +-
.../elasticsearch/ElasticSearchIndexer.java | 210 +-
.../assembly/ESClusterIndexQueryAssembler.java | 5 +
.../ESFilesystemIndexQueryAssembler.java | 5 +
.../assembly/ESMemoryIndexQueryAssembler.java | 5 +
.../ElasticSearchComplexQueryTest.java | 4 +-
.../elasticsearch/ElasticSearchFinderTest.java | 4 +-
.../elasticsearch/ElasticSearchQueryTest.java | 4 +-
.../index/elasticsearch/ElasticSearchTest.java | 3 +-
.../src/test/resources/logback-test.xml | 16 +
extensions/indexing-rdf/build.gradle | 21 +-
.../rdf/assembly/RdfMemoryStoreAssembler.java | 3 +
.../assembly/RdfNativeSesameStoreAssembler.java | 3 +
.../assembly/RdfRdbmsSesameStoreAssembler.java | 3 +
.../index/rdf/query/RdfQueryParserFactory.java | 9 +-
.../rdf/query/internal/RdfQueryParserImpl2.java | 155 +-
.../org/qi4j/index/rdf/ContainsAllTest.java | 3 +-
.../java/org/qi4j/index/rdf/ContainsTest.java | 51 +-
.../org/qi4j/index/rdf/RDFPerformanceTest.java | 3 +-
.../org/qi4j/index/rdf/RdfComplexQueryTest.java | 5 +-
.../org/qi4j/index/rdf/RdfEntityFinderTest.java | 3 +
.../org/qi4j/index/rdf/RdfNamedQueryTest.java | 3 +
.../java/org/qi4j/index/rdf/RdfQueryTest.java | 7 +-
.../qi4j/index/rdf/qi64/AbstractIssueTest.java | 8 +-
.../org/qi4j/index/rdf/qi66/Qi66IssueTest.java | 6 +-
.../org/qi4j/index/rdf/qi95/Qi95IssueTest.java | 13 +-
.../java/org/qi4j/index/solr/SolrAssembler.java | 4 +-
.../index/sql/postgresql/SQLTestHelper.java | 8 +-
.../metrics/yammer/NoMetricsInstalledTest.java | 4 +-
.../org/qi4j/metrics/yammer/YammerTest.java | 10 +-
.../org/qi4j/index/reindexer/ReindexerTest.java | 4 +-
.../valueserialization-jackson/build.gradle | 17 +
.../valueserialization-jackson/dev-status.xml | 17 +
.../src/docs/vs-jackson.txt | 24 +
.../jackson/JacksonValueDeserializer.java | 348 ++++
.../JacksonValueSerializationAssembler.java | 67 +
.../JacksonValueSerializationService.java | 28 +
.../jackson/JacksonValueSerializer.java | 88 +
.../valueserialization/jackson/package.html | 5 +
.../JacksonCollectionSerializationTest.java | 33 +
.../jackson/JacksonJsonDateFormatTest.java | 33 +
.../JacksonPlainValueSerializationTest.java | 34 +
.../JacksonValueCompositeSerializationTest.java | 33 +
.../src/test/resources/logback-test.xml | 18 +
.../valueserialization-orgjson/build.gradle | 15 +
.../valueserialization-orgjson/dev-status.xml | 17 +
.../src/docs/vs-orgjson.txt | 24 +
.../OrgJsonValueSerializationAssembler.java | 67 +
.../valueserialization/orgjson/package.html | 5 +
.../OrgJsonCollectionSerializationTest.java | 33 +
.../orgjson/OrgJsonDateFormatTest.java | 33 +
.../OrgJsonPlainValueSerializationTest.java | 34 +
.../OrgJsonValueCompositeSerializationTest.java | 33 +
extensions/valueserialization-stax/build.gradle | 16 +
.../valueserialization-stax/dev-status.xml | 17 +
.../src/docs/vs-stax.txt | 24 +
.../stax/StaxValueDeserializer.java | 463 +++++
.../stax/StaxValueSerializationAssembler.java | 67 +
.../stax/StaxValueSerializationService.java | 28 +
.../stax/StaxValueSerializer.java | 130 ++
.../qi4j/valueserialization/stax/package.html | 5 +
.../stax/StaxCollectionSerializationTest.java | 33 +
.../stax/StaxPlainValueSerializationTest.java | 34 +
.../StaxValueCompositeSerializationTest.java | 33 +
.../src/test/resources/logback-test.xml | 19 +
libraries.gradle | 4 +
.../library/alarm/AlarmHistoryImplTest.java | 6 +-
.../qi4j/library/alarm/AlarmPointImplTest.java | 6 +-
.../org/qi4j/library/alarm/AlarmProxyTest.java | 6 +-
.../qi4j/library/alarm/AlarmServiceTest.java | 6 +-
.../library/alarm/ExtendedAlarmModelTest.java | 8 +-
.../library/alarm/SimpleAlarmModelTest.java | 6 +-
.../library/alarm/StandardAlarmModelTest.java | 6 +-
.../conversion/values/EntityToValueTest.java | 4 +-
libraries/eventsourcing-jdbm/build.gradle | 1 +
.../source/jdbm/JdbmEventStoreService.java | 46 +-
.../source/jdbm/JdbmEventStoreServiceTest.java | 13 +-
.../replay/ApplicationEventPlayerService.java | 3 +-
.../domain/replay/DomainEventPlayerService.java | 3 +-
.../domain/source/AbstractEventStoreMixin.java | 5 -
.../library/http/JettyJMXStatisticsTest.java | 4 +-
.../org/qi4j/library/http/JettyServiceTest.java | 4 +-
.../http/MutualSecureJettyServiceTest.java | 4 +-
.../library/http/SecureJettyServiceTest.java | 4 +-
.../http/VirtualHostJettyServiceTest.java | 4 +-
.../java/org/qi4j/logging/DebuggingTest.java | 4 +-
.../test/java/org/qi4j/logging/TracingTest.java | 6 +-
libraries/rdf/build.gradle | 1 +
.../rdf/entity/EntityStateSerializer.java | 59 +-
.../rdf/entity/EntitySerializerTest.java | 9 +-
.../rdf/entity/EntityTypeSerializerTest.java | 4 +-
.../rdf/repository/NativeRepositoryTest.java | 4 +-
libraries/rest-client/build.gradle | 17 +-
.../ValueCompositeRequestWriter.java | 43 +-
.../responsereader/JSONResponseReader.java | 19 +-
.../ContextResourceClientFactoryTest.java | 18 +-
.../rest/client/ContinuousIntegrationTest.java | 7 +-
.../qi4j/library/rest/client/RssReaderTest.java | 3 +-
.../requestreader/DefaultRequestReader.java | 22 +-
.../ValueCompositeResponseWriter.java | 10 +-
.../ValueDescriptorResponseWriter.java | 2 +-
libraries/rest/build.gradle | 27 +-
.../library/rest/admin/EntitiesResource.java | 60 +-
.../qi4j/library/rest/admin/EntityResource.java | 264 +--
.../library/rest/admin/RestApplication.java | 4 +-
.../qi4j/library/rest/admin/RDFAssembler.java | 2 +
.../org/qi4j/library/rest/admin/RestTest.java | 159 +-
.../rest/admin/RestletApplicationAssembler.java | 36 -
.../library/shiro/web/WebHttpShiroTest.java | 4 +-
.../library/shiro/web/WebRealmServiceTest.java | 4 +-
libraries/sql-liquibase/build.gradle | 3 +-
.../sql/liquibase/LiquibaseServiceTest.java | 4 +-
...taSourceConfigurationManagerServiceTest.java | 6 +-
manual/src/docs/userguide/extensions.txt | 13 +
samples/dci-cargo/dcisample_a/build.gradle | 1 +
.../sample_a/bootstrap/assembly/Assembler.java | 26 +-
.../data/shipping/cargo/RouteSpecification.java | 5 +-
.../data/shipping/delivery/Delivery.java | 7 +-
.../delivery/ExpectedHandlingEvent.java | 5 +-
.../sample_a/data/shipping/itinerary/Leg.java | 7 +-
.../data/shipping/voyage/CarrierMovement.java | 5 +-
.../infrastructure/model/JSONModel.java | 18 +-
.../sample_a/bootstrap/test/TestAssembler.java | 20 +-
samples/dci-cargo/dcisample_b/build.gradle | 1 +
.../sample_b/bootstrap/assembly/Assembler.java | 25 +-
.../structure/cargo/RouteSpecification.java | 5 +-
.../data/structure/delivery/Delivery.java | 3 +-
.../structure/delivery/NextHandlingEvent.java | 5 +-
.../sample_b/data/structure/itinerary/Leg.java | 15 +-
.../infrastructure/model/JSONModel.java | 18 +-
.../bootstrap/test/TestApplication.java | 7 +
.../sample_b/bootstrap/test/TestAssembler.java | 26 +-
.../context/test/booking/BookNewCargoTest.java | 27 +-
.../moneytransfer/test/TransferMoneyTest.java | 7 +-
.../moneytransfer/test/TransferMoneyTest2.java | 7 +-
.../qi4j/samples/forum/data/entity/User.java | 2 +-
settings.gradle | 3 +
tests/performance/build.gradle | 27 +-
.../MemoryEntityStorePerformanceTest.java | 5 +
.../tests/regression/qi328/Qi328TestCase.java | 6 +-
.../tutorials/services/step4/LibraryTest.java | 6 +-
.../tutorials/services/step5/LibraryTest.java | 6 +-
.../tutorials/services/step6/LibraryTest.java | 6 +-
293 files changed, 8583 insertions(+), 8082 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e2ea757e/core/api/src/main/java/org/qi4j/api/composite/PropertyMapper.java
----------------------------------------------------------------------
diff --cc core/api/src/main/java/org/qi4j/api/composite/PropertyMapper.java
index d51fd0e,06831bc..50ab2a4
--- a/core/api/src/main/java/org/qi4j/api/composite/PropertyMapper.java
+++ b/core/api/src/main/java/org/qi4j/api/composite/PropertyMapper.java
@@@ -457,8 -457,7 +457,7 @@@ public final class PropertyMappe
@Override
public Object map( Composite composite, Type type, String value )
{
- return Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF
- .map( composite ).module().newValueFromJSON( (Class<Object>) type, value );
- return Qi4j.INSTANCE_FUNCTION.map( composite ).module().newValueFromSerializedState( (Class<Object>) type, value );
++ return Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( composite ).module().newValueFromSerializedState( (Class<Object>) type, value );
}
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e2ea757e/core/api/src/main/java/org/qi4j/api/type/MapType.java
----------------------------------------------------------------------
diff --cc core/api/src/main/java/org/qi4j/api/type/MapType.java
index 047b3ae,546fada..c90690f
--- a/core/api/src/main/java/org/qi4j/api/type/MapType.java
+++ b/core/api/src/main/java/org/qi4j/api/type/MapType.java
@@@ -34,14 -33,23 +33,23 @@@ public final class MapTyp
return Map.class.isAssignableFrom( cl );
}
+ public static MapType of( Class<?> keyType, Class<?> valueType )
+ {
+ return new MapType( Map.class, ValueType.of( keyType ), ValueType.of( valueType ) );
+ }
+
public MapType( Class<?> type, ValueType keyType, ValueType valueType )
{
- super( Iterables.iterable( type ) );
+ super( type );
this.keyType = keyType;
this.valueType = valueType;
+ if( !isMap( type ) )
+ {
+ throw new IllegalArgumentException( type + " is not a Map." );
+ }
}
- public ValueType getKeyType()
+ public ValueType keyType()
{
return keyType;
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e2ea757e/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleInstance.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e2ea757e/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithPrototype.java
----------------------------------------------------------------------
diff --cc core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithPrototype.java
index fe9ef6b,34a8b43..0608ace
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithPrototype.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithPrototype.java
@@@ -27,19 -46,16 +46,16 @@@ public class ValueBuilderWithPrototype<
try
{
// @TODO there is probably a more efficient way to do this
- JSONObjectSerializer serializer = new JSONObjectSerializer();
- serializer.serialize(prototype, valueModel.valueType());
- Object object = serializer.rootObject();
-
- JSONDeserializer deserializer = new JSONDeserializer( currentModule );
- value = deserializer.deserialize(object, valueModel.valueType());
+ ValueSerialization valueSerialization = currentModule.valueSerialization();
+ String serialized = valueSerialization.serialize( prototype );
+ value = valueSerialization.deserialize( valueModel.valueType(), serialized);
}
- catch( JSONException e )
+ catch( ValueSerializationException e )
{
- throw new IllegalStateException( "Could not JSON-copy Value", e );
+ throw new IllegalStateException( "Could not serialize-copy Value", e );
}
- ValueInstance valueInstance = ValueInstance.getValueInstance( (ValueComposite) value );
+ ValueInstance valueInstance = ValueInstance.valueInstanceOf( (ValueComposite) value );
valueInstance.prepareToBuild();
this.prototypeInstance = valueInstance;
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e2ea757e/core/runtime/src/main/java/org/qi4j/runtime/value/ValueInstance.java
----------------------------------------------------------------------
diff --cc core/runtime/src/main/java/org/qi4j/runtime/value/ValueInstance.java
index 558eadf,8ad7a37..a68d108
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueInstance.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueInstance.java
@@@ -33,10 -30,12 +30,11 @@@ import org.qi4j.runtime.structure.Modul
/**
* ValueComposite instance
*/
- public final class ValueInstance extends TransientInstance
+ public final class ValueInstance
+ extends TransientInstance
implements CompositeInstance, MixinsInstance
{
-
- public static ValueInstance getValueInstance( ValueComposite composite )
+ public static ValueInstance valueInstanceOf( ValueComposite composite )
{
return (ValueInstance) Proxy.getInvocationHandler( composite );
}
@@@ -144,15 -142,6 +141,6 @@@
@Override
public String toString()
{
- StringWriter string = new StringWriter();
- try
- {
- new JSONWriterSerializer( string ).serialize( this.<ValueComposite>proxy() );
- }
- catch( JSONException e )
- {
- throw new IllegalStateException( "Could not JSON serialize value", e );
- }
- return string.toString();
+ return module().valueSerialization().serialize( this.<ValueComposite>proxy() );
}
--}
++}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e2ea757e/core/spi/src/docs/spi.txt
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e2ea757e/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONEntityState.java
----------------------------------------------------------------------
diff --cc core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONEntityState.java
index 33ef878,5d61190..aed4d7d
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONEntityState.java
+++ b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONEntityState.java
@@@ -128,9 -136,7 +136,7 @@@ public final class JSONEntityStat
}
else
{
- Module module = unitOfWork.module();
- PropertyDescriptor descriptor = entityDescriptor.state().getPropertyByQualifiedName( stateName );
+ PropertyDescriptor descriptor = entityDescriptor.state().findPropertyModelByQualifiedName( stateName );
-
if( descriptor == null )
{
return null;
@@@ -315,4 -333,4 +333,4 @@@
throw new EntityStoreException( e );
}
}
--}
++}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e2ea757e/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e2ea757e/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/MapEntityStoreMixin.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e2ea757e/core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java
----------------------------------------------------------------------
diff --cc core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java
index 0000000,f27dd5b..e5285fc
mode 000000,100644..100644
--- a/core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java
+++ b/core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java
@@@ -1,0 -1,1042 +1,1042 @@@
+ /*
+ * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2010, Niclas Hehdman. All Rights Reserved.
+ * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ *
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package org.qi4j.spi.value;
+
+ import java.io.ByteArrayInputStream;
+ import java.io.InputStream;
+ import java.io.ObjectInputStream;
+ import java.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.util.ArrayList;
+ import java.util.Collection;
+ import java.util.Collections;
+ import java.util.Date;
+ import java.util.HashMap;
+ import java.util.LinkedHashSet;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Scanner;
+ import java.util.Set;
+ import org.joda.time.DateTime;
+ import org.joda.time.DateTimeZone;
+ import org.joda.time.LocalDate;
+ import org.joda.time.LocalDateTime;
+ import org.qi4j.api.association.AssociationDescriptor;
+ import org.qi4j.api.entity.EntityReference;
+ import org.qi4j.api.injection.scope.Service;
+ import org.qi4j.api.injection.scope.Structure;
+ import org.qi4j.api.property.PropertyDescriptor;
+ import org.qi4j.api.service.ServiceReference;
+ import org.qi4j.api.structure.Application;
+ import org.qi4j.api.structure.Module;
+ import org.qi4j.api.type.CollectionType;
+ import org.qi4j.api.type.EnumType;
+ import org.qi4j.api.type.MapType;
+ import org.qi4j.api.type.ValueCompositeType;
+ import org.qi4j.api.type.ValueType;
+ import org.qi4j.api.util.Base64Encoder;
+ import org.qi4j.api.util.Dates;
+ import org.qi4j.api.value.ValueBuilder;
+ import org.qi4j.api.value.ValueDescriptor;
+ import org.qi4j.api.value.ValueDeserializer;
+ import org.qi4j.api.value.ValueSerializationException;
+ import org.qi4j.functional.Function;
+ import org.qi4j.functional.Function2;
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
+
+ import static org.qi4j.functional.Iterables.*;
+
+ /**
+ * Adapter for pull-parsing and tree-parsing capable ValueDeserializers.
+ *
+ * <p>
+ * Among Plain values (see {@link ValueDeserializer}) some are considered primitives to underlying serialization
+ * mechanisms and by so handed/come without conversion to/from implementations. Primitive values can be one of:
+ * </p>
+ * <ul>
+ * <li>String,</li>
+ * <li>Boolean or boolean,</li>
+ * <li>Integer or int,</li>
+ * <li>Long or long,</li>
+ * <li>Short or short,</li>
+ * <li>Byte or byte,</li>
+ * <li>Float or float,</li>
+ * <li>Double or double.</li>
+ * </ul>
+ *
+ * @param <InputType> Implementor pull-parser type
+ * @param <InputNodeType> Implementor tree-parser node type
+ */
+ public abstract class ValueDeserializerAdapter<InputType, InputNodeType>
+ implements ValueDeserializer
+ {
+
+ private static final Logger LOG = LoggerFactory.getLogger( ValueDeserializerAdapter.class );
+ private static final Logger PULL_PARSING_LOG = LoggerFactory.getLogger( ValueDeserializerAdapter.class.getName() + "#PullParsing" );
+ private static final Logger TREE_PARSING_LOG = LoggerFactory.getLogger( ValueDeserializerAdapter.class.getName() + "#TreeParsing" );
+ private static final String UTF_8 = "UTF-8";
+ private final Map<Class<?>, Function<Object, Object>> deserializers = new HashMap<Class<?>, Function<Object, Object>>();
+ private final Application application;
+ private final Module module;
+ private Function<Application, Module> valuesModuleFinder;
+ private Module valuesModule;
+
+ /**
+ * Register a Plain Value type deserialization Function.
+ *
+ * @param <T> Plain Value parametrized Type
+ * @param type Plain Value Type
+ * @param deserializer Deserialization Function
+ */
+ @SuppressWarnings( "unchecked" )
+ protected final <T> void registerDeserializer( Class<T> type, Function<Object, T> deserializer )
+ {
+ deserializers.put( type, (Function<Object, Object>) deserializer );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public ValueDeserializerAdapter( @Structure Application application,
+ @Structure Module module,
+ @Service ServiceReference<ValueDeserializer> serviceRef )
+ {
+ this( application, module, serviceRef.metaInfo( Function.class ) );
+ }
+
+ protected ValueDeserializerAdapter( Application application,
+ Module module,
+ Function<Application, Module> valuesModuleFinder )
+ {
+
+ this.application = application;
+ this.module = module;
+ setValuesModuleFinder( valuesModuleFinder );
+
+ // Primitive Value types
+ registerDeserializer( String.class, new Function<Object, String>()
+ {
+ @Override
+ public String map( Object input )
+ {
+ return input.toString();
+ }
+ } );
+ registerDeserializer( Boolean.class, new Function<Object, Boolean>()
+ {
+ @Override
+ public Boolean map( Object input )
+ {
+ return ( input instanceof String )
+ ? Boolean.parseBoolean( (String) input )
+ : ( (Boolean) input ).booleanValue();
+ }
+ } );
+ registerDeserializer( Integer.class, new Function<Object, Integer>()
+ {
+ @Override
+ public Integer map( Object input )
+ {
+ return ( input instanceof String )
+ ? Integer.parseInt( (String) input )
+ : ( (Number) input ).intValue();
+ }
+ } );
+ registerDeserializer( Long.class, new Function<Object, Long>()
+ {
+ @Override
+ public Long map( Object input )
+ {
+ return ( input instanceof String )
+ ? Long.parseLong( (String) input )
+ : ( (Number) input ).longValue();
+ }
+ } );
+ registerDeserializer( Short.class, new Function<Object, Short>()
+ {
+ @Override
+ public Short map( Object input )
+ {
+ return ( input instanceof String )
+ ? Short.parseShort( (String) input )
+ : ( (Number) input ).shortValue();
+ }
+ } );
+ registerDeserializer( Byte.class, new Function<Object, Byte>()
+ {
+ @Override
+ public Byte map( Object input )
+ {
+ return ( input instanceof String )
+ ? Byte.parseByte( (String) input )
+ : ( (Number) input ).byteValue();
+ }
+ } );
+ registerDeserializer( Float.class, new Function<Object, Float>()
+ {
+ @Override
+ public Float map( Object input )
+ {
+ return ( input instanceof String )
+ ? Float.parseFloat( (String) input )
+ : ( (Number) input ).floatValue();
+ }
+ } );
+ registerDeserializer( Double.class, new Function<Object, Double>()
+ {
+ @Override
+ public Double map( Object input )
+ {
+ return ( input instanceof String )
+ ? Double.parseDouble( (String) input )
+ : ( (Number) input ).doubleValue();
+ }
+ } );
+
+ // Number types
+ registerDeserializer( BigDecimal.class, new Function<Object, BigDecimal>()
+ {
+ @Override
+ public BigDecimal map( Object input )
+ {
+ return new BigDecimal( input.toString() );
+ }
+ } );
+ registerDeserializer( BigInteger.class, new Function<Object, BigInteger>()
+ {
+ @Override
+ public BigInteger map( Object input )
+ {
+ return new BigInteger( input.toString() );
+ }
+ } );
+
+ // Date types
+ registerDeserializer( Date.class, new Function<Object, Date>()
+ {
+ @Override
+ public Date map( Object input )
+ {
+ return Dates.fromString( input.toString() );
+ }
+ } );
+ registerDeserializer( DateTime.class, new Function<Object, DateTime>()
+ {
+ @Override
+ public DateTime map( Object input )
+ {
+ return new DateTime( input, DateTimeZone.UTC );
+ }
+ } );
+ registerDeserializer( LocalDateTime.class, new Function<Object, LocalDateTime>()
+ {
+ @Override
+ public LocalDateTime map( Object input )
+ {
+ return new LocalDateTime( input );
+ }
+ } );
+ registerDeserializer( LocalDate.class, new Function<Object, LocalDate>()
+ {
+ @Override
+ public LocalDate map( Object input )
+ {
+ return new LocalDate( input );
+ }
+ } );
+
+ // Other supported types
+ registerDeserializer( EntityReference.class, new Function<Object, EntityReference>()
+ {
+ @Override
+ public EntityReference map( Object input )
+ {
+ return EntityReference.parseEntityReference( input.toString() );
+ }
+ } );
+ }
+
+ private void setValuesModuleFinder( Function<Application, Module> valuesModuleFinder )
+ {
+ if( valuesModuleFinder != null )
+ {
+ LOG.debug( "Will use the provided Function to find Module to build new ValueComposites instances: {}",
+ valuesModuleFinder );
+ }
+ this.valuesModuleFinder = valuesModuleFinder;
+ this.valuesModule = null;
+ }
+
+ private Module valuesModule()
+ {
+ if( valuesModule == null )
+ {
+ if( valuesModuleFinder == null )
+ {
+ valuesModule = module;
+ }
+ else
+ {
+ valuesModule = valuesModuleFinder.map( application );
+ if( valuesModule == null )
+ {
+ throw new ValueSerializationException( "Values Module provided by the finder Function was null." );
+ }
+ LOG.debug( "Will use a specific Module to build new ValueComposites instances: {}", valuesModule );
+ }
+ }
+ return valuesModule;
+ }
+
+ @Override
+ public <T> Function<String, T> deserialize( Class<T> type )
+ {
+ if( CollectionType.isCollection( type ) )
+ {
+ ValueType objectValueType = new ValueType( Object.class );
+ return deserialize( new CollectionType( type, objectValueType ) );
+ }
+ if( MapType.isMap( type ) )
+ {
+ ValueType objectValueType = new ValueType( Object.class );
+ return deserialize( new MapType( type, objectValueType, objectValueType ) );
+ }
+ return deserialize( new ValueType( type ) );
+ }
+
+ @Override
+ public final <T> Function<String, T> deserialize( final ValueType valueType )
+ {
+ return new Function<String, T>()
+ {
+ @Override
+ public T map( String input )
+ {
+ return deserialize( valueType, input );
+ }
+ };
+ }
+
+ @Override
+ public final <T> Function2<ValueType, String, T> deserialize()
+ {
+ return new Function2<ValueType, String, T>()
+ {
+ @Override
+ public T map( ValueType valueType, String input )
+ {
+ return deserialize( valueType, input );
+ }
+ };
+ }
+
+ @Override
+ public final <T> T deserialize( Class<?> type, String input )
+ throws ValueSerializationException
+ {
+ if( CollectionType.isCollection( type ) )
+ {
+ ValueType objectValueType = new ValueType( Object.class );
+ return deserialize( new CollectionType( type, objectValueType ), input );
+ }
+ if( MapType.isMap( type ) )
+ {
+ ValueType objectValueType = new ValueType( Object.class );
+ return deserialize( new MapType( type, objectValueType, objectValueType ), input );
+ }
+ return deserialize( new ValueType( type ), input );
+ }
+
+ @Override
+ public final <T> T deserialize( ValueType valueType, String input )
+ throws ValueSerializationException
+ {
+ try
+ {
+ return deserializeRoot( valueType, new ByteArrayInputStream( input.getBytes( UTF_8 ) ) );
+ }
+ catch( ValueSerializationException ex )
+ {
+ throw ex;
+ }
+ catch( Exception ex )
+ {
+ throw new ValueSerializationException( "Could not deserialize value", ex );
+ }
+ }
+
+ @Override
+ public final <T> T deserialize( Class<?> type, InputStream input )
+ throws ValueSerializationException
+ {
+ if( CollectionType.isCollection( type ) )
+ {
+ ValueType objectValueType = new ValueType( Object.class );
+ return deserialize( new CollectionType( type, objectValueType ), input );
+ }
+ if( MapType.isMap( type ) )
+ {
+ ValueType objectValueType = new ValueType( Object.class );
+ return deserialize( new MapType( type, objectValueType, objectValueType ), input );
+ }
+ return deserialize( new ValueType( type ), input );
+ }
+
+ @Override
+ public final <T> T deserialize( ValueType valueType, InputStream input )
+ throws ValueSerializationException
+ {
+ try
+ {
+ return deserializeRoot( valueType, input );
+ }
+ catch( ValueSerializationException ex )
+ {
+ throw ex;
+ }
+ catch( Exception ex )
+ {
+ throw new ValueSerializationException( "Could not deserialize value", ex );
+ }
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <T> T deserializeRoot( ValueType valueType, InputStream input )
+ throws Exception
+ {
+ final Class<?> type = first( valueType.types() );
+ // Plain ValueType
+ if( deserializers.get( type ) != null )
+ {
+ Scanner scanner = new Scanner( input, UTF_8 ).useDelimiter( "\\A" );
+ if( !scanner.hasNext() )
+ {
+ return String.class.equals( type ) ? (T) "" : null;
+ }
+ String string = scanner.next();
+ return (T) deserializers.get( type ).map( string );
+ }
+ else // Array ValueType
+ if( type.isArray() )
+ {
+ Scanner scanner = new Scanner( input, UTF_8 ).useDelimiter( "\\A" );
+ if( !scanner.hasNext() )
+ {
+ return null;
+ }
+ String string = scanner.next();
+ return (T) deserializeBase64Serialized( string );
+ }
+ else // Complex ValueType
+ {
+ InputType adaptedInput = adaptInput( input );
+ onDeserializationStart( valueType, adaptedInput );
+ T deserialized = doDeserialize( valueType, adaptedInput );
+ onDeserializationEnd( valueType, adaptedInput );
+ return deserialized;
+ }
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <T> T doDeserialize( ValueType valueType, InputType input )
+ throws Exception
+ {
+ final Class<?> type = first( valueType.types() );
+ // Registered deserializers
+ if( deserializers.get( type ) != null )
+ {
+ Object value = readPlainValue( input );
+ if( value == null )
+ {
+ return null;
+ }
+ return (T) deserializers.get( type ).map( value );
+ }
+ else // Explicit ValueComposite
+ if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ PULL_PARSING_LOG.trace( "ValueCompositeType assignable - deserializeValueComposite( {} )", input );
+ return (T) deserializeValueComposite( valueType, input );
+ }
+ else // Explicit Collections
+ if( CollectionType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ PULL_PARSING_LOG.trace( "CollectionType assignable - deserializeCollection( {} )", input );
+ return (T) deserializeCollection( (CollectionType) valueType, input );
+ }
+ else // Explicit Map
+ if( MapType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ PULL_PARSING_LOG.trace( "MapType assignable - deserializeMap( {} )", input );
+ return (T) deserializeMap( (MapType) valueType, input );
+ }
+ else // Enum
+ if( EnumType.class.isAssignableFrom( valueType.getClass() ) || type.isEnum() )
+ {
+ PULL_PARSING_LOG.trace( "EnumType assignable - readValue( {} )", input );
+ return (T) Enum.valueOf( (Class) type, readPlainValue( input ).toString() );
+ }
+ else // Array
+ if( type.isArray() )
+ {
+ return (T) deserializeBase64Serialized( readPlainValue( input ).toString() );
+ }
+ // Guessed Deserialization
+ PULL_PARSING_LOG.trace( "Unknown ValueType - deserializeGuessed( {} )", input );
+ return (T) deserializeGuessed( valueType, input );
+ }
+
+ private <T> Function<InputType, T> buildDeserializeInputFunction( final ValueType valueType )
+ {
+ return new Function<InputType, T>()
+ {
+ @Override
+ public T map( InputType input )
+ {
+ try
+ {
+ return doDeserialize( valueType, input );
+ }
+ catch( ValueSerializationException ex )
+ {
+ throw ex;
+ }
+ catch( Exception ex )
+ {
+ throw new ValueSerializationException( ex );
+ }
+ }
+ };
+ }
+
+ private <T> Collection<T> deserializeCollection( CollectionType collectionType, InputType input )
+ throws Exception
+ {
+ Collection<T> collection;
+ Class<?> collectionMainType = first( collectionType.types() );
+ if( Set.class.equals( collectionMainType ) )
+ {
+ collection = new LinkedHashSet<T>();
+ }
+ else
+ {
+ collection = new ArrayList<T>();
+ }
+ return readArrayInCollection( input,
+ this.<T>buildDeserializeInputFunction( collectionType.collectedType() ),
+ collection );
+ }
+
+ private <K, V> Map<K, V> deserializeMap( MapType mapType, InputType input )
+ throws Exception
+ {
+ return readMapInMap( input,
- this.<K>buildDeserializeInputFunction( mapType.getKeyType() ),
- this.<V>buildDeserializeInputFunction( mapType.getValueType() ),
++ this.<K>buildDeserializeInputFunction( mapType.keyType() ),
++ this.<V>buildDeserializeInputFunction( mapType.valueType() ),
+ new HashMap<K, V>() );
+ }
+
+ private <T> T deserializeValueComposite( ValueType valueType, InputType input )
+ throws Exception
+ {
+ PULL_PARSING_LOG.trace( "Switching to TREE PARSING @( {} )", input );
+ InputNodeType inputNode = readObjectTree( input );
+ TREE_PARSING_LOG.trace( "Switched to TREE PARSING @( {} )", input );
+ TREE_PARSING_LOG.trace( "ObjectNode is {}", inputNode );
+ if( inputNode == null )
+ {
+ return null;
+ }
+ return deserializeNodeValueComposite( valueType, inputNode );
+ }
+
+ private <T> T deserializeNodeValueComposite( ValueType valueType, InputNodeType inputNode )
+ throws Exception
+ {
+ ValueCompositeType valueCompositeType = (ValueCompositeType) valueType;
+ Class<?> valueBuilderType = first( valueCompositeType.types() );
+ String typeInfo = this.<String>getObjectFieldValue(
+ inputNode,
+ "_type",
+ this.<String>buildDeserializeInputNodeFunction( new ValueType( String.class ) ) );
+ TREE_PARSING_LOG.trace(
+ "In deserializeNodeValueComposite(), getObjectFieldValue( {} ) returned '{}'",
+ inputNode, typeInfo );
+ if( typeInfo != null )
+ {
+ ValueDescriptor valueDescriptor = valuesModule().valueDescriptor( typeInfo );
+ if( valueDescriptor == null )
+ {
+ throw new ValueSerializationException( "Specified value type could not be resolved: " + typeInfo );
+ }
+ valueCompositeType = valueDescriptor.valueType();
+ valueBuilderType = Class.forName( typeInfo );
+ if( !valueType.equals( valueCompositeType ) )
+ {
+ TREE_PARSING_LOG.debug(
+ "Overriding {} with {} as defined in _type field.",
+ valueType, valueCompositeType );
+ }
+ }
+ return deserializeValueComposite( valueCompositeType, valueBuilderType, inputNode );
+ }
+
+ private <T> T deserializeValueComposite( ValueCompositeType valueCompositeType, Class<?> valueBuilderType, InputNodeType inputNode )
+ throws Exception
+ {
+ final Map<String, Object> stateMap = new HashMap<String, Object>();
+
+ // Properties
+ for( PropertyDescriptor property : valueCompositeType.properties() )
+ {
+ String propertyName = property.qualifiedName().name();
+ Object value;
+ if( objectHasField( inputNode, propertyName ) )
+ {
+ value = getObjectFieldValue(
+ inputNode,
+ propertyName,
+ buildDeserializeInputNodeFunction( property.valueType() ) );
+ TREE_PARSING_LOG.trace(
+ "In deserializeValueComposite(), getObjectFieldValue( {} ) for key {} returned '{}' of class {}",
+ inputNode, propertyName, value, value == null ? "N/A" : value.getClass() );
+ if( property.isImmutable() )
+ {
+ if( value instanceof Set )
+ {
+ value = Collections.unmodifiableSet( (Set<?>) value );
+ }
+ else if( value instanceof List )
+ {
+ value = Collections.unmodifiableList( (List<?>) value );
+ }
+ else if( value instanceof Map )
+ {
+ value = Collections.unmodifiableMap( (Map<?, ?>) value );
+ }
+ }
+ TREE_PARSING_LOG.trace( "Property {}#{}( {} ) deserialized value is '{}' of class {}",
+ property.qualifiedName().type(),
+ property.qualifiedName().name(),
+ property.valueType(),
+ value,
+ value == null ? "N/A" : value.getClass() );
+ }
+ else
+ {
+ // Serialized object does not contain the field, try to default it
+ value = property.initialValue( valuesModule() );
+ TREE_PARSING_LOG.trace(
+ "Property {} was not defined in serialized object and has been defaulted to '{}'",
+ property.qualifiedName(), value );
+ }
+ stateMap.put( propertyName, value );
+ }
+
+ // Associations
+ for( AssociationDescriptor association : valueCompositeType.associations() )
+ {
+ String associationName = association.qualifiedName().name();
+ if( objectHasField( inputNode, associationName ) )
+ {
+ Object value = getObjectFieldValue(
+ inputNode,
+ associationName,
+ buildDeserializeInputNodeFunction( new ValueType( EntityReference.class ) ) );
+ stateMap.put( associationName, value );
+ }
+ }
+
+ // ManyAssociations
+ for( AssociationDescriptor manyAssociation : valueCompositeType.manyAssociations() )
+ {
+ String manyAssociationName = manyAssociation.qualifiedName().name();
+ if( objectHasField( inputNode, manyAssociationName ) )
+ {
+ Object value = getObjectFieldValue(
+ inputNode,
+ manyAssociationName,
+ buildDeserializeInputNodeFunction( new CollectionType( Collection.class,
+ new ValueType( EntityReference.class ) ) ) );
+ stateMap.put( manyAssociationName, value );
+ }
+ }
+
+ ValueBuilder<?> valueBuilder = buildNewValueBuilderWithState( valueBuilderType, stateMap );
+ return (T) valueBuilder.newInstance(); // Unchecked cast because the builder could use a type != T
+ }
+
+ private <T> Function<InputNodeType, T> buildDeserializeInputNodeFunction( final ValueType valueType )
+ {
+ return new Function<InputNodeType, T>()
+ {
+ @Override
+ public T map( InputNodeType inputNode )
+ {
+ try
+ {
+ return doDeserializeInputNodeValue( valueType, inputNode );
+ }
+ catch( ValueSerializationException ex )
+ {
+ throw ex;
+ }
+ catch( Exception ex )
+ {
+ throw new ValueSerializationException( ex );
+ }
+ }
+ };
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <T> T doDeserializeInputNodeValue( ValueType valueType, InputNodeType inputNode )
+ throws Exception
+ {
+ if( inputNode == null )
+ {
+ return null;
+ }
+ final Class<?> type = first( valueType.types() );
+ // Registered deserializers
+ if( deserializers.get( type ) != null )
+ {
+ Object value = asSimpleValue( inputNode );
+ TREE_PARSING_LOG.trace(
+ "While registered deserializer attempt, asSimpleValue( {} ) returned '{}'",
+ inputNode, value );
+ if( value == null )
+ {
+ return null;
+ }
+ return (T) deserializers.get( type ).map( value );
+ }
+ else // Explicit ValueComposite
+ if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ return (T) deserializeNodeValueComposite( (ValueCompositeType) valueType, inputNode );
+ }
+ else // Explicit Collections
+ if( CollectionType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ return (T) deserializeNodeCollection( (CollectionType) valueType, inputNode );
+ }
+ else // Explicit Map
+ if( MapType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ return (T) deserializeNodeMap( (MapType) valueType, inputNode );
+ }
+ else // Enum
+ if( EnumType.class.isAssignableFrom( valueType.getClass() ) || type.isEnum() )
+ {
+ Object value = asSimpleValue( inputNode );
+ TREE_PARSING_LOG.trace(
+ "While Enum deserialize attempt, asSimpleValue( {} ) returned '{}'",
+ inputNode, value );
+ if( value == null )
+ {
+ return null;
+ }
+ return (T) Enum.valueOf( (Class) type, value.toString() );
+ }
+ // Guessed deserialization
+ return (T) deserializeNodeGuessed( valueType, inputNode );
+ }
+
+ private ValueBuilder<?> buildNewValueBuilderWithState( Class<?> type, final Map<String, Object> stateMap )
+ {
+ return valuesModule().newValueBuilderWithState(
+ type,
+ new Function<PropertyDescriptor, Object>()
+ {
+ @Override
+ public Object map( PropertyDescriptor property )
+ {
+ return stateMap.get( property.qualifiedName().name() );
+ }
+ },
+ new Function<AssociationDescriptor, EntityReference>()
+ {
+ @Override
+ public EntityReference map( AssociationDescriptor association )
+ {
+ Object entityRef = stateMap.get( association.qualifiedName().name() );
+ if( entityRef == null )
+ {
+ return null;
+ }
+ else
+ {
+ return (EntityReference) entityRef;
+ }
+ }
+ },
+ new Function<AssociationDescriptor, Iterable<EntityReference>>()
+ {
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public Iterable<EntityReference> map( AssociationDescriptor manyAssociation )
+ {
+ Object entityRefs = stateMap.get( manyAssociation.qualifiedName().name() );
+ if( entityRefs == null )
+ {
+ return empty();
+ }
+ else
+ {
+ return (Iterable<EntityReference>) entityRefs;
+ }
+ }
+ } );
+
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <T> T deserializeGuessed( ValueType valueType, InputType input )
+ throws Exception
+ {
+ InputNodeType inputNode = readObjectTree( input );
+ if( inputNode == null )
+ {
+ return null;
+ }
+ return deserializeNodeGuessed( valueType, inputNode );
+ }
+
+ private <T> Collection<T> deserializeNodeCollection( CollectionType collectionType, InputNodeType inputNode )
+ throws Exception
+ {
+ Collection<T> collection;
+ Class<?> collectionMainType = first( collectionType.types() );
+ if( Set.class.equals( collectionMainType ) )
+ {
+ collection = new LinkedHashSet<T>();
+ }
+ else
+ {
+ collection = new ArrayList<T>();
+ }
+ putArrayNodeInCollection( inputNode,
+ this.<T>buildDeserializeInputNodeFunction( collectionType.collectedType() ),
+ collection );
+ return collection;
+ }
+
+ private <K, V> Map<K, V> deserializeNodeMap( MapType mapType, InputNodeType inputNode )
+ throws Exception
+ {
+ Map<K, V> map = new HashMap<K, V>();
+ putArrayNodeInMap( inputNode,
- this.<K>buildDeserializeInputNodeFunction( mapType.getKeyType() ),
- this.<V>buildDeserializeInputNodeFunction( mapType.getValueType() ),
++ this.<K>buildDeserializeInputNodeFunction( mapType.keyType() ),
++ this.<V>buildDeserializeInputNodeFunction( mapType.valueType() ),
+ map );
+ return map;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <T> T deserializeNodeGuessed( ValueType valueType, InputNodeType inputNode )
+ throws Exception
+ {
+ if( isObjectValue( inputNode ) )
+ {
+ // Attempt ValueComposite deserialization
+ ValueCompositeType valueCompositeType;
+ if( objectHasField( inputNode, "_type" ) ) // with _type info
+ {
+ String typeInfo = this.<String>getObjectFieldValue(
+ inputNode,
+ "_type",
+ this.<String>buildDeserializeInputNodeFunction( new ValueType( String.class ) ) );
+ TREE_PARSING_LOG.trace(
+ "In deserializeNodeGuessed(), getObjectFieldValue( {} ) returned '{}'",
+ inputNode, typeInfo );
+ ValueDescriptor valueDescriptor = valuesModule().valueDescriptor( typeInfo );
+ if( valueDescriptor == null )
+ {
+ throw new ValueSerializationException( "Specified value type could not be resolved: " + typeInfo );
+ }
+ valueCompositeType = valueDescriptor.valueType();
+ TREE_PARSING_LOG.debug(
+ "Overriding {} with {} as defined in _type field.",
+ valueType, valueCompositeType );
+ }
+ else // without _type info
+ {
+ ValueDescriptor valueDescriptor = valuesModule().valueDescriptor( first( valueType.types() ).getName() );
+ if( valueDescriptor == null )
+ {
+ throw new ValueSerializationException( "Don't know how to deserialize " + inputNode );
+ }
+ valueCompositeType = valueDescriptor.valueType();
+ TREE_PARSING_LOG.debug(
+ "Overriding {} with {} as found in available ValueComposites.",
+ valueType, valueCompositeType );
+ }
+ Class<?> valueBuilderType = first( valueCompositeType.types() );
+ return deserializeValueComposite( valueCompositeType, valueBuilderType, inputNode );
+ }
+ // Last resort : base64 java deserialization
+ return (T) deserializeBase64Serialized( inputNode );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <T> T deserializeBase64Serialized( InputNodeType inputNode )
+ throws Exception
+ {
+ Object value = asSimpleValue( inputNode );
+ TREE_PARSING_LOG.trace(
+ "While Base64 deserialize attempt, asSimpleValue( {} ) returned '{}'",
+ inputNode, value );
+ if( value == null )
+ {
+ return null;
+ }
+ String base64 = value.toString();
+ return deserializeBase64Serialized( base64 );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <T> T deserializeBase64Serialized( String inputString )
+ throws Exception
+ {
+ byte[] bytes = inputString.getBytes( UTF_8 );
+ bytes = Base64Encoder.decode( bytes );
+ ObjectInputStream oin = new ObjectInputStream( new ByteArrayInputStream( bytes ) );
+ Object result = oin.readObject();
+ oin.close();
+ return (T) result;
+ }
+
+ //
+ // Deserialization Extension Points
+ //
+ /**
+ * Called by the adapter on deserialization start, after {@link #adaptInput(java.io.InputStream)}.
+ *
+ * @throws Exception that will be wrapped in a {@link ValueSerializationException}
+ */
+ protected void onDeserializationStart( ValueType valueType, InputType input )
+ throws Exception
+ {
+ // NOOP
+ }
+
+ /**
+ * Called by the adapter on deserialization end.
+ *
+ * @throws Exception that will be wrapped in a {@link ValueSerializationException}
+ */
+ protected void onDeserializationEnd( ValueType valueType, InputType input )
+ throws Exception
+ {
+ // NOOP
+ }
+
+ //
+ // Pull Parsing Deserialization
+ //
+ /**
+ * This method is always called first, this is a chance to wrap the input type.
+ *
+ * @param input InputStream to adapt
+ * @return Adapted input
+ * @throws Exception that will be wrapped in a {@link ValueSerializationException}
+ */
+ protected abstract InputType adaptInput( InputStream input )
+ throws Exception;
+
+ /**
+ * @return a Plain Value read from the input
+ * @throws Exception that will be wrapped in a {@link ValueSerializationException}
+ */
+ protected abstract Object readPlainValue( InputType input )
+ throws Exception;
+
+ /**
+ * @return The filled collection or null if no array
+ * @throws Exception that will be wrapped in a {@link ValueSerializationException}
+ */
+ protected abstract <T> Collection<T> readArrayInCollection( InputType input,
+ Function<InputType, T> deserializer,
+ Collection<T> collection )
+ throws Exception;
+
+ /**
+ * A Map<K,V> is serialized in an array of entries objects.
+ *
+ * <p>Here is an example in JSON:</p>
+ * <pre>
+ * [
+ * { "key": "foo", "value": "bar" },
+ * { "key": "cathedral", "value": "bazar" }
+ * ]
+ * </pre>
+ * <p>And an empty Map:</p>
+ * <pre>[]</pre>
+ * <p>
+ * This allow to use any type as keys and values while keeping the Map order at the cost of having
+ * non-predictible order of key/value inside an entry object.
+ * </p>
+ *
+ * @return The filled map or null if no array
+ * @throws Exception that will be wrapped in a {@link ValueSerializationException}
+ */
+ protected abstract <K, V> Map<K, V> readMapInMap( InputType input,
+ Function<InputType, K> keyDeserializer,
+ Function<InputType, V> valueDeserializer,
+ Map<K, V> map )
+ throws Exception;
+
+ /**
+ * @return an InputNodeType or null if the value was null
+ * @throws Exception that will be wrapped in a {@link ValueSerializationException}
+ */
+ protected abstract InputNodeType readObjectTree( InputType input )
+ throws Exception;
+
+ //
+ // Tree Parsing Deserialization
+ //
+ protected abstract Object asSimpleValue( InputNodeType inputNode )
+ throws Exception;
+
+ protected abstract boolean isObjectValue( InputNodeType inputNode )
+ throws Exception;
+
+ protected abstract boolean objectHasField( InputNodeType inputNode, String key )
+ throws Exception;
+
+ /**
+ * Return null if the field do not exists.
+ * @throws Exception that will be wrapped in a {@link ValueSerializationException}
+ */
+ protected abstract <T> T getObjectFieldValue( InputNodeType inputNode,
+ String key,
+ Function<InputNodeType, T> valueDeserializer )
+ throws Exception;
+
+ protected abstract <T> void putArrayNodeInCollection( InputNodeType inputNode,
+ Function<InputNodeType, T> deserializer,
+ Collection<T> collection )
+ throws Exception;
+
+ protected abstract <K, V> void putArrayNodeInMap( InputNodeType inputNode,
+ Function<InputNodeType, K> keyDeserializer,
+ Function<InputNodeType, V> valueDeserializer,
+ Map<K, V> map )
+ throws Exception;
+ }
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e2ea757e/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
----------------------------------------------------------------------
diff --cc core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
index 0000000,fa39a6a..fbefa77
mode 000000,100644..100644
--- a/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
+++ b/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
@@@ -1,0 -1,519 +1,519 @@@
+ /*
+ * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2010, Niclas Hehdman. All Rights Reserved.
+ * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ *
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package org.qi4j.spi.value;
+
+ import java.io.ByteArrayOutputStream;
+ import java.io.ObjectOutputStream;
+ import java.io.OutputStream;
+ import java.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.util.Date;
+ import java.util.HashMap;
+ import java.util.Map;
+ import org.joda.time.DateTime;
+ import org.joda.time.LocalDate;
+ import org.joda.time.LocalDateTime;
+ import org.qi4j.api.Qi4j;
+ import org.qi4j.api.association.Association;
+ import org.qi4j.api.association.AssociationDescriptor;
+ import org.qi4j.api.association.AssociationStateHolder;
+ import org.qi4j.api.association.ManyAssociation;
+ import org.qi4j.api.composite.CompositeInstance;
+ import org.qi4j.api.entity.EntityComposite;
+ import org.qi4j.api.entity.EntityReference;
+ import org.qi4j.api.entity.Identity;
+ import org.qi4j.api.property.Property;
+ import org.qi4j.api.property.PropertyDescriptor;
+ import org.qi4j.api.util.Base64Encoder;
+ import org.qi4j.api.util.Dates;
+ import org.qi4j.api.value.ValueComposite;
+ import org.qi4j.api.value.ValueDescriptor;
+ import org.qi4j.api.value.ValueSerializationException;
+ import org.qi4j.api.value.ValueSerializer;
+ import org.qi4j.functional.Function;
+ import org.qi4j.functional.Functions;
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
+
+ import static org.qi4j.functional.Iterables.*;
+
+ /**
+ * Adapter for pull-parsing capable ValueSerializers.
+ *
+ * <p>
+ * Among Plain values (see {@link ValueSerializer}) some are considered primitives to underlying serialization
+ * mechanisms and by so handed/come without conversion to/from implementations. Primitive values can be one of:
+ * </p>
+ * <ul>
+ * <li>String,</li>
+ * <li>Boolean or boolean,</li>
+ * <li>Integer or int,</li>
+ * <li>Long or long,</li>
+ * <li>Short or short,</li>
+ * <li>Byte or byte,</li>
+ * <li>Float or float,</li>
+ * <li>Double or double.</li>
+ * </ul>
+ *
+ * @param <OutputType> Implementor output type
+ */
+ public abstract class ValueSerializerAdapter<OutputType>
+ implements ValueSerializer
+ {
+
+ private static final Logger LOG = LoggerFactory.getLogger( ValueSerializerAdapter.class );
+ private static final String UTF_8 = "UTF-8";
+ private final Map<Class<?>, Function<Object, Object>> serializers = new HashMap<Class<?>, Function<Object, Object>>();
+
+ /**
+ * Register a Plain Value type serialization Function.
+ *
+ * @param <T> Plain Value parametrized Type
+ * @param type Plain Value Type
+ * @param deserializer Serialization Function
+ */
+ @SuppressWarnings( "unchecked" )
+ protected final <T> void registerSerializer( Class<T> type, Function<T, Object> serializer )
+ {
+ serializers.put( type, (Function<Object, Object>) serializer );
+ }
+
+ public ValueSerializerAdapter()
+ {
+ // Primitive Value types
+ registerSerializer( String.class, Functions.<Object, String>identity() );
+ registerSerializer( Boolean.class, Functions.<Object, Boolean>identity() );
+ registerSerializer( Integer.class, Functions.<Object, Integer>identity() );
+ registerSerializer( Long.class, Functions.<Object, Long>identity() );
+ registerSerializer( Short.class, Functions.<Object, Short>identity() );
+ registerSerializer( Byte.class, Functions.<Object, Byte>identity() );
+ registerSerializer( Float.class, Functions.<Object, Float>identity() );
+ registerSerializer( Double.class, Functions.<Object, Double>identity() );
+
+ // Number types
+ registerSerializer( BigDecimal.class, new Function<BigDecimal, Object>()
+ {
+ @Override
+ public Object map( BigDecimal bigDecimal )
+ {
+ return bigDecimal.toString();
+ }
+ } );
+ registerSerializer( BigInteger.class, new Function<BigInteger, Object>()
+ {
+ @Override
+ public Object map( BigInteger bigInteger )
+ {
+ return bigInteger.toString();
+ }
+ } );
+
+ // Date types
+ registerSerializer( Date.class, new Function<Date, Object>()
+ {
+ @Override
+ public Object map( Date date )
+ {
+ return Dates.toUtcString( date );
+ }
+ } );
+ registerSerializer( DateTime.class, new Function<DateTime, Object>()
+ {
+ @Override
+ public Object map( DateTime date )
+ {
+ return date.toString();
+ }
+ } );
+ registerSerializer( LocalDateTime.class, new Function<LocalDateTime, Object>()
+ {
+ @Override
+ public Object map( LocalDateTime date )
+ {
+ return date.toString();
+ }
+ } );
+ registerSerializer( LocalDate.class, new Function<LocalDate, Object>()
+ {
+ @Override
+ public Object map( LocalDate date )
+ {
+ return date.toString();
+ }
+ } );
+
+ // Other supported types
+ registerSerializer( EntityReference.class, new Function<EntityReference, Object>()
+ {
+ @Override
+ public Object map( EntityReference ref )
+ {
+ return ref.toString();
+ }
+ } );
+ }
+
+ @Override
+ public final <T> Function<T, String> serialize()
+ {
+ return new Function<T, String>()
+ {
+ @Override
+ public String map( T object )
+ {
+ return serialize( object );
+ }
+ };
+ }
+
+ @Override
+ public final <T> Function<T, String> serialize( final boolean includeTypeInfo )
+ {
+ return new Function<T, String>()
+ {
+ @Override
+ public String map( T object )
+ {
+ return serialize( object, includeTypeInfo );
+ }
+ };
+ }
+
+ @Override
+ public final String serialize( Object object )
+ throws ValueSerializationException
+ {
+ return serialize( object, true );
+ }
+
+ @Override
+ public final String serialize( Object object, boolean includeTypeInfo )
+ throws ValueSerializationException
+ {
+ try
+ {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ serializeRoot( object, output, includeTypeInfo );
+ return output.toString( UTF_8 );
+ }
+ catch( ValueSerializationException ex )
+ {
+ throw ex;
+ }
+ catch( Exception ex )
+ {
+ throw new ValueSerializationException( "Could not serialize value", ex );
+ }
+ }
+
+ @Override
+ public final void serialize( Object object, OutputStream output )
+ throws ValueSerializationException
+ {
+ serialize( object, output, true );
+ }
+
+ @Override
+ public final void serialize( Object object, OutputStream output, boolean includeTypeInfo )
+ throws ValueSerializationException
+ {
+ try
+ {
+ serializeRoot( object, output, includeTypeInfo );
+ }
+ catch( ValueSerializationException ex )
+ {
+ throw ex;
+ }
+ catch( Exception ex )
+ {
+ throw new ValueSerializationException( "Could not serialize value", ex );
+ }
+ }
+
+ private void serializeRoot( Object object, OutputStream output, boolean includeTypeInfo )
+ throws Exception
+ {
+ if( object != null )
+ {
+ // System.out.println( ">>>>>>>>>>>> " + ( object == null ? "null" : object.getClass() ) );
+ if( serializers.get( object.getClass() ) != null )
+ {
+ // Plain Value
+ Object serialized = serializers.get( object.getClass() ).map( object );
+ output.write( serialized.toString().getBytes( UTF_8 ) );
+ }
+ else if( object.getClass().isEnum() )
+ {
+ // Enum Value
+ output.write( object.toString().getBytes( UTF_8 ) );
+ }
+ else if( object.getClass().isArray() )
+ {
+ // Array Value
+ output.write( serializeBase64Serializable( object ).getBytes( UTF_8 ) );
+ }
+ else
+ {
+ // Complex Value
+ OutputType adaptedOutput = adaptOutput( output );
+ onSerializationStart( object, adaptedOutput );
+ doSerialize( object, adaptedOutput, includeTypeInfo, true );
+ onSerializationEnd( object, adaptedOutput );
+ }
+ }
+ }
+
+ private void doSerialize( Object object, OutputType output, boolean includeTypeInfo, boolean rootPass )
+ throws Exception
+ {
+ // Null
+ if( object == null )
+ {
+ LOG.trace( "Null object -> onValue( null )" );
+ onValue( output, null );
+ }
+ else // Registered serializer
+ if( serializers.get( object.getClass() ) != null )
+ {
+ LOG.trace( "Registered serializer matches -> onValue( serialized )" );
+ onValue( output, serializers.get( object.getClass() ).map( object ) );
+ }
+ else // ValueComposite
+ if( ValueComposite.class.isAssignableFrom( object.getClass() ) )
+ {
+ LOG.trace( "ValueComposite assignable -> serializeValueComposite( object )" );
+ serializeValueComposite( object, output, includeTypeInfo, rootPass );
+ }
+ else // EntityComposite
+ if( EntityComposite.class.isAssignableFrom( object.getClass() ) )
+ {
+ LOG.trace( "EntityComposite assignable -> serializeEntityComposite( object )" );
+ serializeEntityComposite( object, output );
+ }
+ else // Collection - Iterable
+ if( Iterable.class.isAssignableFrom( object.getClass() ) )
+ {
+ LOG.trace( "Iterable assignable -> serializeIterable( object )" );
+ serializeIterable( object, output, includeTypeInfo );
+ }
+ else // Array - QUID Remove this and use java serialization for arrays?
+ if( object.getClass().isArray() )
+ {
+ LOG.trace( "Object isArray -> serializeBase64Serializable( object )" );
+ serializeBase64Serializable( object, output );
+ }
+ else // Map
+ if( Map.class.isAssignableFrom( object.getClass() ) )
+ {
+ LOG.trace( "Map assignable -> serializeMap( object )" );
+ serializeMap( object, output, includeTypeInfo );
+ }
+ else // Enum
+ if( object.getClass().isEnum() )
+ {
+ LOG.trace( "Object is an enum -> onValue( object.toString() )" );
+ onValue( output, object.toString() );
+ }
+ else // Fallback to Base64 encoded Java Serialization
+ {
+ LOG.trace( "Unknown object type -> serializeBase64Serializable( object )" );
+ serializeBase64Serializable( object, output );
+ }
+ }
+
+ private void serializeValueComposite( Object object, OutputType output, boolean includeTypeInfo, boolean rootPass )
+ throws Exception
+ {
- CompositeInstance valueInstance = Qi4j.INSTANCE_FUNCTION.map( (ValueComposite) object );
++ CompositeInstance valueInstance = Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( (ValueComposite) object );
+ ValueDescriptor descriptor = (ValueDescriptor) valueInstance.descriptor();
+ AssociationStateHolder state = (AssociationStateHolder) valueInstance.state();
+
+ onObjectStart( output );
+
+ if( includeTypeInfo && !rootPass )
+ {
+ onFieldStart( output, "_type" );
+ onValueStart( output );
+ onValue( output, first( descriptor.valueType().types() ).getName() );
+ onValueEnd( output );
+ onFieldEnd( output );
+ }
+
+ for( PropertyDescriptor persistentProperty : descriptor.valueType().properties() )
+ {
+ Property<?> property = state.propertyFor( persistentProperty.accessor() );
+ onFieldStart( output, persistentProperty.qualifiedName().name() );
+ onValueStart( output );
+ doSerialize( property.get(), output, includeTypeInfo, false );
+ onValueEnd( output );
+ onFieldEnd( output );
+ }
+ for( AssociationDescriptor associationDescriptor : descriptor.valueType().associations() )
+ {
+ Association<?> association = state.associationFor( associationDescriptor.accessor() );
+ Object instance = association.get();
+ onFieldStart( output, associationDescriptor.qualifiedName().name() );
+ onValueStart( output );
+ if( instance == null )
+ {
+ onValue( output, null );
+ }
+ else
+ {
+ onValue( output, ( (Identity) instance ).identity().get() );
+ }
+ onValueEnd( output );
+ onFieldEnd( output );
+ }
+ for( AssociationDescriptor associationDescriptor : descriptor.valueType().manyAssociations() )
+ {
+ ManyAssociation<?> manyAssociation = state.manyAssociationFor( associationDescriptor.accessor() );
+ onFieldStart( output, associationDescriptor.qualifiedName().name() );
+ onValueStart( output );
+ onArrayStart( output );
+ for( Object instance : manyAssociation )
+ {
+ onValueStart( output );
+ onValue( output, ( (Identity) instance ).identity().get() );
+ onValueEnd( output );
+ }
+ onArrayEnd( output );
+ onValueEnd( output );
+ onFieldEnd( output );
+ }
+
+ onObjectEnd( output );
+ }
+
+ private void serializeEntityComposite( Object object, OutputType output )
+ throws Exception
+ {
- onValue( output, EntityReference.getEntityReference( object ) );
++ onValue( output, EntityReference.entityReferenceFor( object ) );
+ }
+
+ private void serializeIterable( Object object, OutputType output, boolean includeTypeInfo )
+ throws Exception
+ {
+ @SuppressWarnings( "unchecked" )
+ Iterable<Object> collection = (Iterable<Object>) object;
+ onArrayStart( output );
+ for( Object item : collection )
+ {
+ onValueStart( output );
+ doSerialize( item, output, includeTypeInfo, false );
+ onValueEnd( output );
+ }
+ onArrayEnd( output );
+ }
+
+ private void serializeMap( Object object, OutputType output, boolean includeTypeInfo )
+ throws Exception
+ {
+ @SuppressWarnings( "unchecked" )
+ Map<Object, Object> map = (Map<Object, Object>) object;
+ onArrayStart( output );
+ for( Map.Entry<Object, Object> entry : map.entrySet() )
+ {
+ onObjectStart( output );
+
+ onFieldStart( output, "key" );
+ onValueStart( output );
+ onValue( output, entry.getKey().toString() );
+ onValueEnd( output );
+ onFieldEnd( output );
+
+ onFieldStart( output, "value" );
+ onValueStart( output );
+ doSerialize( entry.getValue(), output, includeTypeInfo, false );
+ onValueEnd( output );
+ onFieldEnd( output );
+
+ onObjectEnd( output );
+ }
+ onArrayEnd( output );
+ }
+
+ private void serializeBase64Serializable( Object object, OutputType output )
+ throws Exception
+ {
+ onValue( output, serializeBase64Serializable( object ) );
+ }
+
+ private String serializeBase64Serializable( Object object )
+ throws Exception
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream( bout );
+ out.writeUnshared( object );
+ out.close();
+ byte[] bytes = Base64Encoder.encode( bout.toByteArray(), true );
+ return new String( bytes, UTF_8 );
+ }
+
+ protected abstract OutputType adaptOutput( OutputStream output )
+ throws Exception;
+
+ protected void onSerializationStart( Object object, OutputType output )
+ throws Exception
+ {
+ // NOOP
+ }
+
+ protected void onSerializationEnd( Object object, OutputType output )
+ throws Exception
+ {
+ // NOOP
+ }
+
+ protected abstract void onArrayStart( OutputType output )
+ throws Exception;
+
+ protected abstract void onArrayEnd( OutputType output )
+ throws Exception;
+
+ protected abstract void onObjectStart( OutputType output )
+ throws Exception;
+
+ protected abstract void onObjectEnd( OutputType output )
+ throws Exception;
+
+ protected abstract void onFieldStart( OutputType output, String fieldName )
+ throws Exception;
+
+ protected void onFieldEnd( OutputType output )
+ throws Exception
+ {
+ // NOOP
+ }
+
+ protected void onValueStart( OutputType output )
+ throws Exception
+ {
+ // NOOP
+ }
+
+ protected abstract void onValue( OutputType output, Object value )
+ throws Exception;
+
+ protected void onValueEnd( OutputType output )
+ throws Exception
+ {
+ // NOOP
+ }
+ }