/** * DataCleaner (community edition) * Copyright (C) 2014 Neopost - Customer Information Management * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.datacleaner.descriptors; import java.lang.annotation.Annotation; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.datacleaner.api.Alias; import org.datacleaner.api.Converter; import org.datacleaner.api.InputColumn; import org.datacleaner.components.remote.RemoteTransformer; import org.datacleaner.restclient.Serializator; import com.fasterxml.jackson.databind.JsonNode; /** * A Base class for property descriptors of remote transformers, implementing * common functions. See the child classes for details. * * @Since 25.9.15 */ public abstract class RemoteConfiguredPropertyDescriptor implements ConfiguredPropertyDescriptor { private static final long serialVersionUID = 1L; private final String name; private final String description; private final boolean required; private final ComponentDescriptor<?> component; private final Map<Class<? extends Annotation>, Annotation> annotations; private final JsonNode defaultValue; RemoteConfiguredPropertyDescriptor(final String name, final String description, final boolean required, final ComponentDescriptor<?> component, final Map<Class<? extends Annotation>, Annotation> annotations, final JsonNode defaultValue) { this.name = name; this.annotations = annotations; this.defaultValue = defaultValue; this.description = description; this.required = required; this.component = component; } @Override public String getDescription() { return description; } @Override public boolean isRequired() { return required; } @Override public Converter<?> createCustomConverter() { return null; } @Override public String[] getAliases() { final Alias alias = getAnnotation(Alias.class); if (alias == null) { return new String[0]; } return alias.value(); } @Override public String getName() { return name; } @Override public void setValue(final Object component, final Object value) throws IllegalArgumentException { ((RemoteTransformer) component).setPropertyValue(getName(), value); } public void setDefaultValue(final Object component) { if (defaultValue != null) { setValue(component, createDefaultValue()); } } private Object createDefaultValue() { // TODO: this is code duplicate with // ComponentHandler.convertPropertyValue // (which is used to deserialize properties values on the server side). // TODO: But on server side a StringConverter is used for string values, // which is not fully available on client // side (some extenstions providing custom converters may be not // available on client classpath). // We must unify how values are serialized on client as well as server // side. Maybe use pure JSON string? // Maybe it is enough to support JsonNode in StringConverter? That // should fit the unknown values... try { return Serializator.getJacksonObjectMapper().treeToValue(defaultValue, getType()); } catch (final Exception e) { throw new RuntimeException(e); } } @Override public boolean isInputColumn() { return InputColumn.class.isAssignableFrom(getBaseType()); } @Override public Object getValue(final Object component) throws IllegalArgumentException { return ((RemoteTransformer) component).getPropertyValue(getName()); } @Override public Set<Annotation> getAnnotations() { return new HashSet<>(annotations.values()); } @SuppressWarnings("unchecked") @Override public <A extends Annotation> A getAnnotation(final Class<A> annotationClass) { return (A) annotations.get(annotationClass); } @Override public ComponentDescriptor<?> getComponentDescriptor() { return component; } @Override public int getTypeArgumentCount() { return 0; } @Override public Class<?> getTypeArgument(final int i) throws IndexOutOfBoundsException { return Object.class; } @Override public int compareTo(final PropertyDescriptor o) { return getName().compareTo(o.getName()); } }