org.deephacks.tools4j.config.model.Schema Maven / Gradle / Ivy
/**
* 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.deephacks.tools4j.config.model;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static com.google.common.base.Objects.equal;
/**
*
* Schema is used to provide information to administrative users in order to explain
* its purpose and how configuration changes may affect system behaviour.
*
*
* Schemas are handled by the framework and are not intended for spontaneous creation or
* modification by any user. Schemas originate from when a configurable class is registered
* in the system and are considered read-only entities.
*
*
* @author Kristoffer Sjogren
*/
public final class Schema implements Serializable {
private static final long serialVersionUID = -2914939410489202548L;
private SchemaId id;
private final String name;
private final String type;
private final String description;
private Multimap, AbstractSchemaProperty> properties = HashMultimap
.create();
private Schema(final SchemaId id, final String type, final String name, final String description) {
this.id = Preconditions.checkNotNull(id);
this.type = Preconditions.checkNotNull(type);
this.description = Preconditions.checkNotNull(description);
this.name = Preconditions.checkNotNull(name);
}
/**
* Creates a new schema. Not to be used by users, schemas are created when a configurable class are
* registered in the system.
*
* @param id that identify this schema.
* @param classType classname that fully qualifies the configurable class that this schema originates from.
* @param name of this schema as specified in meta data, names must be unique.
* @param description purpose and useful information needed in order to manage this schema.
* @return A Schema.
*/
public static Schema create(SchemaId id, final String classType, final String name,
final String description) {
return new Schema(id, classType, name, description);
}
/**
* Identification for this this schema. This id must be unqiue in the system.
*
* @return id for this schema.
*/
public SchemaId getId() {
return id;
}
/**
* This is the fully qualified classname of the configurable class that this schema originates from.
*
* Do not display this property to end users, use the 'name' property instead .
*
* @return A full class name.
*/
public final String getType() {
return type;
}
/**
* This is the fully qualified classname of the configurable class that this schema originates from.
*
* @return Class of this schema.
*/
public Class> getClassType() {
try {
return Class.forName(getType());
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
/**
* Description that justify the existence of the schema by putting it into a
* high-level context and describe how it relates to system concepts.
*
* @return description
*/
public final String getDesc() {
return description;
}
/**
* A unique name that identifies the schema in the system. Good names are those
* which describe domain specific aspects established in the system architecture.
*
* @return name
*/
public final String getName() {
return name;
}
/**
* Adds a property of a specific type to this schema. Not to be used by users.
*
* @param property property
*/
public void add(AbstractSchemaProperty property) {
properties.put(property.getClass(), property);
}
/**
* Returns all properties that have been marked as indexed.
*
* @param type
* @return a list of properties.
*/
public Set getIndexed() {
HashSet indexed = new HashSet<>();
for (AbstractSchemaProperty prop : properties.values()) {
if (prop.isIndexed()) indexed.add(prop);
}
return (Set) indexed;
}
/**
* Returns all the properties of a particular type.
*
* @param clazz The specific type of properties to get.
* @return A list of properties that matches the clazz.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public Set get(final Class clazz) {
return (Set) properties.get(clazz);
}
public String getReferenceSchemaName(String propertyName) {
for (AbstractSchemaProperty schema : properties.values()) {
if (!schema.getFieldName().equals(propertyName)) {
continue;
}
if (schema instanceof SchemaPropertyRef) {
return ((SchemaPropertyRef) schema).getSchemaName();
}
if (schema instanceof SchemaPropertyRefList) {
return ((SchemaPropertyRefList) schema).getSchemaName();
}
if (schema instanceof SchemaPropertyRefMap) {
return ((SchemaPropertyRefMap) schema).getSchemaName();
}
}
return null;
}
/**
* Returns a specific properties of a particular type identified with a name.
*
* @param clazz specific type of property to get.
* @param name The AbstractSchemaProperty name of the property.
* @return Matching property.
*/
public T get(final Class clazz, final String name) {
Set propertyCollection = get(clazz);
for (T property : propertyCollection) {
if (property.getName().equals(name)) {
return property;
}
}
return null;
}
/**
* Returns all property names that exist for this schema.
*/
public Set getPropertyNames() {
Set names = new HashSet<>();
for (AbstractSchemaProperty prop : get(SchemaProperty.class)) {
names.add(prop.getName());
}
for (AbstractSchemaProperty prop : get(SchemaPropertyList.class)) {
names.add(prop.getName());
}
return names;
}
/**
* Returns all reference names that exist for this schema.
*/
public Set getReferenceNames() {
Set names = new HashSet<>();
for (AbstractSchemaProperty prop : get(SchemaPropertyRef.class)) {
names.add(prop.getName());
}
for (AbstractSchemaProperty prop : get(SchemaPropertyRefList.class)) {
names.add(prop.getName());
}
for (AbstractSchemaProperty prop : get(SchemaPropertyRefMap.class)) {
names.add(prop.getName());
}
return names;
}
public String toString() {
return Objects.toStringHelper(Schema.class).add("id", id).add("name", getName())
.add("type", getType()).add("desc", getDesc()).add("properties", properties)
.toString();
}
@Override
public int hashCode() {
return Objects.hashCode(properties, getType(), getDesc(), getName());
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Schema)) {
return false;
}
Schema o = (Schema) obj;
return equal(getName(), o.getName()) && equal(getType(), o.getType());
}
public boolean isReference(String property) {
return getReferenceNames().contains(property);
}
public boolean isProperty(String property) {
return getPropertyNames().contains(property);
}
/**
* Description of the identification of a a particular schema registered
* in the system.
*/
public static class SchemaId implements Serializable {
private static final long serialVersionUID = 5803256931889425514L;
private final String name;
private final String desc;
private boolean isSingleton;
private SchemaId(final String name, final String desc, final boolean isSingleton) {
this.name = Preconditions.checkNotNull(name);
this.desc = Preconditions.checkNotNull(desc);
this.isSingleton = isSingleton;
}
public static SchemaId create(final String name, final String desc,
final boolean isSingleton) {
return new SchemaId(name, desc, isSingleton);
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
public boolean isSingleton() {
return isSingleton;
}
public String toString() {
return Objects.toStringHelper(SchemaId.class).add("id", getName())
.add("desc", getDesc()).toString();
}
@Override
public int hashCode() {
return Objects.hashCode(getName(), getDesc());
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SchemaId)) {
return false;
}
SchemaId o = (SchemaId) obj;
return equal(getName(), o.getName()) && equal(getDesc(), o.getDesc());
}
}
/**
* Abstract base class for schema properties.
*/
public static class AbstractSchemaProperty implements Serializable {
private static final long serialVersionUID = -3057627766413883885L;
private String name;
private String desc;
private String fieldName;
private boolean isImmutable;
private boolean indexed;
protected AbstractSchemaProperty(final String name, final String fieldName,
final String desc, final boolean isimmutable, final boolean indexed) {
this.name = Preconditions.checkNotNull(name);
this.fieldName = Preconditions.checkNotNull(fieldName);
this.desc = Preconditions.checkNotNull(desc);
this.isImmutable = isimmutable;
this.indexed = indexed;
}
public boolean isImmutable() {
return isImmutable;
}
public boolean isIndexed() {
return indexed;
}
public String getName() {
return this.name;
}
public String getFieldName() {
return this.fieldName;
}
public String getDesc() {
return this.desc;
}
ToStringHelper toStringHelper(Class> clazz) {
return Objects.toStringHelper(clazz).add("name", name).add("fieldName", fieldName)
.add("desc", desc).add("immutable", isImmutable);
}
int getHashCode() {
return Objects.hashCode(getName(), getFieldName(), getDesc(), isImmutable());
}
boolean equals(AbstractSchemaProperty o) {
return equal(getName(), o.getName()) && equal(getFieldName(), o.getFieldName())
&& equal(getDesc(), o.getDesc()) && equal(isImmutable(), o.isImmutable());
}
}
/**
* Description of a single simple type.
*/
public final static class SchemaProperty extends AbstractSchemaProperty {
private static final long serialVersionUID = -8108590860088240249L;
private String defaultValue;
private String type;
private List enums;
private Class> cls;
private SchemaProperty(final String name, final String fieldName, final String type,
final String desc, final boolean isImmutable, final List enums,
final String defaultValue, final boolean indexed) {
super(name, fieldName, desc, isImmutable, indexed);
this.defaultValue = defaultValue;
this.enums = enums;
this.type = Preconditions.checkNotNull(type);
}
/**
* Not to be used by users.
*/
public static SchemaProperty create(final String name, final String fieldName,
final String type, final String desc, final boolean isImmutable,
final List enums, final String defaultValue, final boolean indexed) {
return new SchemaProperty(name, fieldName, type, desc, isImmutable, enums, defaultValue, indexed);
}
public String getType() {
return type;
}
public Class> getClassType() {
if(cls != null) {
return cls;
}
try {
cls = Class.forName(type);
return cls;
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
public boolean isEnum() {
return enums != null && enums.size() > 0;
}
public List getEnums() {
return enums;
}
public String getDefaultValue() {
return defaultValue;
}
public String toString() {
return super.toStringHelper(SchemaProperty.class).add("type", getType())
.add("defaultValue", getDefaultValue()).toString();
}
@Override
public int hashCode() {
return Objects.hashCode(super.getHashCode(), getDefaultValue(), getType());
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SchemaProperty)) {
return false;
}
SchemaProperty o = (SchemaProperty) obj;
return super.equals(o) && equal(getDefaultValue(), o.getDefaultValue())
&& equal(getType(), o.getType());
}
}
/**
* Description of a collection (or any other subtype) of simple types.
*/
public final static class SchemaPropertyList extends AbstractSchemaProperty {
private static final long serialVersionUID = 3192273741446945936L;
private final String type;
private final String collectionType;
private List defaultValues;
private List enums;
private Class> cls;
private Class> collectionTypeCls;
private SchemaPropertyList(final String name, final String fieldName, final String type,
final String desc, final boolean isImmutable, final List enums,
final String collectionType, final List defaultValues, final boolean indexed) {
super(name, fieldName, desc, isImmutable, indexed);
this.collectionType = Preconditions.checkNotNull(collectionType);
this.type = Preconditions.checkNotNull(type);
this.defaultValues = defaultValues;
this.enums = enums;
}
/**
* Not to be used by users.
*/
public static SchemaPropertyList create(final String name, final String fieldName,
final String type, final String desc, boolean isImmutable,
final List enums, List defaultValues, final String collectionType, final boolean indexed) {
return new SchemaPropertyList(name, fieldName, type, desc, isImmutable, enums,
collectionType, defaultValues, indexed);
}
public String getType() {
return type;
}
public String getCollectionType() {
return collectionType;
}
public Class> getClassCollectionType() {
if(collectionTypeCls != null) {
return collectionTypeCls;
}
try {
collectionTypeCls = Class.forName(collectionType);
return collectionTypeCls;
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
public Class> getClassType() {
if(cls != null) {
return cls;
}
try {
cls = Class.forName(type);
return cls;
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
public List getDefaultValues() {
return defaultValues;
}
public boolean isEnum() {
return enums != null && enums.size() > 0;
}
public List getEnums() {
return enums;
}
public String toString() {
return Objects.toStringHelper(SchemaPropertyList.class)
.add("type", getCollectionType()).add("collectionType", getCollectionType())
.add("defaultValue", getDefaultValues()).toString();
}
@Override
public int hashCode() {
return Objects.hashCode(super.getHashCode(), getType(), getCollectionType());
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SchemaPropertyList)) {
return false;
}
SchemaPropertyList o = (SchemaPropertyList) obj;
return equals(o) && equal(getCollectionType(), o.getCollectionType())
&& equal(getType(), o.getType());
}
}
/**
* Description of a single reference to any other bean registered in the system.
*/
public final static class SchemaPropertyRef extends AbstractSchemaProperty {
private final String schemaName;
private boolean isSingleton;
private static final long serialVersionUID = 987642987178370676L;
protected SchemaPropertyRef(final String name, final String fieldName,
final String schemaName, final String desc, final boolean isImmutable,
final boolean isSingleton, final boolean indexed) {
super(name, fieldName, desc, isImmutable, indexed);
this.isSingleton = isSingleton;
this.schemaName = Preconditions.checkNotNull(schemaName);
}
/**
* Not to be used by users.
*/
public static SchemaPropertyRef create(final String name, final String fieldName,
final String schemaName, final String desc, final boolean isImmutable,
final boolean isSingleton, final boolean indexed) {
return new SchemaPropertyRef(name, fieldName, schemaName, desc, isImmutable,
isSingleton, indexed);
}
public final String getSchemaName() {
return schemaName;
}
public boolean isSingleton() {
return isSingleton;
}
@Override
public int hashCode() {
return super.getHashCode() + Objects.hashCode(getSchemaName());
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SchemaPropertyRef)) {
return false;
}
SchemaPropertyRef o = (SchemaPropertyRef) obj;
return equals(o) && equal(getSchemaName(), o.getSchemaName());
}
@Override
public final String toString() {
return super.toStringHelper(SchemaPropertyRef.class).add("schema-name", schemaName)
.toString();
}
}
/**
* Description of a collection (or any other subtype) of references to any other
* bean defined in the system.
*/
public final static class SchemaPropertyRefList extends AbstractSchemaProperty {
private static final long serialVersionUID = -2386455434996679436L;
private final String collectionType;
private final String schemaName;
private Class> collectionTypeCls;
private SchemaPropertyRefList(final String name, final String fieldName,
final String schemaName, final String desc, final boolean isImmutable,
final String collectionType, final boolean indexed) {
super(name, fieldName, desc, isImmutable, indexed);
this.collectionType = Preconditions.checkNotNull(collectionType);
this.schemaName = Preconditions.checkNotNull(schemaName);
}
/**
* Not to be used by users.
*/
public static SchemaPropertyRefList create(final String name, final String fieldName,
final String schemaName, final String desc, final boolean isImmutable,
final String collectionType, final boolean indexed) {
return new SchemaPropertyRefList(name, fieldName, schemaName, desc, isImmutable,
collectionType, indexed);
}
public final String getCollectionType() {
return collectionType;
}
public Class> getClassCollectionType() {
if(collectionTypeCls != null) {
return collectionTypeCls;
}
try {
collectionTypeCls = Class.forName(collectionType);
return collectionTypeCls;
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
public final String getSchemaName() {
return schemaName;
}
@Override
public int hashCode() {
return super.getHashCode() + Objects.hashCode(collectionType, schemaName);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SchemaPropertyRefList)) {
return false;
}
SchemaPropertyRefList o = (SchemaPropertyRefList) obj;
return equals(o) && equal(getCollectionType(), o.getCollectionType())
&& equal(getSchemaName(), o.getSchemaName());
}
@Override
public final String toString() {
return toStringHelper(SchemaPropertyRefList.class)
.add("collectionType", getCollectionType()).add("schema-name", getSchemaName())
.toString();
}
}
/**
* Represent a map of references indexed on instance id.
*/
public final static class SchemaPropertyRefMap extends AbstractSchemaProperty {
private static final long serialVersionUID = 9128725908670921628L;
private final String mapType;
private final String schemaName;
private Class> collectionTypeCls;
private SchemaPropertyRefMap(final String name, final String fieldName,
final String schemaName, final String desc, final boolean isImmutable,
final String mapType, final boolean indexed) {
super(name, fieldName, desc, isImmutable, indexed);
this.mapType = Preconditions.checkNotNull(mapType);
this.schemaName = Preconditions.checkNotNull(schemaName);
}
/**
* Not to be used by users.
*/
public static SchemaPropertyRefMap create(final String name, final String fieldName,
final String schemaName, final String desc, final boolean isImmutable,
final String mapType, final boolean indexed) {
return new SchemaPropertyRefMap(name, fieldName, schemaName, desc, isImmutable, mapType, indexed);
}
public String getMapType() {
return mapType;
}
public Class> getClassMapType() {
if(collectionTypeCls != null) {
return collectionTypeCls;
}
try {
collectionTypeCls = Class.forName(mapType);
return collectionTypeCls;
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
public String getSchemaName() {
return schemaName;
}
@Override
public int hashCode() {
return super.getHashCode() + Objects.hashCode(mapType, schemaName);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SchemaPropertyRefMap)) {
return false;
}
SchemaPropertyRefMap o = (SchemaPropertyRefMap) obj;
return equals(o) && equal(getMapType(), o.getMapType())
&& equal(getSchemaName(), o.getSchemaName());
}
@Override
public String toString() {
return toStringHelper(SchemaPropertyRefList.class).add("mapType", getMapType())
.add("schema-name", getSchemaName()).toString();
}
}
}