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 {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    public static final String ENUM_ALIAS_SEPARATOR = "::";
    static {
        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(String response) {
        return Serializator.fromString(response, ShortNews.class);
    }

    public static ComponentList componentList(String response) {
        ComponentList components = Serializator.fromString(response, ComponentList.class);
        return components;
    }

    public static ComponentList.ComponentInfo componentInfo(String response) {
        return (ComponentList.ComponentInfo) Serializator.fromString(response, ComponentList.ComponentInfo.class);
    }

    public static String stringProcessStatelessInput(ProcessStatelessInput processStatelessInput) {
        return Serializator.intoString(processStatelessInput);
    }

    public static OutputColumns outputColumnsOutput(String response) {
        return Serializator.fromString(response, OutputColumns.class);
    }

    public static ProcessStatelessOutput processStatelessOutput(String response) {
        return (ProcessStatelessOutput) Serializator.fromString(response, ProcessStatelessOutput.class);
    }

    public static String stringCreateInput(CreateInput createInput) {
        return Serializator.intoString(createInput);
    }

    public static String stringProcessInput(ProcessInput processInput) {
        return Serializator.intoString(processInput);
    }

    public static ProcessOutput processOutput(String response) {
        return (ProcessOutput) Serializator.fromString(response, ProcessOutput.class);
    }

    public static ProcessResult processResult(String response) {
        return (ProcessResult) Serializator.fromString(response, ProcessResult.class);
    }

    public static DataCloudUser processDataCloudUser(String response){
        return (DataCloudUser) Serializator.fromString(response, DataCloudUser.class);
    }

    private static String intoString(Object value) {
        try {
            return objectMapper.writeValueAsString(value);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    private static  T fromString(String value, Class type) {
        try {
            if (value == null || value.equals("")) {
                return null;
            }

            return objectMapper.readValue(value, type);
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 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(InputColumn value, JsonGenerator gen, 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(SerializerProvider provider, Type typeHint) { ObjectNode objectNode = createSchemaNode("string", true); if (typeHint != null) { JavaType type = provider.constructType(typeHint); if (type.isEnumType()) { ArrayNode enumNode = objectNode.putArray("enum"); for (Object value : type.getRawClass().getEnumConstants()) { enumNode.add(enumValueToSchemaString((Enum) value)); } } } return objectNode; } @Override public void serialize(Enum value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeString(value.name()); } @Override public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { JsonStringFormatVisitor stringVisitor = visitor.expectStringFormat(typeHint); if (typeHint != null && stringVisitor != null) { if (typeHint.isEnumType()) { Set enums = new LinkedHashSet(); for (Object value : typeHint.getRawClass().getEnumConstants()) { enums.add(enumValueToSchemaString((Enum) value)); } stringVisitor.enumTypes(enums); } } } protected String enumValueToSchemaString(Enum value) { final String enumValue = value.name(); 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); } } public static String enumValueToSchemaString(String enumValue, String enumName, 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(String alias: aliases) { if(alias != null && !alias.isEmpty()) { serialized.append(ENUM_ALIAS_SEPARATOR).append(alias); } } } return serialized.toString(); } @JsonDeserialize(using = ComponentScopeServiceTypeDeserializer.class) interface ComponentScopeServiceTypeMixin {} @JsonDeserialize(using = ComponentScopeEntityTypeDeserializer.class) interface ComponentScopeEntityTypeMixin {} 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; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy