Repository: incubator-brooklyn Updated Branches: refs/heads/master bf627f76a -> 4891355f7
extract an AbstractBrooklynObjectSpec to combine common spec code Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/98a37f07 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/98a37f07 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/98a37f07 Branch: refs/heads/master Commit: 98a37f07a17ae307ecc4f362f47a19cc4119af2e Parents: 7d2d42b Author: Alex Heneveld <[email protected]> Authored: Fri Aug 1 15:27:09 2014 -0400 Committer: Alex Heneveld <[email protected]> Committed: Tue Aug 5 10:40:30 2014 -0400 ---------------------------------------------------------------------- .../basic/AbstractBrooklynObjectSpec.java | 92 ++++++++++++++++++++ .../brooklyn/entity/proxying/EntitySpec.java | 61 ++----------- .../java/brooklyn/location/LocationSpec.java | 63 ++------------ .../main/java/brooklyn/policy/EnricherSpec.java | 60 ++----------- .../main/java/brooklyn/policy/PolicySpec.java | 60 ++----------- 5 files changed, 122 insertions(+), 214 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/98a37f07/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java b/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java new file mode 100644 index 0000000..d61e016 --- /dev/null +++ b/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java @@ -0,0 +1,92 @@ +/* + * 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 brooklyn.basic; + +import java.io.Serializable; +import java.lang.reflect.Modifier; + +import brooklyn.util.exceptions.Exceptions; + +import com.google.common.base.Objects; + +public abstract class AbstractBrooklynObjectSpec<T,K extends AbstractBrooklynObjectSpec<T,K>> implements Serializable { + + private static final long serialVersionUID = 3010955277740333030L; + + private final Class<T> type; + private String displayName; + + protected AbstractBrooklynObjectSpec(Class<T> type) { + checkValidType(type); + this.type = type; + } + + @SuppressWarnings("unchecked") + protected final K self() { + return (K) this; + } + + @Override + public String toString() { + return Objects.toStringHelper(this).add("type", getType()).toString(); + } + + protected abstract void checkValidType(Class<T> type); + + public K displayName(String val) { + displayName = val; + return self(); + } + + /** + * @return The type of the enricher + */ + public final Class<T> getType() { + return type; + } + + /** + * @return The display name of the enricher + */ + public final String getDisplayName() { + return displayName; + } + + // TODO Duplicates method in BasicEntityTypeRegistry and InternalEntityFactory.isNewStyleEntity + protected final void checkIsNewStyleImplementation(Class<?> implClazz) { + try { + implClazz.getConstructor(new Class[0]); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Implementation "+implClazz+" must have a no-argument constructor"); + } catch (SecurityException e) { + throw Exceptions.propagate(e); + } + + if (implClazz.isInterface()) throw new IllegalStateException("Implementation "+implClazz+" is an interface, but must be a non-abstract class"); + if (Modifier.isAbstract(implClazz.getModifiers())) throw new IllegalStateException("Implementation "+implClazz+" is abstract, but must be a non-abstract class"); + } + + // TODO Duplicates method in BasicEntityTypeRegistry + protected final void checkIsImplementation(Class<?> val, Class<? super T> requiredInterface) { + if (!requiredInterface.isAssignableFrom(val)) throw new IllegalStateException("Implementation "+val+" does not implement "+requiredInterface.getName()); + if (val.isInterface()) throw new IllegalStateException("Implementation "+val+" is an interface, but must be a non-abstract class"); + if (Modifier.isAbstract(val.getModifiers())) throw new IllegalStateException("Implementation "+val+" is abstract, but must be a non-abstract class"); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/98a37f07/api/src/main/java/brooklyn/entity/proxying/EntitySpec.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/brooklyn/entity/proxying/EntitySpec.java b/api/src/main/java/brooklyn/entity/proxying/EntitySpec.java index a141d60..daaa6c8 100644 --- a/api/src/main/java/brooklyn/entity/proxying/EntitySpec.java +++ b/api/src/main/java/brooklyn/entity/proxying/EntitySpec.java @@ -20,8 +20,6 @@ package brooklyn.entity.proxying; import static com.google.common.base.Preconditions.checkNotNull; -import java.io.Serializable; -import java.lang.reflect.Modifier; import java.util.Collections; import java.util.List; import java.util.Map; @@ -32,6 +30,7 @@ import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import brooklyn.basic.AbstractBrooklynObjectSpec; import brooklyn.config.ConfigKey; import brooklyn.config.ConfigKey.HasConfigKey; import brooklyn.entity.Entity; @@ -42,9 +41,7 @@ import brooklyn.policy.Enricher; import brooklyn.policy.EnricherSpec; import brooklyn.policy.Policy; import brooklyn.policy.PolicySpec; -import brooklyn.util.exceptions.Exceptions; -import com.google.common.base.Objects; import com.google.common.base.Throwables; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -63,7 +60,7 @@ import com.google.common.collect.Sets; * * @author aled */ -public class EntitySpec<T extends Entity> implements Serializable { +public class EntitySpec<T extends Entity> extends AbstractBrooklynObjectSpec<T,EntitySpec<T>> { private static final long serialVersionUID = -2247153452919128990L; @@ -131,9 +128,8 @@ public class EntitySpec<T extends Entity> implements Serializable { return new EntitySpec<T>(type); } - private final Class<T> type; private String id; - private String displayName; + private Class<? extends T> impl; private Entity parent; private final Map<String, Object> flags = Maps.newLinkedHashMap(); @@ -151,14 +147,12 @@ public class EntitySpec<T extends Entity> implements Serializable { private volatile boolean immutable; public EntitySpec(Class<T> type) { - this.type = type; + super(type); } - /** - * @return The type of the entity - */ - public Class<T> getType() { - return type; + @Override + protected void checkValidType(Class<T> type) { + // EntitySpec does nothing. Other specs do check it's an implementation etc. } /** @@ -172,13 +166,6 @@ public class EntitySpec<T extends Entity> implements Serializable { } /** - * @return The display name of the entity - */ - public String getDisplayName() { - return displayName; - } - - /** * @return The implementation of the entity; if not null. this overrides any defaults or other configuration * * @see ImplementedBy on the entity interface classes for how defaults are defined. @@ -266,15 +253,9 @@ public class EntitySpec<T extends Entity> implements Serializable { return this; } - public EntitySpec<T> displayName(String val) { - checkMutable(); - displayName = val; - return this; - } - public EntitySpec<T> impl(Class<? extends T> val) { checkMutable(); - checkIsImplementation(checkNotNull(val, "impl")); + checkIsImplementation(checkNotNull(val, "impl"), getType()); checkIsNewStyleImplementation(val); impl = val; return this; @@ -486,34 +467,8 @@ public class EntitySpec<T extends Entity> implements Serializable { return this; } - @Override - public String toString() { - return Objects.toStringHelper(this).add("type", type).toString(); - } - private void checkMutable() { if (immutable) throw new IllegalStateException("Cannot modify immutable entity spec "+this); } - // TODO Duplicates method in BasicEntityTypeRegistry - private void checkIsImplementation(Class<?> val) { - if (!type.isAssignableFrom(val)) throw new IllegalStateException("Implementation "+val+" does not implement "+type); - if (val.isInterface()) throw new IllegalStateException("Implementation "+val+" is an interface, but must be a non-abstract class"); - if (Modifier.isAbstract(val.getModifiers())) throw new IllegalStateException("Implementation "+val+" is abstract, but must be a non-abstract class"); - } - - // TODO Duplicates method in BasicEntityTypeRegistry, and InternalEntityFactory.isNewStyleEntity - private void checkIsNewStyleImplementation(Class<?> implClazz) { - try { - implClazz.getConstructor(new Class[0]); - } catch (NoSuchMethodException e) { - throw new IllegalStateException("Implementation "+implClazz+" must have a no-argument constructor"); - } catch (SecurityException e) { - throw Exceptions.propagate(e); - } - - if (implClazz.isInterface()) throw new IllegalStateException("Implementation "+implClazz+" is an interface, but must be a non-abstract class"); - if (Modifier.isAbstract(implClazz.getModifiers())) throw new IllegalStateException("Implementation "+implClazz+" is abstract, but must be a non-abstract class"); - } - } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/98a37f07/api/src/main/java/brooklyn/location/LocationSpec.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/brooklyn/location/LocationSpec.java b/api/src/main/java/brooklyn/location/LocationSpec.java index ce280c8..f34d1a2 100644 --- a/api/src/main/java/brooklyn/location/LocationSpec.java +++ b/api/src/main/java/brooklyn/location/LocationSpec.java @@ -20,20 +20,17 @@ package brooklyn.location; import static com.google.common.base.Preconditions.checkNotNull; -import java.io.Serializable; -import java.lang.reflect.Modifier; import java.util.Collections; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import brooklyn.basic.AbstractBrooklynObjectSpec; import brooklyn.config.ConfigKey; import brooklyn.config.ConfigKey.HasConfigKey; import brooklyn.management.Task; -import brooklyn.util.exceptions.Exceptions; -import com.google.common.base.Objects; import com.google.common.collect.Maps; /** @@ -46,7 +43,7 @@ import com.google.common.collect.Maps; * * @author aled */ -public class LocationSpec<T extends Location> implements Serializable { +public class LocationSpec<T extends Location> extends AbstractBrooklynObjectSpec<T,LocationSpec<T>> { // TODO Would like to add `configure(ConfigBag)`, but `ConfigBag` is in core rather than api @@ -76,18 +73,19 @@ public class LocationSpec<T extends Location> implements Serializable { return LocationSpec.create(type).configure(config); } - private final Class<T> type; private String id; - private String displayName; private Location parent; private final Map<String, Object> flags = Maps.newLinkedHashMap(); private final Map<ConfigKey<?>, Object> config = Maps.newLinkedHashMap(); private final Map<Class<?>, Object> extensions = Maps.newLinkedHashMap(); protected LocationSpec(Class<T> type) { - checkIsImplementation(type); + super(type); + } + + protected void checkValidType(java.lang.Class<T> type) { + checkIsImplementation(type, Location.class); checkIsNewStyleImplementation(type); - this.type = type; } /** @@ -99,11 +97,6 @@ public class LocationSpec<T extends Location> implements Serializable { return this; } - public LocationSpec<T> displayName(String val) { - displayName = val; - return this; - } - public LocationSpec<T> parent(Location val) { parent = checkNotNull(val, "parent"); return this; @@ -165,13 +158,6 @@ public class LocationSpec<T extends Location> implements Serializable { } /** - * @return The type of the location - */ - public Class<T> getType() { - return type; - } - - /** * @return The id of the location to be created, or null if brooklyn can auto-generate an id * * @deprecated since 0.7.0; instead let the management context pick a random+unique id @@ -182,13 +168,6 @@ public class LocationSpec<T extends Location> implements Serializable { } /** - * @return The display name of the location - */ - public String getDisplayName() { - return displayName; - } - - /** * @return The location's parent */ public Location getParent() { @@ -216,31 +195,5 @@ public class LocationSpec<T extends Location> implements Serializable { public Map<Class<?>, Object> getExtensions() { return Collections.unmodifiableMap(extensions); } - - - @Override - public String toString() { - return Objects.toStringHelper(this).add("type", type).toString(); - } - - // TODO Duplicates method in EntitySpec and BasicEntityTypeRegistry - private void checkIsImplementation(Class<?> val) { - if (!Location.class.isAssignableFrom(val)) throw new IllegalStateException("Implementation "+val+" does not implement "+Location.class.getName()); - if (val.isInterface()) throw new IllegalStateException("Implementation "+val+" is an interface, but must be a non-abstract class"); - if (Modifier.isAbstract(val.getModifiers())) throw new IllegalStateException("Implementation "+val+" is abstract, but must be a non-abstract class"); - } - - // TODO Duplicates method in EntitySpec, BasicEntityTypeRegistry, and InternalEntityFactory.isNewStyleEntity - private void checkIsNewStyleImplementation(Class<?> implClazz) { - try { - implClazz.getConstructor(new Class[0]); - } catch (NoSuchMethodException e) { - throw new IllegalStateException("Implementation "+implClazz+" must have a no-argument constructor"); - } catch (SecurityException e) { - throw Exceptions.propagate(e); - } - - if (implClazz.isInterface()) throw new IllegalStateException("Implementation "+implClazz+" is an interface, but must be a non-abstract class"); - if (Modifier.isAbstract(implClazz.getModifiers())) throw new IllegalStateException("Implementation "+implClazz+" is abstract, but must be a non-abstract class"); - } + } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/98a37f07/api/src/main/java/brooklyn/policy/EnricherSpec.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/brooklyn/policy/EnricherSpec.java b/api/src/main/java/brooklyn/policy/EnricherSpec.java index 36851df..43f1a85 100644 --- a/api/src/main/java/brooklyn/policy/EnricherSpec.java +++ b/api/src/main/java/brooklyn/policy/EnricherSpec.java @@ -20,20 +20,17 @@ package brooklyn.policy; import static com.google.common.base.Preconditions.checkNotNull; -import java.io.Serializable; -import java.lang.reflect.Modifier; import java.util.Collections; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import brooklyn.basic.AbstractBrooklynObjectSpec; import brooklyn.config.ConfigKey; import brooklyn.config.ConfigKey.HasConfigKey; import brooklyn.management.Task; -import brooklyn.util.exceptions.Exceptions; -import com.google.common.base.Objects; import com.google.common.collect.Maps; /** @@ -46,7 +43,7 @@ import com.google.common.collect.Maps; * * @author aled */ -public class EnricherSpec<T extends Enricher> implements Serializable { +public class EnricherSpec<T extends Enricher> extends AbstractBrooklynObjectSpec<T,EnricherSpec<T>> { private static final Logger log = LoggerFactory.getLogger(EnricherSpec.class); @@ -75,22 +72,18 @@ public class EnricherSpec<T extends Enricher> implements Serializable { return EnricherSpec.create(type).configure(config); } - private final Class<T> type; - private String displayName; private final Map<String, Object> flags = Maps.newLinkedHashMap(); private final Map<ConfigKey<?>, Object> config = Maps.newLinkedHashMap(); protected EnricherSpec(Class<T> type) { - checkIsImplementation(type); - checkIsNewStyleImplementation(type); - this.type = type; + super(type); } - public EnricherSpec<T> displayName(String val) { - displayName = val; - return this; + protected void checkValidType(Class<T> type) { + checkIsImplementation(type, Enricher.class); + checkIsNewStyleImplementation(type); } - + public EnricherSpec<T> configure(Map<?,?> val) { for (Map.Entry<?, ?> entry: val.entrySet()) { if (entry.getKey()==null) throw new NullPointerException("Null key not permitted"); @@ -137,20 +130,6 @@ public class EnricherSpec<T extends Enricher> implements Serializable { } /** - * @return The type of the enricher - */ - public Class<T> getType() { - return type; - } - - /** - * @return The display name of the enricher - */ - public String getDisplayName() { - return displayName; - } - - /** * @return Read-only construction flags * @see SetFromFlag declarations on the enricher type */ @@ -164,30 +143,5 @@ public class EnricherSpec<T extends Enricher> implements Serializable { public Map<ConfigKey<?>, Object> getConfig() { return Collections.unmodifiableMap(config); } - - @Override - public String toString() { - return Objects.toStringHelper(this).add("type", type).toString(); - } - - // TODO Duplicates method in EntitySpec and BasicEntityTypeRegistry - private void checkIsImplementation(Class<?> val) { - if (!Enricher.class.isAssignableFrom(val)) throw new IllegalStateException("Implementation "+val+" does not implement "+Enricher.class.getName()); - if (val.isInterface()) throw new IllegalStateException("Implementation "+val+" is an interface, but must be a non-abstract class"); - if (Modifier.isAbstract(val.getModifiers())) throw new IllegalStateException("Implementation "+val+" is abstract, but must be a non-abstract class"); - } - // TODO Duplicates method in EntitySpec, BasicEntityTypeRegistry, and InternalEntityFactory.isNewStyleEntity - private void checkIsNewStyleImplementation(Class<?> implClazz) { - try { - implClazz.getConstructor(new Class[0]); - } catch (NoSuchMethodException e) { - throw new IllegalStateException("Implementation "+implClazz+" must have a no-argument constructor"); - } catch (SecurityException e) { - throw Exceptions.propagate(e); - } - - if (implClazz.isInterface()) throw new IllegalStateException("Implementation "+implClazz+" is an interface, but must be a non-abstract class"); - if (Modifier.isAbstract(implClazz.getModifiers())) throw new IllegalStateException("Implementation "+implClazz+" is abstract, but must be a non-abstract class"); - } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/98a37f07/api/src/main/java/brooklyn/policy/PolicySpec.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/brooklyn/policy/PolicySpec.java b/api/src/main/java/brooklyn/policy/PolicySpec.java index 310e867..ccce6e0 100644 --- a/api/src/main/java/brooklyn/policy/PolicySpec.java +++ b/api/src/main/java/brooklyn/policy/PolicySpec.java @@ -20,20 +20,17 @@ package brooklyn.policy; import static com.google.common.base.Preconditions.checkNotNull; -import java.io.Serializable; -import java.lang.reflect.Modifier; import java.util.Collections; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import brooklyn.basic.AbstractBrooklynObjectSpec; import brooklyn.config.ConfigKey; import brooklyn.config.ConfigKey.HasConfigKey; import brooklyn.management.Task; -import brooklyn.util.exceptions.Exceptions; -import com.google.common.base.Objects; import com.google.common.collect.Maps; /** @@ -46,7 +43,7 @@ import com.google.common.collect.Maps; * * @author aled */ -public class PolicySpec<T extends Policy> implements Serializable { +public class PolicySpec<T extends Policy> extends AbstractBrooklynObjectSpec<T,PolicySpec<T>> { private static final Logger log = LoggerFactory.getLogger(PolicySpec.class); @@ -75,22 +72,18 @@ public class PolicySpec<T extends Policy> implements Serializable { return PolicySpec.create(type).configure(config); } - private final Class<T> type; - private String displayName; private final Map<String, Object> flags = Maps.newLinkedHashMap(); private final Map<ConfigKey<?>, Object> config = Maps.newLinkedHashMap(); protected PolicySpec(Class<T> type) { - checkIsImplementation(type); - checkIsNewStyleImplementation(type); - this.type = type; + super(type); } - public PolicySpec<T> displayName(String val) { - displayName = val; - return this; + protected void checkValidType(Class<T> type) { + checkIsImplementation(type, Policy.class); + checkIsNewStyleImplementation(type); } - + public PolicySpec<T> configure(Map<?,?> val) { for (Map.Entry<?, ?> entry: val.entrySet()) { if (entry.getKey()==null) throw new NullPointerException("Null key not permitted"); @@ -137,20 +130,6 @@ public class PolicySpec<T extends Policy> implements Serializable { } /** - * @return The type of the policy - */ - public Class<T> getType() { - return type; - } - - /** - * @return The display name of the policy - */ - public String getDisplayName() { - return displayName; - } - - /** * @return Read-only construction flags * @see SetFromFlag declarations on the policy type */ @@ -165,29 +144,4 @@ public class PolicySpec<T extends Policy> implements Serializable { return Collections.unmodifiableMap(config); } - @Override - public String toString() { - return Objects.toStringHelper(this).add("type", type).toString(); - } - - // TODO Duplicates method in EntitySpec and BasicEntityTypeRegistry - private void checkIsImplementation(Class<?> val) { - if (!Policy.class.isAssignableFrom(val)) throw new IllegalStateException("Implementation "+val+" does not implement "+Policy.class.getName()); - if (val.isInterface()) throw new IllegalStateException("Implementation "+val+" is an interface, but must be a non-abstract class"); - if (Modifier.isAbstract(val.getModifiers())) throw new IllegalStateException("Implementation "+val+" is abstract, but must be a non-abstract class"); - } - - // TODO Duplicates method in EntitySpec, BasicEntityTypeRegistry, and InternalEntityFactory.isNewStyleEntity - private void checkIsNewStyleImplementation(Class<?> implClazz) { - try { - implClazz.getConstructor(new Class[0]); - } catch (NoSuchMethodException e) { - throw new IllegalStateException("Implementation "+implClazz+" must have a no-argument constructor"); - } catch (SecurityException e) { - throw Exceptions.propagate(e); - } - - if (implClazz.isInterface()) throw new IllegalStateException("Implementation "+implClazz+" is an interface, but must be a non-abstract class"); - if (Modifier.isAbstract(implClazz.getModifiers())) throw new IllegalStateException("Implementation "+implClazz+" is abstract, but must be a non-abstract class"); - } }
