Return-Path: X-Original-To: apmail-zest-commits-archive@minotaur.apache.org Delivered-To: apmail-zest-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 4B34A18D18 for ; Sat, 18 Jul 2015 15:26:28 +0000 (UTC) Received: (qmail 77556 invoked by uid 500); 18 Jul 2015 15:26:18 -0000 Delivered-To: apmail-zest-commits-archive@zest.apache.org Received: (qmail 77534 invoked by uid 500); 18 Jul 2015 15:26:18 -0000 Mailing-List: contact commits-help@zest.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@zest.apache.org Delivered-To: mailing list commits@zest.apache.org Received: (qmail 77516 invoked by uid 99); 18 Jul 2015 15:26:18 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 18 Jul 2015 15:26:18 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 79420E00DE; Sat, 18 Jul 2015 15:26:18 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: niclas@apache.org To: commits@zest.apache.org Date: Sat, 18 Jul 2015 15:26:18 -0000 Message-Id: <7c04566c050948d2933b77d742c326aa@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/3] zest-qi4j git commit: removed the complex testcase setup again, and that solved two out of three failures. Repository: zest-qi4j Updated Branches: refs/heads/develop 2c6c2726f -> 2daf2be41 removed the complex testcase setup again, and that solved two out of three failures. Project: http://git-wip-us.apache.org/repos/asf/zest-qi4j/repo Commit: http://git-wip-us.apache.org/repos/asf/zest-qi4j/commit/7ce42530 Tree: http://git-wip-us.apache.org/repos/asf/zest-qi4j/tree/7ce42530 Diff: http://git-wip-us.apache.org/repos/asf/zest-qi4j/diff/7ce42530 Branch: refs/heads/develop Commit: 7ce4253036a2ce67d5775968d7f7e5da49ee0846 Parents: d641afd Author: Niclas Hedhman Authored: Sat Jul 18 15:53:47 2015 +0300 Committer: Niclas Hedhman Committed: Sat Jul 18 15:53:47 2015 +0300 ---------------------------------------------------------------------- build.gradle | 2 + .../qi4j/api/configuration/Configuration.java | 147 ++++++++++++++++--- .../configuration/ConfigurationComposite.java | 4 +- .../NoSuchConfigurationException.java | 48 ++++++ .../main/java/org/qi4j/api/entity/Identity.java | 2 +- .../org/qi4j/api/value/ValueSerialization.java | 4 + .../qi4j/bootstrap/ConfigurationAssembly.java | 28 ++++ .../bootstrap/ConfigurationDeclaration.java | 87 +++++++++++ .../java/org/qi4j/bootstrap/ModuleAssembly.java | 22 +++ .../bootstrap/ConfigurationAssemblyImpl.java | 85 +++++++++++ .../bootstrap/ConfigurationDeclarationImpl.java | 125 ++++++++++++++++ .../runtime/bootstrap/ModuleAssemblyImpl.java | 68 +++++++++ .../runtime/injection/InjectedFieldModel.java | 6 + ...bstractConfigurationDeserializationTest.java | 120 +++++++++++++++ ...JacksonConfigurationDeserializationTest.java | 36 +++++ .../src/test/resources/configtest.json | 8 + ...OrgJsonConfigurationDeserializationTest.java | 36 +++++ .../src/test/resources/configtest.json | 8 + .../StaxConfigurationDeserializationTest.java | 64 ++++++++ .../src/test/resources/configtest.xml | 48 ++++++ 20 files changed, 923 insertions(+), 25 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/build.gradle ---------------------------------------------------------------------- diff --git a/build.gradle b/build.gradle index b0f4791..de2147b 100644 --- a/build.gradle +++ b/build.gradle @@ -74,6 +74,8 @@ rat { '**/.settings/**', '**/.classpath', '**/.project', '**/.gradletasknamecache', '**/private/cache/**', '**/.nb-gradle-properties', '**/.nb-gradle/**', + // JSON files are not allowed to have comments, according to http://www.json.org/ and http://www.ietf.org/rfc/rfc4627.txt + '**/*.json', // Various Text Resources '**/README.*','**/README*.*', '**/TODO', '**/src/main/resources/**/*.txt', http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/api/src/main/java/org/qi4j/api/configuration/Configuration.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/configuration/Configuration.java b/core/api/src/main/java/org/qi4j/api/configuration/Configuration.java index a9154ae..77c373d 100644 --- a/core/api/src/main/java/org/qi4j/api/configuration/Configuration.java +++ b/core/api/src/main/java/org/qi4j/api/configuration/Configuration.java @@ -20,12 +20,17 @@ import java.io.InputStream; import org.qi4j.api.Qi4j; import org.qi4j.api.composite.Composite; import org.qi4j.api.composite.PropertyMapper; +import org.qi4j.api.constraint.ConstraintViolationException; import org.qi4j.api.entity.EntityBuilder; +import org.qi4j.api.entity.Identity; +import org.qi4j.api.injection.scope.Service; import org.qi4j.api.injection.scope.Structure; import org.qi4j.api.injection.scope.This; import org.qi4j.api.mixin.Mixins; import org.qi4j.api.service.ServiceComposite; import org.qi4j.api.service.ServiceDescriptor; +import org.qi4j.api.service.ServiceReference; +import org.qi4j.api.service.qualifier.ServiceTags; import org.qi4j.api.structure.Module; import org.qi4j.api.unitofwork.EntityTypeNotFoundException; import org.qi4j.api.unitofwork.NoSuchEntityException; @@ -33,6 +38,7 @@ import org.qi4j.api.unitofwork.UnitOfWork; import org.qi4j.api.unitofwork.UnitOfWorkCompletionException; import org.qi4j.api.usecase.Usecase; import org.qi4j.api.usecase.UsecaseBuilder; +import org.qi4j.api.value.ValueSerialization; import static org.qi4j.functional.Iterables.first; @@ -107,7 +113,6 @@ import static org.qi4j.functional.Iterables.first; * : * } * - * */ @SuppressWarnings( "JavadocReference" ) @Mixins( Configuration.ConfigurationMixin.class ) @@ -162,6 +167,9 @@ public interface Configuration @Structure private Module module; + @Service + private Iterable> valueSerialization; + public ConfigurationMixin() { } @@ -238,10 +246,10 @@ public interface Configuration } @SuppressWarnings( "unchecked" ) - private V initializeConfigurationInstance( ServiceComposite serviceComposite, - UnitOfWork uow, - ServiceDescriptor serviceModel, - String identity + private V initializeConfigurationInstance( ServiceComposite serviceComposite, + UnitOfWork uow, + ServiceDescriptor serviceModel, + String identity ) throws InstantiationException { @@ -249,22 +257,68 @@ public interface Configuration Usecase usecase = UsecaseBuilder.newUsecase( "Configuration:" + me.identity().get() ); UnitOfWork buildUow = module.newUnitOfWork( usecase ); - EntityBuilder configBuilder = buildUow.newEntityBuilder( serviceModel.configurationType(), identity ); + Class type = first( api.serviceDescriptorFor( serviceComposite ).types() ); + Class configType = serviceModel.configurationType(); // Check for defaults - String s = identity + ".properties"; - Class type = first( api.serviceDescriptorFor( serviceComposite ).types() ); - // Load defaults from classpath root if available - if ( type.getResource( s ) == null && type.getResource( "/" + s ) != null ) + V config = tryLoadPropertiesFile( buildUow, type, configType, identity ); + if( config == null ) + { + config = tryLoadJsonFile( buildUow, type, configType, identity ); + if( config == null ) + { + config = tryLoadYamlFile( buildUow, type, configType, identity ); + if( config == null ) + { + config = tryLoadXmlFile( buildUow, type, configType, identity ); + if( config == null ) + { + try + { + EntityBuilder configBuilder = buildUow.newEntityBuilder( serviceModel.configurationType(), identity ); + configBuilder.newInstance(); + } + catch( ConstraintViolationException e ) + { + throw new NoSuchConfigurationException( configType, identity, e ); + } + } + } + } + } + + try + { + buildUow.complete(); + + // Try again + return (V) findConfigurationInstanceFor( serviceComposite, uow ); + } + catch( Exception e1 ) { - s = "/" + s; + InstantiationException ex = new InstantiationException( + "Could not instantiate configuration, and no configuration initialization file was found (" + identity + ")" ); + ex.initCause( e1 ); + throw ex; } - InputStream asStream = type.getResourceAsStream( s ); + } + + private V tryLoadPropertiesFile( UnitOfWork buildUow, + Class compositeType, + Class configType, + String identity + ) + throws InstantiationException + { + EntityBuilder configBuilder = buildUow.newEntityBuilder( configType, identity ); + String resourceName = identity + ".properties"; + InputStream asStream = getResource( compositeType, resourceName ); if( asStream != null ) { try { PropertyMapper.map( asStream, (Composite) configBuilder.instance() ); + return configBuilder.newInstance(); } catch( IOException e1 ) { @@ -274,22 +328,69 @@ public interface Configuration throw exception; } } + return null; + } - try + private InputStream getResource( Class type, String resourceName ) + { + // Load defaults from classpath root if available + if( type.getResource( resourceName ) == null && type.getResource( "/" + resourceName ) != null ) { - configBuilder.newInstance(); - buildUow.complete(); - - // Try again - return (V) findConfigurationInstanceFor( serviceComposite, uow ); + resourceName = "/" + resourceName; } - catch( Exception e1 ) + return type.getResourceAsStream( resourceName ); + } + + private V tryLoadJsonFile( UnitOfWork uow, + Class compositeType, + Class configType, + String identity + ) + { + return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.JSON, ".json" ); + } + + private V tryLoadYamlFile( UnitOfWork uow, + Class compositeType, + Class configType, + String identity + ) + { + return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.YAML, ".yaml" ); + } + + private V tryLoadXmlFile( UnitOfWork uow, + Class compositeType, + Class configType, + String identity + ) + { + return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.XML, ".xml" ); + } + + private V readConfig( UnitOfWork uow, + Class compositeType, + Class configType, + String identity, + String format, + String extension + ) + { + for( ServiceReference serializerRef : valueSerialization ) { - InstantiationException ex = new InstantiationException( - "Could not instantiate configuration, and no Properties file was found (" + s + ")" ); - ex.initCause( e1 ); - throw ex; + ServiceTags serviceTags = serializerRef.metaInfo( ServiceTags.class ); + if( serviceTags.hasTag( format ) ) + { + String resourceName = identity + extension; + InputStream asStream = getResource( compositeType, resourceName ); + if( asStream != null ) + { + V configObject = serializerRef.get().deserialize( configType, asStream ); + return uow.toEntity( configType, configObject ); + } + } } + return null; } } } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/api/src/main/java/org/qi4j/api/configuration/ConfigurationComposite.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/configuration/ConfigurationComposite.java b/core/api/src/main/java/org/qi4j/api/configuration/ConfigurationComposite.java index a2919f2..39fb149 100644 --- a/core/api/src/main/java/org/qi4j/api/configuration/ConfigurationComposite.java +++ b/core/api/src/main/java/org/qi4j/api/configuration/ConfigurationComposite.java @@ -14,7 +14,9 @@ package org.qi4j.api.configuration; +import org.qi4j.api.composite.Composite; import org.qi4j.api.entity.EntityComposite; +import org.qi4j.api.entity.Identity; import org.qi4j.api.entity.Queryable; /** @@ -25,6 +27,6 @@ import org.qi4j.api.entity.Queryable; */ @Queryable( false ) public interface ConfigurationComposite - extends EntityComposite + extends Identity, Composite { } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/api/src/main/java/org/qi4j/api/configuration/NoSuchConfigurationException.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/configuration/NoSuchConfigurationException.java b/core/api/src/main/java/org/qi4j/api/configuration/NoSuchConfigurationException.java new file mode 100644 index 0000000..b3d3ed1 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/configuration/NoSuchConfigurationException.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.qi4j.api.configuration; + +import org.qi4j.api.constraint.ConstraintViolationException; +import org.qi4j.api.entity.Identity; + +public class NoSuchConfigurationException extends RuntimeException +{ + private final Class configType; + private final String identity; + + public NoSuchConfigurationException( Class configType, + String identity, + ConstraintViolationException cause + ) + { + super( "No configuration found for '" + identity + "' and configuration " + configType.getName() + " has one or more non-Optional properties.", cause ); + this.configType = configType; + this.identity = identity; + } + + public Class configType() + { + return configType; + } + + public String identity() + { + return identity; + } +} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/api/src/main/java/org/qi4j/api/entity/Identity.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/entity/Identity.java b/core/api/src/main/java/org/qi4j/api/entity/Identity.java index 0c82ca9..b4adbc5 100644 --- a/core/api/src/main/java/org/qi4j/api/entity/Identity.java +++ b/core/api/src/main/java/org/qi4j/api/entity/Identity.java @@ -41,7 +41,7 @@ public interface Identity /** * Default Identity implementation. */ - public class IdentityMixin + class IdentityMixin implements Identity { @State http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java b/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java index 503aa5c..31a4af0 100644 --- a/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java +++ b/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java @@ -43,6 +43,10 @@ public interface ValueSerialization * Tag a ValueSerialization service that support the XML format. */ String XML = "xml"; + /** + * Tag a ValueSerialization service that support the YAML format. + */ + String YAML = "yaml"; } } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationAssembly.java ---------------------------------------------------------------------- diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationAssembly.java new file mode 100644 index 0000000..8f45332 --- /dev/null +++ b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationAssembly.java @@ -0,0 +1,28 @@ +/* + * 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.qi4j.bootstrap; + +import org.qi4j.api.type.HasTypes; + +/** + * This represents the assembly information of a single ConfigurationComposite in a Module. + */ +public interface ConfigurationAssembly + extends HasTypes +{ +} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationDeclaration.java ---------------------------------------------------------------------- diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationDeclaration.java new file mode 100644 index 0000000..ef10c35 --- /dev/null +++ b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationDeclaration.java @@ -0,0 +1,87 @@ +/* + * 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.qi4j.bootstrap; + +import org.qi4j.api.common.Visibility; + +/** + * Fluent API for declaring configurations. Instances + * of this API are acquired by calling {@link ModuleAssembly#configurations(Class[])}. + */ +public interface ConfigurationDeclaration +{ + /** + * Set additional metainfo for this configuration declaration. + * + * @param info metainfo that can be retrieved from the CompositeDescriptor. + * + * @return This instance for a fluid DSL + */ + ConfigurationDeclaration setMetaInfo( Object info ); + + /** + * Set visibility for declared entities. + * + * @param visibility The {@link Visibility} that this ConfigurationComposite will have. + * + * @return This instance for a fluid DSL + */ + ConfigurationDeclaration visibleIn( Visibility visibility ); + + /** + * Declare additional concerns for these configurations. + * + * @param concerns The concerns that are to be added to the ConfigurationComposite beyond the statically declared ones. + * + * @return This instance for a fluid DSL + */ + ConfigurationDeclaration withConcerns( Class... concerns ); + + /** + * Declare additional side-effects for these configurations. + * + * @param sideEffects The sideeffects that are to be added to the ConfigurationComposite beyond the statically declared ones. + * + * @return This instance for a fluid DSL + */ + ConfigurationDeclaration withSideEffects( Class... sideEffects ); + + /** + * Declare additional mixins for these configurations. + *

+ * This can be useful to override any default mixins from the configuration interface. + *

+ * @param mixins The mixins that are to be added to the ConfigurationComposite beyond the statically declared ones. + * + * @return This instance for a fluid DSL + */ + ConfigurationDeclaration withMixins( Class... mixins ); + + /** + * Declare additional interfaces for these declared interfaces. + *

+ * This can be useful to add types that the Configuration should implement, but + * which you do not want to include in the entity interface itself. + *

+ * @param types list of interfaces to add + * + * @return This instance for a fluid DSL + */ + ConfigurationDeclaration withTypes( Class... types ); +} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/bootstrap/src/main/java/org/qi4j/bootstrap/ModuleAssembly.java ---------------------------------------------------------------------- diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ModuleAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ModuleAssembly.java index a7f8cab..4e473b4 100644 --- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ModuleAssembly.java +++ b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ModuleAssembly.java @@ -21,6 +21,7 @@ package org.qi4j.bootstrap; import org.qi4j.api.activation.Activator; import org.qi4j.api.structure.Module; +import org.qi4j.api.type.HasTypes; import org.qi4j.functional.Specification; /** @@ -140,6 +141,27 @@ public interface ModuleAssembly EntityDeclaration entities( Specification specification ); /** + * Declare a list of Configuration Composites for this Module. Use the ConfigurationDeclaration that is returned to + * declare further settings. Note that the ConfigurationDeclaration works on all of the types specified. + * + * @param configurationTypes The types that specifies the Configuration types. + * + * @return An ConfigurationDeclaration for the specified Configuration types. + */ + ConfigurationDeclaration configurations( Class... configurationTypes ); + + /** + * Given a Specification for ConfigurationAssembly's, returns a ConfigurationDeclaration that can + * be used to work with all of the assemblies matched by the specification. + * + * @param specification The Specification that specifies the ConfigurationComposite types of interest. + * + * @return An ConfigurationDeclaration for the specified EntityComposite types. + */ + ConfigurationDeclaration configurations( Specification specification ); + + + /** * Declare a list of object classes for this Module. Use the ObjectDeclaration that is returned to * declare further settings. Note that the ObjectDeclaration works on all of the types specified. * http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationAssemblyImpl.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationAssemblyImpl.java new file mode 100644 index 0000000..d8088cc --- /dev/null +++ b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationAssemblyImpl.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.qi4j.runtime.bootstrap; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Member; +import org.qi4j.api.association.Association; +import org.qi4j.api.association.GenericAssociationInfo; +import org.qi4j.api.association.ManyAssociation; +import org.qi4j.api.association.NamedAssociation; +import org.qi4j.api.common.InvalidApplicationException; +import org.qi4j.api.common.MetaInfo; +import org.qi4j.api.common.Optional; +import org.qi4j.api.common.QualifiedName; +import org.qi4j.api.common.UseDefaults; +import org.qi4j.api.constraint.Constraint; +import org.qi4j.api.entity.EntityComposite; +import org.qi4j.api.property.GenericPropertyInfo; +import org.qi4j.api.property.Immutable; +import org.qi4j.api.property.Property; +import org.qi4j.api.util.Annotations; +import org.qi4j.api.util.Classes; +import org.qi4j.bootstrap.AssociationDeclarations; +import org.qi4j.bootstrap.ConfigurationAssembly; +import org.qi4j.bootstrap.EntityAssembly; +import org.qi4j.bootstrap.ManyAssociationDeclarations; +import org.qi4j.bootstrap.NamedAssociationDeclarations; +import org.qi4j.bootstrap.StateDeclarations; +import org.qi4j.runtime.association.AssociationModel; +import org.qi4j.runtime.association.AssociationsModel; +import org.qi4j.runtime.association.ManyAssociationModel; +import org.qi4j.runtime.association.ManyAssociationsModel; +import org.qi4j.runtime.association.NamedAssociationModel; +import org.qi4j.runtime.association.NamedAssociationsModel; +import org.qi4j.runtime.composite.MixinsModel; +import org.qi4j.runtime.composite.StateModel; +import org.qi4j.runtime.composite.ValueConstraintsInstance; +import org.qi4j.runtime.composite.ValueConstraintsModel; +import org.qi4j.runtime.entity.EntityMixinsModel; +import org.qi4j.runtime.entity.EntityModel; +import org.qi4j.runtime.entity.EntityStateModel; +import org.qi4j.runtime.property.PropertyModel; + +import static org.qi4j.api.util.Annotations.isType; +import static org.qi4j.api.util.Classes.typeOf; +import static org.qi4j.functional.Iterables.filter; +import static org.qi4j.functional.Iterables.first; + +/** + * Declaration of a EntityComposite. + */ +public final class ConfigurationAssemblyImpl + implements ConfigurationAssembly +{ + private ValueAssemblyImpl value; + private EntityAssemblyImpl entity; + + public ConfigurationAssemblyImpl( Class mainType ) + { + value = new ValueAssemblyImpl( mainType ); + entity = new EntityAssemblyImpl( mainType ); + } + + @Override + public Iterable> types() + { + return value.types(); + } +} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationDeclarationImpl.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationDeclarationImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationDeclarationImpl.java new file mode 100644 index 0000000..18a14cb --- /dev/null +++ b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationDeclarationImpl.java @@ -0,0 +1,125 @@ +/* + * 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.qi4j.runtime.bootstrap; + +import org.qi4j.api.common.Visibility; +import org.qi4j.bootstrap.ConfigurationDeclaration; +import org.qi4j.bootstrap.EntityDeclaration; + +import static java.util.Arrays.asList; + +/** + * Declaration of a Composite. Created by {@link org.qi4j.bootstrap.ModuleAssembly#configurations(Class[])}. + */ +public final class ConfigurationDeclarationImpl + implements ConfigurationDeclaration +{ + private final Iterable entities; + private final Iterable values; + + public ConfigurationDeclarationImpl( Iterable entities, Iterable values ) + { + this.entities = entities; + this.values = values; + } + + @Override + public ConfigurationDeclaration setMetaInfo( Object info ) + { + for( EntityAssemblyImpl entity : entities ) + { + entity.metaInfo.set( info ); + } + for( ValueAssemblyImpl value : values ) + { + value.metaInfo.set( info ); + } + return this; + } + + @Override + public ConfigurationDeclaration visibleIn( Visibility visibility ) + { + for( EntityAssemblyImpl entity : entities ) + { + entity.visibility = visibility; + } + for( ValueAssemblyImpl value : values ) + { + value.visibility = visibility; + } + return this; + } + + @Override + public ConfigurationDeclaration withConcerns( Class... concerns ) + { + for( EntityAssemblyImpl entity : entities ) + { + entity.concerns.addAll( asList( concerns ) ); + } + for( ValueAssemblyImpl value : values ) + { + value.concerns.addAll( asList( concerns ) ); + } + return this; + } + + @Override + public ConfigurationDeclaration withSideEffects( Class... sideEffects ) + { + for( EntityAssemblyImpl entity : entities ) + { + entity.sideEffects.addAll( asList( sideEffects ) ); + } + for( ValueAssemblyImpl value : values ) + { + value.sideEffects.addAll( asList( sideEffects ) ); + } + return this; + } + + @Override + public ConfigurationDeclaration withMixins( Class... mixins ) + { + for( EntityAssemblyImpl entity : entities ) + { + entity.mixins.addAll( asList( mixins ) ); + } + for( ValueAssemblyImpl value : values ) + { + value.mixins.addAll( asList( mixins ) ); + } + return this; + } + + @Override + public ConfigurationDeclaration withTypes( Class... types ) + { + for( EntityAssemblyImpl entity : entities ) + { + entity.types.addAll( asList( types ) ); + } + for( ValueAssemblyImpl value : values ) + { + value.types.addAll( asList( types ) ); + } + return this; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ModuleAssemblyImpl.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ModuleAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ModuleAssemblyImpl.java index a06bb9f..1f470dc 100644 --- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ModuleAssemblyImpl.java +++ b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ModuleAssemblyImpl.java @@ -27,13 +27,17 @@ import org.qi4j.api.common.MetaInfo; import org.qi4j.api.common.Visibility; import org.qi4j.api.composite.TransientComposite; import org.qi4j.api.entity.EntityComposite; +import org.qi4j.api.entity.Identity; import org.qi4j.api.service.DuplicateServiceIdentityException; import org.qi4j.api.service.ServiceImporter; import org.qi4j.api.structure.Module; +import org.qi4j.api.type.HasTypes; +import org.qi4j.api.type.MatchTypeSpecification; import org.qi4j.api.value.ValueComposite; import org.qi4j.bootstrap.AssemblyException; import org.qi4j.bootstrap.AssemblySpecifications; import org.qi4j.bootstrap.AssemblyVisitor; +import org.qi4j.bootstrap.ConfigurationDeclaration; import org.qi4j.bootstrap.EntityAssembly; import org.qi4j.bootstrap.EntityDeclaration; import org.qi4j.bootstrap.ImportedServiceAssembly; @@ -52,6 +56,7 @@ import org.qi4j.bootstrap.ValueAssembly; import org.qi4j.bootstrap.ValueDeclaration; import org.qi4j.functional.Iterables; import org.qi4j.functional.Specification; +import org.qi4j.functional.Specifications; import org.qi4j.runtime.activation.ActivatorsModel; import org.qi4j.runtime.composite.TransientModel; import org.qi4j.runtime.composite.TransientsModel; @@ -254,6 +259,69 @@ public final class ModuleAssemblyImpl } @Override + public ConfigurationDeclaration configurations( Class... configurationTypes ) + { + List entityAssemblyList = new ArrayList<>(); + + for( Class entityType : configurationTypes ) + { + if( this.entityAssemblies.containsKey( entityType ) ) + { + entityAssemblyList.add( this.entityAssemblies.get( entityType ) ); + } + else + { + EntityAssemblyImpl entityAssembly = new EntityAssemblyImpl( entityType ); + this.entityAssemblies.put( entityType, entityAssembly ); + entityAssemblyList.add( entityAssembly ); + } + } + + List valueAssemblyList = new ArrayList<>(); + + for( Class valueType : configurationTypes ) + { + if( valueAssemblies.containsKey( valueType ) ) + { + valueAssemblyList.add( valueAssemblies.get( valueType ) ); + } + else + { + ValueAssemblyImpl valueAssembly = new ValueAssemblyImpl( valueType ); + valueAssemblies.put( valueType, valueAssembly ); + valueAssemblyList.add( valueAssembly ); + valueAssembly.types.add( Identity.class ); + } + } + + return new ConfigurationDeclarationImpl( entityAssemblyList, valueAssemblyList ); + } + + @Override + public ConfigurationDeclaration configurations( Specification specification ) + { + Specification isConfigurationComposite = new MatchTypeSpecification( Identity.class ); + specification = Specifications.and( specification, isConfigurationComposite ); + List entityAssmblyList = new ArrayList<>(); + for( EntityAssemblyImpl entityAssembly : entityAssemblies.values() ) + { + if( specification.satisfiedBy( entityAssembly ) ) + { + entityAssmblyList.add( entityAssembly ); + } + } + List valueAssemblyList = new ArrayList<>(); + for( ValueAssemblyImpl transientAssembly : valueAssemblies.values() ) + { + if( specification.satisfiedBy( transientAssembly ) ) + { + valueAssemblyList.add( transientAssembly ); + } + } + return new ConfigurationDeclarationImpl( entityAssmblyList, valueAssemblyList ); + } + + @Override public ObjectDeclaration objects( Class... objectTypes ) throws AssemblyException { http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedFieldModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedFieldModel.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedFieldModel.java index bd51924..5412fec 100644 --- a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedFieldModel.java +++ b/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedFieldModel.java @@ -138,4 +138,10 @@ public final class InjectedFieldModel return emptyList(); } } + + @Override + public String toString() + { + return "InjectedFieldModel{" + ", injectedField=" + injectedField + '}'; + } } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/core/testsupport/src/main/java/org/qi4j/test/entity/AbstractConfigurationDeserializationTest.java ---------------------------------------------------------------------- diff --git a/core/testsupport/src/main/java/org/qi4j/test/entity/AbstractConfigurationDeserializationTest.java b/core/testsupport/src/main/java/org/qi4j/test/entity/AbstractConfigurationDeserializationTest.java new file mode 100644 index 0000000..7e2b7ea --- /dev/null +++ b/core/testsupport/src/main/java/org/qi4j/test/entity/AbstractConfigurationDeserializationTest.java @@ -0,0 +1,120 @@ +/* + * 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.qi4j.test.entity; + +import org.junit.Test; +import org.qi4j.api.common.Visibility; +import org.qi4j.api.configuration.Configuration; +import org.qi4j.api.entity.Identity; +import org.qi4j.api.injection.scope.This; +import org.qi4j.api.mixin.Mixins; +import org.qi4j.api.property.Property; +import org.qi4j.api.service.ServiceReference; +import org.qi4j.api.value.ValueSerialization; +import org.qi4j.bootstrap.AssemblyException; +import org.qi4j.bootstrap.ModuleAssembly; +import org.qi4j.entitystore.memory.MemoryEntityStoreService; +import org.qi4j.spi.uuid.UuidIdentityGeneratorService; +import org.qi4j.test.AbstractQi4jTest; +import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.junit.Assert.assertThat; + +public abstract class AbstractConfigurationDeserializationTest extends AbstractQi4jTest +{ + @Override + public void assemble( ModuleAssembly module ) + throws AssemblyException + { +// ModuleAssembly storageModule = module.layer().module( "storage" ); + ModuleAssembly storageModule = module; // Disable the more complex set up. The entire value serialization has gotten the deserialization type lookup problem wrong. + module.configurations( ConfigSerializationConfig.class ); + module.values( Host.class ); + module.services( MyService.class ).identifiedBy( "configtest" ); + storageModule.services( MemoryEntityStoreService.class ).visibleIn( Visibility.layer ); + storageModule.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON ); + storageModule.services( UuidIdentityGeneratorService.class ); + } + + @Test + public void givenServiceWhenInitializingExpectCorrectDeserialization() + { + ServiceReference ref = module.findService( MyService.class ); + assertThat( ref, notNullValue() ); + assertThat( ref.isAvailable(), equalTo( true ) ); + MyService myService = ref.get(); + assertThat( myService, notNullValue() ); + assertThat( myService.name(), equalTo( "main" ) ); + assertThat( myService.hostIp(), equalTo( "12.23.34.45" ) ); + assertThat( myService.hostPort(), equalTo( 1234 ) ); + } + + @Mixins( MyServiceMixin.class ) + public interface MyService + { + + String hostIp(); + + Integer hostPort(); + + String name(); + } + + public static class MyServiceMixin + implements MyService + { + + @This + private Configuration config; + + @Override + public String hostIp() + { + return config.get().host().get().ip().get(); + } + + @Override + public Integer hostPort() + { + return config.get().host().get().port().get(); + } + + @Override + public String name() + { + return config.get().name().get(); + } + } + + public interface ConfigSerializationConfig extends Identity + { + Property name(); + + Property host(); + } + + public interface Host + { + Property ip(); + + Property port(); + } +} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonConfigurationDeserializationTest.java ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonConfigurationDeserializationTest.java b/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonConfigurationDeserializationTest.java new file mode 100644 index 0000000..1209abf --- /dev/null +++ b/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonConfigurationDeserializationTest.java @@ -0,0 +1,36 @@ +/* + * 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.qi4j.valueserialization.jackson; + +import org.qi4j.bootstrap.AssemblyException; +import org.qi4j.bootstrap.ModuleAssembly; +import org.qi4j.test.entity.AbstractConfigurationDeserializationTest; + +public class JacksonConfigurationDeserializationTest + extends AbstractConfigurationDeserializationTest +{ + @Override + public void assemble( final ModuleAssembly module ) + throws AssemblyException + { + super.assemble( module ); + new JacksonValueSerializationAssembler() + .assemble( module ); + } +} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/extensions/valueserialization-jackson/src/test/resources/configtest.json ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/src/test/resources/configtest.json b/extensions/valueserialization-jackson/src/test/resources/configtest.json new file mode 100644 index 0000000..d48a241 --- /dev/null +++ b/extensions/valueserialization-jackson/src/test/resources/configtest.json @@ -0,0 +1,8 @@ +{ + "identity" : "configtest", + "host": { + "ip": "12.23.34.45", + "port": 1234 + }, + "name": "main" +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonConfigurationDeserializationTest.java ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonConfigurationDeserializationTest.java b/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonConfigurationDeserializationTest.java new file mode 100644 index 0000000..3d9cd3e --- /dev/null +++ b/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonConfigurationDeserializationTest.java @@ -0,0 +1,36 @@ +/* + * 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.qi4j.valueserialization.orgjson; + +import org.qi4j.bootstrap.AssemblyException; +import org.qi4j.bootstrap.ModuleAssembly; +import org.qi4j.test.entity.AbstractConfigurationDeserializationTest; + +public class OrgJsonConfigurationDeserializationTest + extends AbstractConfigurationDeserializationTest +{ + @Override + public void assemble( final ModuleAssembly module ) + throws AssemblyException + { + super.assemble( module ); + new OrgJsonValueSerializationAssembler() + .assemble( module ); + } +} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/extensions/valueserialization-orgjson/src/test/resources/configtest.json ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-orgjson/src/test/resources/configtest.json b/extensions/valueserialization-orgjson/src/test/resources/configtest.json new file mode 100644 index 0000000..d48a241 --- /dev/null +++ b/extensions/valueserialization-orgjson/src/test/resources/configtest.json @@ -0,0 +1,8 @@ +{ + "identity" : "configtest", + "host": { + "ip": "12.23.34.45", + "port": 1234 + }, + "name": "main" +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxConfigurationDeserializationTest.java ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxConfigurationDeserializationTest.java b/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxConfigurationDeserializationTest.java new file mode 100644 index 0000000..f4c4b87 --- /dev/null +++ b/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxConfigurationDeserializationTest.java @@ -0,0 +1,64 @@ +/* + * 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.qi4j.valueserialization.stax; + +import org.junit.Test; +import org.qi4j.api.injection.scope.Service; +import org.qi4j.api.value.ValueBuilder; +import org.qi4j.api.value.ValueSerialization; +import org.qi4j.bootstrap.AssemblyException; +import org.qi4j.bootstrap.ModuleAssembly; +import org.qi4j.spi.uuid.UuidIdentityGeneratorService; +import org.qi4j.test.entity.AbstractConfigurationDeserializationTest; + +public class StaxConfigurationDeserializationTest + extends AbstractConfigurationDeserializationTest +{ + @Service + private ValueSerialization valueSerialization; + + @Override + public void assemble( final ModuleAssembly module ) + throws AssemblyException + { + super.assemble( module ); + new StaxValueSerializationAssembler() + .assemble( module ); + } + + @Test + public void serializeTest() + { + ValueBuilder builder = module.newValueBuilder( ConfigSerializationConfig.class ); + builder.prototype().name().set( "main" ); + builder.prototype().host().set( createHost() ); + builder.prototype().identity().set( "configtest" ); + ConfigSerializationConfig value = builder.newInstance(); + + valueSerialization.serialize( value, System.out ); + } + + private Host createHost() + { + ValueBuilder builder = module.newValueBuilder( Host.class ); + builder.prototype().ip().set( "12.23.34.45" ); + builder.prototype().port().set( 1234 ); + return builder.newInstance(); + } +} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/7ce42530/extensions/valueserialization-stax/src/test/resources/configtest.xml ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-stax/src/test/resources/configtest.xml b/extensions/valueserialization-stax/src/test/resources/configtest.xml new file mode 100644 index 0000000..90d2d23 --- /dev/null +++ b/extensions/valueserialization-stax/src/test/resources/configtest.xml @@ -0,0 +1,48 @@ + + + + + + name + main + + + host + + + + _type + org.qi4j.test.entity.AbstractConfigurationDeserializationTest$Host + + + port + 1234 + + + ip + 12.23.34.45 + + + + + + identity + configtest + +