Preferences -- matemodel


package org.jboss.seam.wiki.preferences.metamodel;

import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
import org.hibernate.validator.NotNull;
import org.jboss.seam.core.Interpolator;
import org.jboss.seam.core.Validators;
import org.jboss.seam.log.Log;
import org.jboss.seam.log.Logging;
import org.jboss.seam.util.Reflections;
import org.jboss.seam.wiki.preferences.PreferenceValue;
import org.jboss.seam.wiki.preferences.PreferenceVisibility;
import org.jboss.seam.wiki.preferences.annotations.PreferenceProperty;
import org.jboss.seam.wiki.preferences.annotations.Preferences;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.*;

/*
TODO: This implementation of Comparable is not consistent with equals()!
*/
public class PreferenceEntity implements Comparable, Serializable {

Log log = Logging.getLog(PreferenceEntity.class);

private Class clazz;
private String description;
private String entityName;
private String mappedTo;
private SortedSet<Property> properties = new TreeSet<Property>();
private Map<String, Property> propertiesByName = new HashMap<String,Property>();
private SortedSet<Property> propertiesSystemVisible = new TreeSet<Property>();
private SortedSet<Property> propertiesUserVisible = new TreeSet<Property>();
private SortedSet<Property> propertiesInstanceVisible = new TreeSet<Property>();

public PreferenceEntity(Class<?> entityClass) {
if (!entityClass.isAnnotationPresent(Preferences.class)) {
throw new RuntimeException("Configured as preferences but missing @Preferences: " + entityClass.getName());
}

this.clazz = entityClass;
this.description = interpolate(entityClass.getAnnotation(Preferences.class).description());
this.entityName = entityClass.getAnnotation(Preferences.class).name();
this.mappedTo = entityClass.getAnnotation(Preferences.class).mappedTo();
if (this.entityName != null && this.entityName.length() == 0) this.entityName = clazz.getSimpleName();

// @PreferenceProperty fields
for (Field field : entityClass.getDeclaredFields()) {
if (field.isAnnotationPresent(PreferenceProperty.class)) {
if (!field.isAccessible()) field.setAccessible(true);

Property property =
new Property(field.getName(),
field.getType(),
interpolate(field.getAnnotation(PreferenceProperty.class).description()),
field.getAnnotation(PreferenceProperty.class).visibility(),
field.getAnnotation(PreferenceProperty.class).editorIncludeName(),
field.getAnnotation(PreferenceProperty.class).templateComponentName(),
field.getAnnotation(PreferenceProperty.class).mappedTo()
);

if (property.isSystemVisible()) propertiesSystemVisible.add(property);
if (property.isUserVisible()) propertiesUserVisible.add(property);
if (property.isInstanceVisible()) propertiesInstanceVisible.add(property);
properties.add(property);
propertiesByName.put(property.getFieldName(), property);
}
}
}

public Class getClazz() {
return clazz;
}

public String getDescription() {
return description;
}

public String getEntityName() {
return entityName;
}

public String getMappedTo() {
return mappedTo;
}

public SortedSet<Property> getProperties() {
return properties;
}

public Map<String, Property> getPropertiesByName() {
return propertiesByName;
}

public SortedSet<Property> getPropertiesSystemVisible() {
return propertiesSystemVisible;
}

public SortedSet<Property> getPropertiesUserVisible() {
return propertiesUserVisible;
}

public SortedSet<Property> getPropertiesInstanceVisible() {
return propertiesInstanceVisible;
}

public boolean isSystemPropertiesVisible() {
return propertiesSystemVisible.size() != 0;
}

public boolean isUserPropertiesVisible() {
return propertiesUserVisible.size() != 0;
}

public boolean isInstancePropertiesVisible() {
return propertiesInstanceVisible.size() != 0;
}

public Object materialize(Set<PreferenceValue> valueHolders) {
log.trace("materializing preference entity instance: " + getEntityName());
Map<Property, InvalidValue[]> invalidProperties = validate(valueHolders);
if (invalidProperties.size() > 0) {
log.error("can't materialize preference entity: " + getEntityName());
for (Map.Entry<Property, InvalidValue[]> invalidProperty : invalidProperties.entrySet()) {
log.error("invalid value for : " + invalidProperty.getKey());
for (InvalidValue invalidValue : invalidProperty.getValue()) {
log.error("validation error: " + invalidValue.getMessage());
}
}
throw new RuntimeException("could not materialize preference entity '"
+ getEntityName() + "', check the log");
}

Object preferenceEntityInstance;
try {
preferenceEntityInstance = getClazz().newInstance();
for (PreferenceValue valueHolder : valueHolders) {
log.trace("writing preference value: " + valueHolder.getPreferenceProperty().getFieldName());
valueHolder.getPreferenceProperty()
.write(preferenceEntityInstance, valueHolder.getValue());
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return preferenceEntityInstance;
}

public Map<Property, InvalidValue[]> validate(Collection<PreferenceValue> valueHolders) {
return validate(valueHolders, Arrays.asList(PreferenceVisibility.values()));
}

public Map<Property, InvalidValue[]> validate(Collection<PreferenceValue> valueHolders, List<PreferenceVisibility> visibilities) {
log.trace("validating preference entity values");

Set<Property> uncheckedProperties = getProperties();

Map<Property, InvalidValue[]> invalidProperties = new HashMap<Property, InvalidValue[]>();
for (PreferenceValue valueHolder : valueHolders) {
Property property = valueHolder.getPreferenceProperty();
log.trace("validating " + property);
uncheckedProperties.remove(property);
InvalidValue[] invalidValues = property.validate(valueHolder.getValue());
if (invalidValues.length > 0) invalidProperties.put(property, invalidValues);
}

log.trace("validating properties with no values, checking for @NotNull by given visibility");
// Now validate all the properties for which we didn't have values, they need to be !@NotNull
if (uncheckedProperties.size() > 0) {
boolean uncheckedAreNullable = true;
for (Property uncheckedProperty : uncheckedProperties) {
if (uncheckedProperty.getVisibility().containsAll(visibilities) && !uncheckedProperty.isNullable()) {
log.error("missing value for @NotNull " + uncheckedProperty);
uncheckedAreNullable = false;
}
}
if (!uncheckedAreNullable) {
throw new IllegalStateException("missing values for validation of " + getEntityName() + ", check the log");
}
}

return invalidProperties;
}

public int compareTo(Object o) {
return getDescription().compareTo(((PreferenceEntity) o).getDescription());
}

public String toString() {
return "PreferenceEntity: " + getClazz().getName() + " properties: " + getProperties().size();
}

/*
TODO: This implementation of Comparable is not consistent with equals()!
*/
public class Property implements Comparable, Serializable {

private String fieldName;
private Class fieldType;
private String description;
private List<PreferenceVisibility> visibility;
private String editorIncludeName;
private String templateComponentName;
private String mappedTo;

public Property(String fieldName, Class fieldType, String description,
PreferenceVisibility[] visibility,
String editorIncludeName, String templateComponentName, String mappedTo) {
this.fieldName = fieldName;
this.fieldType = fieldType;
this.description = description;
this.visibility = Arrays.asList(visibility);
this.editorIncludeName = editorIncludeName;
this.templateComponentName = templateComponentName;
this.mappedTo = mappedTo;
}

public Field getField() {
return Reflections.getField(getClazz(), fieldName);
}

public String getOwningEntityName() {
return getEntityName();
}

public String getFieldName() {
return fieldName;
}

public Class getFieldType() {
return fieldType;
}

public String getDescription() {
return description;
}

public List<PreferenceVisibility> getVisibility() {
return visibility;
}

public String getEditorIncludeName() {
return "editor" + editorIncludeName;
}

public String getTemplateComponentName() {
return templateComponentName;
}

public String getMappedTo() {
return mappedTo;
}

public boolean isSystemVisible() {
return getVisibility().contains(PreferenceVisibility.SYSTEM);
}

public boolean isUserVisible() {
return getVisibility().contains(PreferenceVisibility.USER);
}

public boolean isInstanceVisible() {
return getVisibility().contains(PreferenceVisibility.INSTANCE);
}

public void write(Object preferenceEntityInstance, Object value) throws Exception {
Field field = getField();
field.setAccessible(true);
Reflections.set(field, preferenceEntityInstance, value);
}

public boolean isNullable() {
return !getField().isAnnotationPresent(NotNull.class);
}

public InvalidValue[] validate(Object value) {
ClassValidator validator = Validators.instance().getValidator(getClazz());
return validator.getPotentialInvalidValues(getFieldName(), value);
}

public int compareTo(Object o) {
return getDescription().compareTo(((Property) o).getDescription());
}

public String toString() {
return "Property: " + getFieldName() + " of type: " + getFieldType();
}
}

private String interpolate(String s) {
return Interpolator.instance().interpolate(s);
}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值