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

com.enonic.xp.json.JsonToPropertyTreeTranslator Maven / Gradle / Ivy

There is a newer version: 7.14.4
Show newest version
package com.enonic.xp.json;

import java.util.Iterator;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;

import com.enonic.xp.annotation.PublicApi;
import com.enonic.xp.data.Property;
import com.enonic.xp.data.PropertySet;
import com.enonic.xp.data.PropertyTree;
import com.enonic.xp.data.Value;
import com.enonic.xp.data.ValueFactory;
import com.enonic.xp.form.Form;
import com.enonic.xp.form.FormItemPath;
import com.enonic.xp.form.Input;
import com.enonic.xp.inputtype.InputType;
import com.enonic.xp.inputtype.InputTypeResolver;
import com.enonic.xp.inputtype.InputTypes;


/**
 * @deprecated As of release 6.9
 */
@PublicApi
@Deprecated(since = "6.9")
public final class JsonToPropertyTreeTranslator
{
    private final Form form;

    private final PropertyTree propertyTree;

    private final InputTypeResolver inputTypeResolver;

    private final boolean strictMode;

    @SuppressWarnings("unused")
    // Kept for backward compatibility
    public JsonToPropertyTreeTranslator()
    {
        this( null, false );
    }

    @SuppressWarnings("unused")
    // Kept for backward compatibility
    public JsonToPropertyTreeTranslator( final Form form, final boolean strict )
    {
        this.form = form != null ? form : Form.create().build();
        this.strictMode = strict;
        this.propertyTree = new PropertyTree();
        this.inputTypeResolver = InputTypes.BUILTIN;
    }

    public PropertyTree translate( final JsonNode json )
    {
        traverse( json, this.propertyTree.getRoot() );
        return this.propertyTree;
    }

    private void traverse( final JsonNode json, final PropertySet parent )
    {
        final Iterator> fields = json.fields();

        while ( fields.hasNext() )
        {
            final Map.Entry next = fields.next();
            addValue( parent, next.getKey(), next.getValue() );
        }
    }

    private void addValue( final PropertySet parent, final String key, final JsonNode value )
    {
        if ( value.isArray() )
        {
            for ( final JsonNode objNode : value )
            {
                addValue( parent, key, objNode );
            }
        }
        else if ( value.isObject() && !hasInput( parent.getProperty(), key ) )
        {
            final PropertySet parentSet = parent.addSet( key );
            value.fields().forEachRemaining( ( objectValue ) -> addValue( parentSet, objectValue.getKey(), objectValue.getValue() ) );
        }
        else
        {
            mapValue( parent, key, value );
        }
    }

    private void mapValue( final PropertySet parent, final String key, final JsonNode value )
    {
        final Property parentProperty = parent.getProperty();
        final Input input = getInput( parentProperty, key );

        if ( input == null )
        {
            if ( this.strictMode )
            {
                throw new IllegalArgumentException(
                    "No mapping defined for property " + key + " with value " + resolveStringValue( value ) );
            }

            parent.addProperty( key, resolveCoreValue( value ) );
        }
        else
        {
            final InputType type = this.inputTypeResolver.resolve( input.getInputType() );
            final Value mappedPropertyValue = type.createValue( resolveCoreValue( value ), input.getInputTypeConfig() );

            parent.addProperty( key, mappedPropertyValue );
        }
    }

    private Value resolveCoreValue( final JsonNode value )
    {
        if ( value.isTextual() )
        {
            return ValueFactory.newString( value.textValue() );
        }

        if ( value.isDouble() )
        {
            return ValueFactory.newDouble( value.doubleValue() );
        }

        if ( value.isInt() )
        {
            return ValueFactory.newLong( (long) value.intValue() );
        }

        if ( value.isLong() )
        {
            return ValueFactory.newLong( value.longValue() );
        }

        if ( value.isObject() )
        {
            PropertySet propertySet = new PropertySet();
            value.fields().
                forEachRemaining( ( field ) -> {
                    if ( field.getValue().isArray() )
                    {
                        for ( final JsonNode arrayNode : field.getValue() )
                        {
                            propertySet.addProperty( field.getKey(), resolveCoreValue( arrayNode ) );
                        }
                    }
                    else
                    {
                        propertySet.addProperty( field.getKey(), resolveCoreValue( field.getValue() ) );
                    }
                } );
            return ValueFactory.newPropertySet( propertySet );
        }

        return ValueFactory.newString( value.toString() );
    }

    private String resolveStringValue( final JsonNode value )
    {
        if ( value.isTextual() )
        {
            return value.textValue();
        }

        return value.toString();
    }

    private FormItemPath resolveInputPath( final String key, final Property parentProperty )
    {
        if ( parentProperty == null )
        {
            return FormItemPath.from( key );
        }

        final FormItemPath parentPath = FormItemPath.from( parentProperty.getPath().resetAllIndexesTo( 0 ).toString() );
        return FormItemPath.from( parentPath, key );
    }

    private boolean hasInput( final Property parentProperty, final String key )
    {
        return this.form.getFormItem( resolveInputPath( key, parentProperty ) ) instanceof Input;
    }

    private Input getInput( final Property parentProperty, final String key )
    {
        return this.form.getInput( resolveInputPath( key, parentProperty ), true );
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy