http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/concern/ConcernDescriptor.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/concern/ConcernDescriptor.java b/core/api/src/main/java/org/qi4j/api/concern/ConcernDescriptor.java new file mode 100644 index 0000000..a98adf7 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/concern/ConcernDescriptor.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2008, Rickard Ãberg. 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.api.concern; + +/** + * Concern descriptor. + */ +public interface ConcernDescriptor +{ + Class modifierClass(); +}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/concern/ConcernOf.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/concern/ConcernOf.java b/core/api/src/main/java/org/qi4j/api/concern/ConcernOf.java new file mode 100644 index 0000000..33cdd01 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/concern/ConcernOf.java @@ -0,0 +1,44 @@ +/* + * Copyright 2008 Niclas Hedhman. 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.api.concern; + +import org.qi4j.api.concern.internal.ConcernFor; + +/** + * Base class for Concerns. It introduces a typed "next" pointer + * that Concerns can use to invoke the next Concern (or mixin) in + * the chain. + * <p> + * Generic Concerns should subclass {@link GenericConcern} instead. + * </p> + * <p> + * Concerns implementations must be thread-safe in their implementation, + * as multiple threads may share instances. + * </p> + */ +public abstract class ConcernOf<T> +{ + /** + * The "next" pointer. This points to + * the next concern in the chain or the mixin + * to be invoked. + */ + final + @ConcernFor + protected T next = null; +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/concern/Concerns.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/concern/Concerns.java b/core/api/src/main/java/org/qi4j/api/concern/Concerns.java new file mode 100644 index 0000000..9213035 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/concern/Concerns.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2007, Rickard Ãberg. All Rights Reserved. + * Copyright (c) 2007, Niclas Hedhman. 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.api.concern; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation is used by composites and mixins to declare what Concerns + * should be applied to the type or specific method. + */ +@Retention( RetentionPolicy.RUNTIME ) +@Target( { ElementType.TYPE, ElementType.METHOD } ) +@Documented +public @interface Concerns +{ + Class<?>[] value(); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/concern/ConcernsDescriptor.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/concern/ConcernsDescriptor.java b/core/api/src/main/java/org/qi4j/api/concern/ConcernsDescriptor.java new file mode 100644 index 0000000..dd9a91b --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/concern/ConcernsDescriptor.java @@ -0,0 +1,24 @@ +/* Copyright 2008 Edward Yakop. +* +* 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.api.concern; + +/** + * Concerns descriptor. + */ +public interface ConcernsDescriptor +{ +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/concern/GenericConcern.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/concern/GenericConcern.java b/core/api/src/main/java/org/qi4j/api/concern/GenericConcern.java new file mode 100644 index 0000000..2986ff8 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/concern/GenericConcern.java @@ -0,0 +1,32 @@ +/* + * Copyright 2008 Niclas Hedhman. 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.api.concern; + +import java.lang.reflect.InvocationHandler; + +/** + * Base class for generic Concerns. Subclass + * and implement the "invoke" method. Use the + * "next" field in {@link ConcernOf} to continue the invocation + * chain. + */ +public abstract class GenericConcern + extends ConcernOf<InvocationHandler> + implements InvocationHandler +{ +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/concern/internal/ConcernFor.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/concern/internal/ConcernFor.java b/core/api/src/main/java/org/qi4j/api/concern/internal/ConcernFor.java new file mode 100644 index 0000000..de3e1b4 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/concern/internal/ConcernFor.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2007, Rickard Ãberg. All Rights Reserved. + * Copyright (c) 2007, Niclas Hedhman. 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.api.concern.internal; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.qi4j.api.injection.InjectionScope; + +/** + * This annotation is required once in each Concern, to mark the + * field where the next element in the call sequence should be + * injected. + * <p> + * The type of the field must be of the same type as the Concern + * itself, or an InvocationHandler. + * </p> + * <p> + * Example; + * </p> + * <pre><code> + * public interface MyStuff + * { + * void doSomething(); + * } + * + * public class MyStuffConcern + * implements MyStuff + * { + * @ConcernFor MyStuff next; + * + * public void doSomething() + * { + * // HERE DO THE MODIFIER STUFF. + * + * // Delegate to the underlying mixin/modifier. + * next.doSomething(); + * } + * } + * </code></pre> + */ +@Retention( RetentionPolicy.RUNTIME ) +@Target( { ElementType.FIELD, ElementType.PARAMETER } ) +@Documented +@InjectionScope +public @interface ConcernFor +{ +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/concern/internal/package.html ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/concern/internal/package.html b/core/api/src/main/java/org/qi4j/api/concern/internal/package.html new file mode 100644 index 0000000..9351f10 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/concern/internal/package.html @@ -0,0 +1,25 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> +<html> + <body> + <h1>Internal/Private package for the Concern API.</h1> + <p> + This is an internal package, and no classes in this package is part of the API and compatibility + with these classes will not be attempted. + </p> + </body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/concern/package.html ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/concern/package.html b/core/api/src/main/java/org/qi4j/api/concern/package.html new file mode 100644 index 0000000..fcc7ef7 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/concern/package.html @@ -0,0 +1,21 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> +<html> + <body> + <h2>Concern API.</h2> + </body> +</html> http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/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 new file mode 100644 index 0000000..77c373d --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/configuration/Configuration.java @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2008, Rickard Ãberg. All Rights Reserved. + * Copyright (c) 2012, Paul Merlin. + * + * 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.api.configuration; + +import java.io.IOException; +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; +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; + +/** + * Provide Configurations for Services. A Service that wants to be configurable + * should inject a reference to Configuration with the Configuration type: + * <pre><code> + * * @This Configuration<MyServiceConfiguration> config; + * </code></pre> + * <p> + * where MyServiceConfiguration extends {@link ConfigurationComposite}, which itself is an ordinary + * {@link org.qi4j.api.entity.EntityComposite}. The Configuration implementation + * will either locate an instance of the given Configuration type in the + * persistent store using the identity of the Service, or create a new such instance + * if one doesn't already exist. + * </p> + * <p> + * If a new Configuration instance is created then it will be populated with properties + * from the properties file whose filesystem name is the same as the identity (e.g. "MyService.properties"). + * If a service is not given a name via the {@code org.qi4j.bootstrap.ServiceDeclaration#identifiedBy(String)}, the + * name will default to the FQCN of the ServiceComposite type. + * </p> + * <p> + * The Configuration instance can be modified externally just like any other EntityComposite, but + * its values will not be updated in the Service until {@link #refresh()} is called. This allows + * safe reloads of Configuration state to ensure that it is not reloaded while the Service is handling + * a request. + * </p> + * <p> + * The Configuration will be automatically refreshed when the Service is activated by the Zest runtime. + * Any refreshes at other points will have to be done manually or triggered through some other + * mechanism. + * </p> + * <p> + * The user configuration entity is part of a long running {@link UnitOfWork}, and to persist changes to it the + * {@link #save()} method must be called. No other actions are required. Example; + * </p> + * <pre><code> + * + * public interface MyConfiguration extends ConfigurationComposite + * { + * Property<Long> timeout(); + * } + * + * : + * + * @This Configuration<MyConfiguration> config; + * : + * private void setTimeoutConfiguration( long timeout ) + * { + * config.get().timeout().set( timeout ); + * config.save(); + * } + * </code></pre> + * <p> + * And even if a separate thread is using the {@code timeout()} configuration when this is happening, the + * {@link UnitOfWork} isolation will ensure that the other thread is not affected. That thread, on the other hand + * will need to do a {@link #refresh()} at an appropriate time to pick up the timeout change. For instance; + * </p> + * <pre><code> + * + * @Service InventoryService remoteInventoryService; + * + * public void restockInventoryItem( InventoryItemId id, int itemCount ) + * { + * config.refresh(); + * long timeout = config.get().timeout().get(); + * + * remoteInventoryService.restock( id, itemCount, timeout ); + * + * : + * : + * } + * </code></pre> + */ +@SuppressWarnings( "JavadocReference" ) +@Mixins( Configuration.ConfigurationMixin.class ) +public interface Configuration<T> +{ + /** + * Retrieves the user configuration instance managed by this Configuration. + * <p> + * Even if the user configuration is initialized from properties file, the consistency rules of Zest composites + * still applies. If the the properties file is missing a value, then the initialization will fail with a + * RuntimeException. If Constraints has been defined, those will need to be satisfied as well. The user + * configuration instance returned will fulfill the constraints and consistency normal to all composites, and + * can therefor safely be used with additional checks. + * </p> + * + * @return The fully initialized and ready-to-use user configuration instance. + */ + T get(); + + /** + * Updates the values of the managed user ConfigurationComposite instance from the underlying + * {@code org.qi4j.spi.entitystore.EntityStore}. Any modified values in the current user configuration that + * has not been saved, via {@link #save()} method, will be lost. + */ + void refresh(); + + /** + * Persists the modified values in the user configuration instance to the underlying store. + */ + void save(); + + /** + * Implementation of Configuration. + * <p> + * This is effectively an internal class in Zest and should never be used directly by user code. + * </p> + * + * @param <T> + */ + public class ConfigurationMixin<T> + implements Configuration<T> + { + private T configuration; + private UnitOfWork uow; + + @Structure + private Qi4j api; + + @This + private ServiceComposite me; + + @Structure + private Module module; + + @Service + private Iterable<ServiceReference<ValueSerialization>> valueSerialization; + + public ConfigurationMixin() + { + } + + @Override + public synchronized T get() + { + if( configuration == null ) + { + Usecase usecase = UsecaseBuilder.newUsecase( "Configuration:" + me.identity().get() ); + uow = module.newUnitOfWork( usecase ); + try + { + configuration = this.findConfigurationInstanceFor( me, uow ); + } + catch( InstantiationException e ) + { + throw new IllegalStateException( e ); + } + } + + return configuration; + } + + @Override + public synchronized void refresh() + { + if( configuration != null ) + { + configuration = null; + uow.discard(); + uow = null; + } + } + + @Override + public void save() + { + if( uow != null ) + { + try + { + uow.complete(); + uow = null; + } + catch( UnitOfWorkCompletionException e ) + { + // Should be impossible + e.printStackTrace(); + } + + configuration = null; // Force refresh + } + } + + @SuppressWarnings( "unchecked" ) + public <V> V findConfigurationInstanceFor( ServiceComposite serviceComposite, UnitOfWork uow ) + throws InstantiationException + { + ServiceDescriptor serviceModel = api.serviceDescriptorFor( serviceComposite ); + + String identity = serviceComposite.identity().get(); + V configuration; + try + { + configuration = uow.get( serviceModel.<V>configurationType(), identity ); + uow.pause(); + } + catch( NoSuchEntityException | EntityTypeNotFoundException e ) + { + return (V) initializeConfigurationInstance( serviceComposite, uow, serviceModel, identity ); + } + return configuration; + } + + @SuppressWarnings( "unchecked" ) + private <V extends Identity> V initializeConfigurationInstance( ServiceComposite serviceComposite, + UnitOfWork uow, + ServiceDescriptor serviceModel, + String identity + ) + throws InstantiationException + { + Module module = api.moduleOf( serviceComposite ); + Usecase usecase = UsecaseBuilder.newUsecase( "Configuration:" + me.identity().get() ); + UnitOfWork buildUow = module.newUnitOfWork( usecase ); + + Class<?> type = first( api.serviceDescriptorFor( serviceComposite ).types() ); + Class<V> configType = serviceModel.configurationType(); + + // Check for defaults + 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<V> configBuilder = buildUow.newEntityBuilder( serviceModel.<V>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 ) + { + InstantiationException ex = new InstantiationException( + "Could not instantiate configuration, and no configuration initialization file was found (" + identity + ")" ); + ex.initCause( e1 ); + throw ex; + } + } + + private <C, V> V tryLoadPropertiesFile( UnitOfWork buildUow, + Class<C> compositeType, + Class<V> configType, + String identity + ) + throws InstantiationException + { + EntityBuilder<V> 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 ) + { + InstantiationException exception = new InstantiationException( + "Could not read underlying Properties file." ); + exception.initCause( e1 ); + throw exception; + } + } + return null; + } + + private InputStream getResource( Class<?> type, String resourceName ) + { + // Load defaults from classpath root if available + if( type.getResource( resourceName ) == null && type.getResource( "/" + resourceName ) != null ) + { + resourceName = "/" + resourceName; + } + return type.getResourceAsStream( resourceName ); + } + + private <C, V extends Identity> V tryLoadJsonFile( UnitOfWork uow, + Class<C> compositeType, + Class<V> configType, + String identity + ) + { + return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.JSON, ".json" ); + } + + private <C, V extends Identity> V tryLoadYamlFile( UnitOfWork uow, + Class<C> compositeType, + Class<V> configType, + String identity + ) + { + return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.YAML, ".yaml" ); + } + + private <C, V extends Identity> V tryLoadXmlFile( UnitOfWork uow, + Class<C> compositeType, + Class<V> configType, + String identity + ) + { + return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.XML, ".xml" ); + } + + private <C, V extends Identity> V readConfig( UnitOfWork uow, + Class<C> compositeType, + Class<V> configType, + String identity, + String format, + String extension + ) + { + for( ServiceReference<ValueSerialization> serializerRef : valueSerialization ) + { + 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/polygene-java/blob/a789141d/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 new file mode 100644 index 0000000..39fb149 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/configuration/ConfigurationComposite.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2008, Rickard Ãberg. 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.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; + +/** + * Services that want to be configurable should have a ConfigurationComposite that contains all the settings. + * They are treated as EntityComposites, and are therefore stored in an EntityStore. There will be one instance + * per service instance that uses each ConfigurationComposite, and the identity of the entity is the same as that + * of the service. + */ +@Queryable( false ) +public interface ConfigurationComposite + extends Identity, Composite +{ +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/configuration/Enabled.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/configuration/Enabled.java b/core/api/src/main/java/org/qi4j/api/configuration/Enabled.java new file mode 100644 index 0000000..19a2c29 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/configuration/Enabled.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2010, Rickard Ãberg. 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.api.configuration; + +import org.qi4j.api.common.UseDefaults; +import org.qi4j.api.property.Property; + +/** + * Common configuration for setting whether a service is enabled or not. A disabled service + * is not considered to be available. Let your own ConfigurationComposite extend this interface to use. + */ +public interface Enabled +{ + @UseDefaults + Property<Boolean> enabled(); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/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<? extends Identity> configType; + private final String identity; + + public NoSuchConfigurationException( Class<? extends Identity> 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<? extends Identity> configType() + { + return configType; + } + + public String identity() + { + return identity; + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/configuration/package.html ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/configuration/package.html b/core/api/src/main/java/org/qi4j/api/configuration/package.html new file mode 100644 index 0000000..7f8a892 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/configuration/package.html @@ -0,0 +1,21 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> +<html> + <body> + <h2>Configuration API.</h2> + </body> +</html> http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/constraint/Constraint.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/constraint/Constraint.java b/core/api/src/main/java/org/qi4j/api/constraint/Constraint.java new file mode 100644 index 0000000..8e53e0e --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/constraint/Constraint.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2007, Rickard Ãberg. 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.api.constraint; + +import java.io.Serializable; +import java.lang.annotation.Annotation; + +/** + * All Constraints must implement this interface, which is used for each + * value validation. + */ +public interface Constraint<ANNOTATION extends Annotation, TYPE> + extends Serializable +{ + /** + * For each value or parameter which should be checked this method will be invoked. + * If the method returns true the value is valid. If it returns false the value + * is considered invalid. When all constraints have been checked a ConstraintViolationException + * will be thrown with all the constraint violations that were found. + * + * @param annotation the annotation to match + * @param value the value to be checked + * + * @return true if valid, false if invalid + */ + boolean isValid( ANNOTATION annotation, TYPE value ); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDeclaration.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDeclaration.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDeclaration.java new file mode 100644 index 0000000..7ca9249 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDeclaration.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2007, Rickard Ãberg. 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.api.constraint; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * All annotations that are used to trigger Constraints must have this annotation. + */ +@Retention( RetentionPolicy.RUNTIME ) +@Target( ElementType.ANNOTATION_TYPE ) +@Documented +public @interface ConstraintDeclaration +{ +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDescriptor.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDescriptor.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDescriptor.java new file mode 100644 index 0000000..ff5e5a6 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDescriptor.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2008, Rickard Ãberg. 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.api.constraint; + +import java.lang.annotation.Annotation; + +/** + * Constraint Descriptor. + */ +public interface ConstraintDescriptor +{ + Annotation annotation(); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/constraint/ConstraintImplementationNotFoundException.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintImplementationNotFoundException.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintImplementationNotFoundException.java new file mode 100644 index 0000000..e27ef94 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintImplementationNotFoundException.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008, Niclas Hedhman. 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.api.constraint; + +import org.qi4j.api.common.InvalidApplicationException; + +/** + * This exception is thrown if a Constraint implementation can not be found. + */ +public class ConstraintImplementationNotFoundException + extends InvalidApplicationException +{ + public ConstraintImplementationNotFoundException( String message ) + { + super( message ); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolation.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolation.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolation.java new file mode 100644 index 0000000..09c4be0 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolation.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2007, Rickard Ãberg. 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.api.constraint; + +import java.io.Serializable; +import java.lang.annotation.Annotation; + +/** + * When a constraint violation has occurred (ie Constraint.isValid has returned false) it + * is put in a collection of all violations that have occurred for this value check. + */ +public final class ConstraintViolation + implements Serializable +{ + private String name; + private final Annotation constraint; + private final Object value; + + public ConstraintViolation( String name, Annotation constraint, Object value ) + { + this.name = name; + this.constraint = constraint; + this.value = value; + } + + public String name() + { + return name; + } + + public Annotation constraint() + { + return constraint; + } + + public Object value() + { + return value; + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolationException.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolationException.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolationException.java new file mode 100644 index 0000000..28e41b3 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolationException.java @@ -0,0 +1,257 @@ +/* + * Copyright 2008 Niclas Hedhman. 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.api.constraint; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Member; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import org.qi4j.api.Qi4j; +import org.qi4j.api.composite.Composite; +import org.qi4j.functional.Function; +import org.qi4j.functional.Iterables; + +/** + * This Exception is thrown when there is one or more Constraint Violations in a method + * call. + * <p> + * The Constraint Violations are aggregated per method, and this exception will contain those + * violations, together with the Composite instance it happened on as well as the Method that + * was invoked. The Exception also has support for localized messages of these violations. + * </p> + */ +public class ConstraintViolationException + extends IllegalArgumentException +{ + private static final long serialVersionUID = 1L; + + private final Collection<ConstraintViolation> constraintViolations; + private String methodName; + private String mixinTypeName; + private String instanceToString; + private Iterable<Class<?>> instanceTypes; + + public ConstraintViolationException( Composite instance, Member method, + Collection<ConstraintViolation> constraintViolations + ) + { + this( instance.toString(), Qi4j.FUNCTION_DESCRIPTOR_FOR.map( instance ).types(), method, constraintViolations ); + } + + public ConstraintViolationException( String instanceToString, + Iterable<Class<?>> instanceTypes, + Member method, + Collection<ConstraintViolation> violations + ) + { + this.instanceToString = instanceToString; + this.instanceTypes = instanceTypes; + mixinTypeName = method.getDeclaringClass().getName(); + methodName = method.getName(); + this.constraintViolations = violations; + } + + public ConstraintViolationException( String instanceToString, + Iterable<Class<?>> instanceTypes, + String mixinTypeName, + String methodName, + Collection<ConstraintViolation> violations + ) + { + this.instanceToString = instanceToString; + this.instanceTypes = instanceTypes; + this.mixinTypeName = mixinTypeName; + this.methodName = methodName; + this.constraintViolations = violations; + } + + public Collection<ConstraintViolation> constraintViolations() + { + return constraintViolations; + } + + /** + * Creates localized messages of all the constraint violations that has occured. + * <p> + * The key "<code>Qi4j_ConstraintViolation_<i><strong>CompositeType</strong></i></code>" will be used to lookup the text formatting + * pattern from the ResourceBundle, where <strong><code><i>CompositeType</i></code></strong> is the + * class name of the Composite where the constraint was violated. If such key does not exist, then the + * key "<code>Qi4j_ConstraintViolation</code>" will be used, and if that one also doesn't exist, or + * the resourceBundle argument is null, then the default patterns will be used; + * </p> + * <table summary="Localization of constraint vioations."> + * <tr><th>Type of Composite</th><th>Pattern used</th></tr> + * <tr><td>Composite</td> + * <td><code>Constraint Violation in {2}.{3} with constraint {4}, in composite \n{0} of type {1}</code></td> + * </tr> + * <tr><td>EntityComposite</td> + * <td><code>Constraint Violation in {2}.{3} with constraint {4}, in entity {1}[id={0}]</code></td> + * </tr> + * <tr><td>ServiceComposite</td> + * <td><code>Constraint Violation in {2}.{3} with constraint {4}, in service {0}</code></td> + * </tr> + * </table> + * Then format each ConstraintViolation according to such pattern, where the following argument are passed; + * <table summary="List of arguments available."><tr><th>Arg</th><th>Value</th></tr> + * <tr> + * <td>{0}</td> + * <td>Composite instance toString()</td> + * </tr> + * <tr> + * <td>{1}</td> + * <td>CompositeType class name</td> + * </tr> + * <tr> + * <td>{2}</td> + * <td>MixinType class name</td> + * </tr> + * <tr> + * <td>{3}</td> + * <td>MixinType method name</td> + * </tr> + * <tr> + * <td>{4}</td> + * <td>Annotation toString()</td> + * </tr> + * <tr> + * <td>{5}</td> + * <td>toString() of value passed as the argument, or "null" text if argument was null.</td> + * </tr> + * </table> + * <p> + * <b>NOTE!!!</b> This class is still under construction and will be modified further. + * </p> + * + * @param bundle The ResourceBundle for Localization, or null if default formatting and locale to be used. + * + * @return An array of localized messages of the violations incurred. + */ + public String[] localizedMessagesFrom( ResourceBundle bundle ) + { + String pattern = "Constraint violation in {0}.{1} for method ''{3}'' with constraint \"{4}({6})\", for value ''{5}''"; + + ArrayList<String> list = new ArrayList<String>(); + for( ConstraintViolation violation : constraintViolations ) + { + Locale locale; + if( bundle != null ) + { + try + { + pattern = bundle.getString( "qi4j.constraint." + mixinTypeName + "." + methodName ); + } + catch( MissingResourceException e1 ) + { + try + { + pattern = bundle.getString( "qi4j.constraint" ); + } + catch( MissingResourceException e2 ) + { + // ignore. The default pattern will be used. + } + } + locale = bundle.getLocale(); + } + else + { + locale = Locale.getDefault(); + } + MessageFormat format = new MessageFormat( pattern, locale ); + + Annotation annotation = violation.constraint(); + String name = violation.name(); + Object value = violation.value(); + String classes; + if( Iterables.count( instanceTypes ) == 1 ) + { + classes = Iterables.first( instanceTypes ).getSimpleName(); + } + else + { + classes = "[" + Iterables.<Class<?>>toString( instanceTypes, new Function<Class<?>, String>() + { + @Override + public String map( Class<?> from ) + { + return from.getSimpleName(); + } + }, "," ) + "]"; + } + Object[] args = new Object[] + { + instanceToString, + classes, + mixinTypeName, + methodName, + annotation.toString(), + "" + value, + name + }; + StringBuffer text = new StringBuffer(); + format.format( args, text, null ); + list.add( text.toString() ); + } + String[] result = new String[ list.size() ]; + list.toArray( result ); + return result; + } + + public String localizedMessage() + { + String[] messages = localizedMessagesFrom( null ); + StringBuilder result = new StringBuilder(); + boolean first = true; + for( String message : messages ) + { + if( !first ) + { + result.append( ',' ); + } + first = false; + result.append( message ); + } + return result.toString(); + } + + @Override + public String getLocalizedMessage() + { + return localizedMessage(); + } + + @Override + public String getMessage() + { + return localizedMessage(); + } + + public String methodName() + { + return methodName; + } + + public String mixinTypeName() + { + return mixinTypeName; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/constraint/Constraints.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/constraint/Constraints.java b/core/api/src/main/java/org/qi4j/api/constraint/Constraints.java new file mode 100644 index 0000000..b42701c --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/constraint/Constraints.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2007, Rickard Ãberg. 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.api.constraint; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation is used by composites and mixins to declare what Constraints + * can be applied in the Composite. + * <p> + * Constraints implement the {@link Constraint} interface + * </p> + */ +@Retention( RetentionPolicy.RUNTIME ) +@Target( { ElementType.TYPE } ) +@Documented +public @interface Constraints +{ + Class<? extends Constraint<?, ?>>[] value(); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/constraint/ConstraintsDescriptor.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintsDescriptor.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintsDescriptor.java new file mode 100644 index 0000000..bea1115 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintsDescriptor.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2008, Rickard Ãberg. 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.api.constraint; + +/** + * Constraints Descriptor. + */ +public interface ConstraintsDescriptor +{ +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/constraint/Name.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/constraint/Name.java b/core/api/src/main/java/org/qi4j/api/constraint/Name.java new file mode 100644 index 0000000..fc4c79e --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/constraint/Name.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2007, Rickard Ãberg. All Rights Reserved. + * Copyright (c) 2007, Niclas Hedhman. 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.api.constraint; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation for parameter names. This is used to add extra information for constraint exception. + */ +@Retention( RetentionPolicy.RUNTIME ) +@Target( { ElementType.PARAMETER } ) +@Documented +public @interface Name +{ + String value(); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/constraint/package.html ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/constraint/package.html b/core/api/src/main/java/org/qi4j/api/constraint/package.html new file mode 100644 index 0000000..2e4d340 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/constraint/package.html @@ -0,0 +1,21 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> +<html> + <body> + <h2>Constraint API.</h2> + </body> +</html> http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/dataset/DataSet.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/dataset/DataSet.java b/core/api/src/main/java/org/qi4j/api/dataset/DataSet.java new file mode 100644 index 0000000..2e4bdc3 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/dataset/DataSet.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.api.dataset; + +import org.qi4j.functional.Function; +import org.qi4j.functional.Specification; + +/** + * definition.constrain(entity(Person.class)) + * builder.from(path(Person.class,Movie.)) + * TODO + */ +public interface DataSet<T> +{ + DataSet<T> constrain( Specification<T> selection ); + + <U> DataSet<U> project( Function<T, U> conversion ); + + Query<T> newQuery(); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/dataset/DataSetSource.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/dataset/DataSetSource.java b/core/api/src/main/java/org/qi4j/api/dataset/DataSetSource.java new file mode 100644 index 0000000..4cf68f1 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/dataset/DataSetSource.java @@ -0,0 +1,27 @@ +/* + * 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.dataset; + +/** + * TODO + */ +public interface DataSetSource +{ + <T> DataSet<T> newDataSet( Class<T> type ); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/dataset/Query.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/dataset/Query.java b/core/api/src/main/java/org/qi4j/api/dataset/Query.java new file mode 100644 index 0000000..61edd73 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/dataset/Query.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.api.dataset; + +import org.qi4j.api.property.Property; +import org.qi4j.api.query.QueryException; +import org.qi4j.api.query.QueryExecutionException; +import org.qi4j.functional.Specification; +import org.qi4j.functional.Visitor; + +/** + * TODO + */ +public interface Query<T> +{ + public enum Order + { + ASCENDING, DESCENDING + } + + Query filter( Specification<T> filter ); + + Query orderBy( final Property<?> property, final Order order ); + + Query skip( int skipNrOfResults ); + + Query limit( int maxNrOfResults ); + + // Variables + Query<T> setVariable( String name, Object value ); + + Object getVariable( String name ); + + long count() + throws QueryExecutionException; + + T first() + throws QueryExecutionException; + + T single() + throws QueryException; + + <ThrowableType extends Throwable> boolean execute( Visitor<T, ThrowableType> resultVisitor ) + throws ThrowableType, QueryExecutionException; + + Iterable<T> toIterable() + throws QueryExecutionException; +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableDataSet.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableDataSet.java b/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableDataSet.java new file mode 100644 index 0000000..3300ea4 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableDataSet.java @@ -0,0 +1,57 @@ +/* + * 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.dataset.iterable; + +import org.qi4j.api.dataset.DataSet; +import org.qi4j.api.dataset.Query; +import org.qi4j.functional.Function; +import org.qi4j.functional.Iterables; +import org.qi4j.functional.Specification; + +/** + * TODO + */ +public class IterableDataSet<T> + implements DataSet<T> +{ + private Iterable<T> iterable; + + public IterableDataSet( Iterable<T> iterable ) + { + this.iterable = iterable; + } + + @Override + public DataSet<T> constrain( Specification<T> selection ) + { + return new IterableDataSet<T>( Iterables.filter( selection, iterable ) ); + } + + @Override + public <U> DataSet<U> project( Function<T, U> conversion ) + { + return new IterableDataSet<U>( Iterables.map( conversion, iterable ) ); + } + + @Override + public Query<T> newQuery() + { + return new IterableQuery<T>( iterable ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableQuery.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableQuery.java b/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableQuery.java new file mode 100644 index 0000000..b816a25 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableQuery.java @@ -0,0 +1,127 @@ +/* + * 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.dataset.iterable; + +import java.util.HashMap; +import java.util.Map; +import org.qi4j.api.dataset.Query; +import org.qi4j.api.property.Property; +import org.qi4j.api.query.QueryException; +import org.qi4j.functional.Iterables; +import org.qi4j.functional.Specification; +import org.qi4j.functional.Visitor; + +/** + * TODO + */ +public class IterableQuery<T> implements Query<T> +{ + private Iterable<T> iterable; + private int skip; + private int limit; + private Map<String, Object> variables = new HashMap<String, Object>(); + + public IterableQuery( Iterable<T> iterable ) + { + this.iterable = iterable; + } + + @Override + public Query filter( Specification<T> filter ) + { + iterable = Iterables.filter( filter, iterable ); + + return this; + } + + @Override + public Query orderBy( Property<?> property, Order order ) + { + return this; + } + + @Override + public Query skip( int skipNrOfResults ) + { + this.skip = skipNrOfResults; + + return this; + } + + @Override + public Query limit( int maxNrOfResults ) + { + this.limit = maxNrOfResults; + return this; + } + + @Override + public Query<T> setVariable( String name, Object value ) + { + variables.put( name, value ); + return this; + } + + @Override + public Object getVariable( String name ) + { + return variables.get( name ); + } + + @Override + public long count() + { + return Iterables.count( Iterables.limit( limit, Iterables.skip( skip, iterable ) ) ); + } + + @Override + public T first() + { + return Iterables.first( Iterables.limit( limit, Iterables.skip( skip, iterable ) ) ); + } + + @Override + public T single() + throws QueryException + { + return Iterables.single( Iterables.limit( limit, Iterables.skip( skip, iterable ) ) ); + } + + @Override + public <ThrowableType extends Throwable> boolean execute( Visitor<T, ThrowableType> resultVisitor ) + throws ThrowableType + { + for( T t : toIterable() ) + { + if( !resultVisitor.visit( t ) ) + { + return false; + } + } + + return true; + } + + @Override + public Iterable<T> toIterable() + throws QueryException + { + return Iterables.limit( limit, Iterables.skip( skip, iterable ) ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/dataset/iterable/package.html ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/dataset/iterable/package.html b/core/api/src/main/java/org/qi4j/api/dataset/iterable/package.html new file mode 100644 index 0000000..9874cb5 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/dataset/iterable/package.html @@ -0,0 +1,21 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> +<html> + <body> + <h2>Iterable DataSets.</h2> + </body> +</html> http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/dataset/package.html ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/dataset/package.html b/core/api/src/main/java/org/qi4j/api/dataset/package.html new file mode 100644 index 0000000..f324682 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/dataset/package.html @@ -0,0 +1,21 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> +<html> + <body> + <h2>DataSet API.</h2> + </body> +</html> http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/entity/Aggregated.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/entity/Aggregated.java b/core/api/src/main/java/org/qi4j/api/entity/Aggregated.java new file mode 100644 index 0000000..11e4ba5 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/entity/Aggregated.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2009, Rickard Ãberg. 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.api.entity; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks an association as aggregating the referenced Entities + */ +@Retention( RetentionPolicy.RUNTIME ) +@Target( { ElementType.METHOD } ) +@Documented +public @interface Aggregated +{ +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/entity/EntityBuilder.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/entity/EntityBuilder.java b/core/api/src/main/java/org/qi4j/api/entity/EntityBuilder.java new file mode 100644 index 0000000..7020253 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/entity/EntityBuilder.java @@ -0,0 +1,60 @@ +/* Copyright 2007 Niclas Hedhman. + * + * 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.api.entity; + +import org.qi4j.api.common.ConstructionException; + +/** + * EntityBuilders are used to instantiate EntityComposites. They can be acquired from + * {@link org.qi4j.api.unitofwork.UnitOfWork#newEntityBuilder(Class)} and allows the client + * to provide additional settings before instantiating the Composite. + * + * After calling newInstance() the builder becomes invalid, and may not be called again. + */ +public interface EntityBuilder<T> +{ + /** + * Get a representation of the state for the new Composite. + * It is possible to access and update properties and associations, + * even immutable ones since the builder represents the initial state. + * + * @return a proxy implementing the Composite type + */ + T instance(); + + /** + * Get a representation of the state of the given type for the new Composite. + * This is primarily used if you want to provide state for a private mixin type. + * + * @param mixinType the mixin which you want to provide state for + * + * @return a proxy implementing the given mixin type + */ + <K> K instanceFor( Class<K> mixinType ); + + /** + * Create a new Entity instance. + * + * @return a new Entity instance + * + * @throws org.qi4j.api.common.ConstructionException + * thrown if it was not possible to instantiate the Composite + * @throws LifecycleException if the entity could not be created + */ + T newInstance() + throws ConstructionException, LifecycleException; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/entity/EntityBuilderTemplate.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/entity/EntityBuilderTemplate.java b/core/api/src/main/java/org/qi4j/api/entity/EntityBuilderTemplate.java new file mode 100644 index 0000000..4473844 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/entity/EntityBuilderTemplate.java @@ -0,0 +1,43 @@ +/* + * 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.entity; + +import org.qi4j.api.structure.Module; + +/** + * EntityBuilderTemplate. + */ +public abstract class EntityBuilderTemplate<T> +{ + Class<T> type; + + protected EntityBuilderTemplate( Class<T> type ) + { + this.type = type; + } + + protected abstract void build( T prototype ); + + public T newInstance( Module module ) + { + EntityBuilder<T> builder = module.currentUnitOfWork().newEntityBuilder( type ); + build( builder.instance() ); + return builder.newInstance(); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/entity/EntityComposite.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/entity/EntityComposite.java b/core/api/src/main/java/org/qi4j/api/entity/EntityComposite.java new file mode 100644 index 0000000..93089b8 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/entity/EntityComposite.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2007, Rickard Ãberg. All Rights Reserved. + * Copyright (c) 2007, Niclas Hedhman. 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.api.entity; + +import org.qi4j.api.association.AssociationMixin; +import org.qi4j.api.association.ManyAssociationMixin; +import org.qi4j.api.association.NamedAssociationMixin; +import org.qi4j.api.composite.Composite; +import org.qi4j.api.mixin.Mixins; + +/** + * EntityComposites are Composites that has mutable state persisted in EntityStores and equality defined from its + * identity. + */ +@Mixins( { AssociationMixin.class, ManyAssociationMixin.class, NamedAssociationMixin.class } ) +public interface EntityComposite + extends Identity, Composite +{ +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/entity/EntityDescriptor.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/entity/EntityDescriptor.java b/core/api/src/main/java/org/qi4j/api/entity/EntityDescriptor.java new file mode 100644 index 0000000..6ce2500 --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/entity/EntityDescriptor.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2008, Rickard Ãberg. 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.api.entity; + +import org.qi4j.api.association.AssociationStateDescriptor; +import org.qi4j.api.composite.CompositeDescriptor; +import org.qi4j.api.composite.StatefulCompositeDescriptor; + +/** + * Entity Descriptor. + */ +public interface EntityDescriptor + extends CompositeDescriptor, StatefulCompositeDescriptor +{ + @Override + AssociationStateDescriptor state(); + + boolean queryable(); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java b/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java new file mode 100644 index 0000000..967647c --- /dev/null +++ b/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2007, Rickard Ãberg. 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.api.entity; + +import java.io.Serializable; +import org.qi4j.api.util.NullArgumentException; + +/** + * An EntityReference is identity of a specific Entity instance. + * <p>When stringified, the identity is used as-is. Example:</p> + * <pre>123456-abcde</pre> + */ +public final class EntityReference + implements Serializable +{ + /** + * Parse an URI to an EntityReference. + * @param uri the URI to parse + * @return the EntityReference represented by the given URI + */ + public static EntityReference parseURI( String uri ) + { + String identity = uri.substring( "urn:qi4j:entity:".length() ); + return new EntityReference( identity ); + } + + /** + * Parse an Entity identity to an EntityReference. + * @param identity the EntityReference identity + * @return the EntityReference represented by the given identity + */ + public static EntityReference parseEntityReference( String identity ) + { + return new EntityReference( identity ); + } + + /** + * @param object an EntityComposite + * @return the EntityReference for the given EntityComposite + */ + public static EntityReference entityReferenceFor( Object object ) + { + return new EntityReference( (EntityComposite) object ); + } + + public static EntityReference create( Identity identity ) + { + if( identity == null ) + return null; + return new EntityReference( identity.identity().get() ); + } + + private static final long serialVersionUID = 1L; + + private String identity; + + /** + * @param entityComposite a non-null EntityComposite + * @throws NullPointerException if entityComposite is null + */ + public EntityReference( EntityComposite entityComposite ) + { + this( entityComposite.identity().get() ); + } + + /** + * @param identity reference identity + * @throws NullArgumentException if identity is null or empty + */ + public EntityReference( String identity ) + { + NullArgumentException.validateNotEmpty( "identity", identity ); + this.identity = identity; + } + + /** + * @return This EntityReference identity. + */ + public final String identity() + { + return identity; + } + + /** + * @return An URI representation of this EntityReference. + */ + public String toURI() + { + return "urn:qi4j:entity:" + identity; + } + + @Override + public boolean equals( Object o ) + { + if( this == o ) + { + return true; + } + if( o == null || getClass() != o.getClass() ) + { + return false; + } + EntityReference that = (EntityReference) o; + return identity.equals( that.identity ); + } + + @Override + public int hashCode() + { + return identity.hashCode(); + } + + /** + * @return This EntityReference identity. + */ + @Override + public String toString() + { + return identity; + } +}