All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.datacleaner.restclient.Serializator Maven / Gradle / Ivy

There is a newer version: 6.0.0
Show newest version
/**
 * 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.restclient;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.metamodel.util.HasName;
import org.datacleaner.api.ComponentScope;
import org.datacleaner.api.InputColumn;
import org.datacleaner.api.ShortNews;
import org.datacleaner.util.HasAliases;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

/**
 * Class for input/output data types conversion from/into String.
 * @since 11. 09. 2015
 */
public class Serializator {
    @JsonDeserialize(using = ComponentScopeServiceTypeDeserializer.class)
    interface ComponentScopeServiceTypeMixin {
    }

    @JsonDeserialize(using = ComponentScopeEntityTypeDeserializer.class)
    interface ComponentScopeEntityTypeMixin {
    }

    /**
     * When calling the REST API, we want the input columns to be specified only by its name in the JSON payload.
     */
    @SuppressWarnings("rawtypes")
    private static class MyInputColumnSerializer extends StdSerializer {
        protected MyInputColumnSerializer() {
            super(InputColumn.class);
        }

        @Override
        public void serialize(final InputColumn value, final JsonGenerator gen, final SerializerProvider serializers)
                throws IOException {
            gen.writeString(value.getName());
        }
    }

    /** Custom enum serializer. Serializes as the default one (using the enum name()), but
     * generates customized Json schema. In this schema, the enum constants are provided
     * and we provide a concatenatin of enum name() and a human-readable form for the enumeration
     * (via interface {@link HasName} or toString()).
     * 

The DataCleaner Desktop then interprets it and uses the name() part for json queries and the * second part for GUI. *

An example of enumeration json schema: *

     * {
     *   "type": "string",
     *   "enum": [
     *     "TRUE_FALSE::True or false",
     *     "INPUT_OR_NULL::Corrected value or null"
     *   ]
     * }
*/ @SuppressWarnings("rawtypes") private static class MyEnumSerializer extends StdSerializer { protected MyEnumSerializer() { super(Enum.class); } @Override public JsonNode getSchema(final SerializerProvider provider, final Type typeHint) { final ObjectNode objectNode = createSchemaNode("string", true); if (typeHint != null) { final JavaType type = provider.constructType(typeHint); if (type.isEnumType()) { final ArrayNode enumNode = objectNode.putArray("enum"); for (final Object value : type.getRawClass().getEnumConstants()) { enumNode.add(enumValueToSchemaString((Enum) value)); } } } return objectNode; } @Override public void serialize(final Enum value, final JsonGenerator gen, final SerializerProvider serializers) throws IOException { gen.writeString(value.name()); } @Override public void acceptJsonFormatVisitor(final JsonFormatVisitorWrapper visitor, final JavaType typeHint) throws JsonMappingException { final JsonStringFormatVisitor stringVisitor = visitor.expectStringFormat(typeHint); if (typeHint != null && stringVisitor != null) { if (typeHint.isEnumType()) { final Set enums = new LinkedHashSet<>(); for (final Object value : typeHint.getRawClass().getEnumConstants()) { enums.add(enumValueToSchemaString((Enum) value)); } stringVisitor.enumTypes(enums); } } } protected String enumValueToSchemaString(final Enum value) { final String enumValue = value.name(); final String enumName; String[] aliases = null; if (value instanceof HasName) { enumName = ((HasName) value).getName(); } else { enumName = String.valueOf(value); } if (value instanceof HasAliases) { aliases = ((HasAliases) value).getAliases(); } return Serializator.enumValueToSchemaString(enumValue, enumName, aliases); } } private static final class ComponentScopeServiceTypeDeserializer extends JsonDeserializer { @Override public ComponentScope.ServiceType deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException { final String jsonParserText = jsonParser.getText(); for (final ComponentScope.ServiceType value : ComponentScope.ServiceType.values()) { if (value.name().equals(jsonParserText)) { return value; } } return null; } } private static final class ComponentScopeEntityTypeDeserializer extends JsonDeserializer { @Override public ComponentScope.EntityType deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException { final String jsonParserText = jsonParser.getText(); for (final ComponentScope.EntityType value : ComponentScope.EntityType.values()) { if (value.name().equals(jsonParserText)) { return value; } } return null; } } public static final String ENUM_ALIAS_SEPARATOR = "::"; private static final ObjectMapper objectMapper = new ObjectMapper(); static { final SimpleModule myModule = new SimpleModule("RemoteTransformersModule", new Version(1, 0, 0, null, "org.datacleaner", "DataCleaner-remote-transformers")); // our custom serializers myModule.addSerializer(new MyInputColumnSerializer()); myModule.addSerializer(new MyEnumSerializer()); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.registerModule(myModule); //For better deserialize of enumeration in ComponentScope annotation. - We will ignore unknown values. objectMapper.registerModule(new SimpleModule() { @Override public void setupModule(final SetupContext context) { context.setMixInAnnotations(ComponentScope.ServiceType.class, ComponentScopeServiceTypeMixin.class); context.setMixInAnnotations(ComponentScope.EntityType.class, ComponentScopeEntityTypeMixin.class); } }); } public static ObjectMapper getJacksonObjectMapper() { return objectMapper; } public static ShortNews shortNewsList(final String response) { return Serializator.fromString(response, ShortNews.class); } public static ComponentList componentList(final String response) { return Serializator.fromString(response, ComponentList.class); } public static ComponentList.ComponentInfo componentInfo(final String response) { return (ComponentList.ComponentInfo) Serializator.fromString(response, ComponentList.ComponentInfo.class); } public static String stringProcessStatelessInput(final ProcessStatelessInput processStatelessInput) { return Serializator.intoString(processStatelessInput); } public static OutputColumns outputColumnsOutput(final String response) { return Serializator.fromString(response, OutputColumns.class); } public static ProcessStatelessOutput processStatelessOutput(final String response) { return (ProcessStatelessOutput) Serializator.fromString(response, ProcessStatelessOutput.class); } public static String stringCreateInput(final CreateInput createInput) { return Serializator.intoString(createInput); } public static String stringProcessInput(final ProcessInput processInput) { return Serializator.intoString(processInput); } public static ProcessOutput processOutput(final String response) { return (ProcessOutput) Serializator.fromString(response, ProcessOutput.class); } public static ProcessResult processResult(final String response) { return (ProcessResult) Serializator.fromString(response, ProcessResult.class); } public static DataCloudUser processDataCloudUser(final String response) { return (DataCloudUser) Serializator.fromString(response, DataCloudUser.class); } private static String intoString(final Object value) { try { return objectMapper.writeValueAsString(value); } catch (final JsonProcessingException e) { throw new RuntimeException(e); } } private static T fromString(final String value, final Class type) { try { if (value == null || value.equals("")) { return null; } return objectMapper.readValue(value, type); } catch (final IOException e) { throw new RuntimeException(e); } } public static String enumValueToSchemaString(final String enumValue, final String enumName, final String[] aliases) { final StringBuilder serialized = new StringBuilder(); serialized.append(enumValue); serialized.append(ENUM_ALIAS_SEPARATOR); serialized.append(enumName); if (aliases != null && aliases.length > 0) { for (final String alias : aliases) { if (alias != null && !alias.isEmpty()) { serialized.append(ENUM_ALIAS_SEPARATOR).append(alias); } } } return serialized.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy