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

com.bazaarvoice.jolt.common.PathElementBuilder Maven / Gradle / Ivy

There is a newer version: 0.1.8
Show newest version
/*
 * Copyright 2013 Bazaarvoice, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.bazaarvoice.jolt.common;

import com.bazaarvoice.jolt.common.pathelement.AmpPathElement;
import com.bazaarvoice.jolt.common.pathelement.ArrayPathElement;
import com.bazaarvoice.jolt.common.pathelement.AtPathElement;
import com.bazaarvoice.jolt.common.pathelement.DollarPathElement;
import com.bazaarvoice.jolt.common.pathelement.HashPathElement;
import com.bazaarvoice.jolt.common.pathelement.LiteralPathElement;
import com.bazaarvoice.jolt.common.pathelement.MatchablePathElement;
import com.bazaarvoice.jolt.common.pathelement.PathElement;
import com.bazaarvoice.jolt.common.pathelement.StarAllPathElement;
import com.bazaarvoice.jolt.common.pathelement.StarDoublePathElement;
import com.bazaarvoice.jolt.common.pathelement.StarRegexPathElement;
import com.bazaarvoice.jolt.common.pathelement.StarSinglePathElement;
import com.bazaarvoice.jolt.common.pathelement.TransposePathElement;
import com.bazaarvoice.jolt.exception.SpecException;
import com.bazaarvoice.jolt.utils.StringTools;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import static com.bazaarvoice.jolt.common.SpecStringParser.fixLeadingBracketSugar;
import static com.bazaarvoice.jolt.common.SpecStringParser.parseDotNotation;
import static com.bazaarvoice.jolt.common.SpecStringParser.removeEscapeChars;
import static com.bazaarvoice.jolt.common.SpecStringParser.removeEscapedValues;
import static com.bazaarvoice.jolt.common.SpecStringParser.stringIterator;

/**
 * Static utility class that creates PathElement(s) given a string key from a json spec document
 */
public class PathElementBuilder {

    private PathElementBuilder() {}

    /**
     * Create a path element and ensures it is a Matchable Path Element
     */
    public static MatchablePathElement buildMatchablePathElement(String rawJsonKey) {
        PathElement pe = PathElementBuilder.parseSingleKeyLHS( rawJsonKey );

        if ( ! ( pe instanceof MatchablePathElement ) ) {
            throw new SpecException( "Spec LHS key=" + rawJsonKey + " is not a valid LHS key." );
        }

        return (MatchablePathElement) pe;
    }

    /**
     * Visible for Testing.
     *
     * Inspects the key in a particular order to determine the correct sublass of
     *  PathElement to create.
     *
     * @param origKey String that should represent a single PathElement
     * @return a concrete implementation of PathElement
     */
    public static PathElement parseSingleKeyLHS( String origKey )  {

        String elementKey;  // the String to use to actually make Elements
        String keyToInspect;  // the String to use to determine which kind of Element to create

        if ( origKey.contains( "\\" ) ) {
            // only do the extra work of processing for escaped chars, if there is one.
            keyToInspect = removeEscapedValues( origKey );
            elementKey = removeEscapeChars( origKey );
        }
        else {
            keyToInspect = origKey;
            elementKey = origKey;
        }

        //// LHS single values
        if ( "@".equals( keyToInspect ) ) {
            return new AtPathElement( elementKey );
        }
        else if ( "*".equals( keyToInspect ) ) {
            return new StarAllPathElement( elementKey );
        }
        else if ( keyToInspect.startsWith( "[" ) ) {

            if ( StringTools.countMatches( keyToInspect, "[" ) != 1 || StringTools.countMatches(keyToInspect, "]") != 1 ) {
                throw new SpecException( "Invalid key:" + origKey + " has too many [] references.");
            }

            return new ArrayPathElement( elementKey );
        }
        //// LHS multiple values
        else if ( keyToInspect.startsWith("@") || keyToInspect.contains( "@(" ) ) {
            // The traspose path element gets the origKey so that it has it's escapes.
            return TransposePathElement.parse( origKey );
        }
        else if ( keyToInspect.contains( "@" ) ) {
            throw new SpecException( "Invalid key:" + origKey  + " can not have an @ other than at the front." );
        }
        else if ( keyToInspect.contains("$") ) {
            return new DollarPathElement( elementKey );
        }
        else if ( keyToInspect.contains("[") ) {

            if ( StringTools.countMatches(keyToInspect, "[") != 1 || StringTools.countMatches(keyToInspect, "]") != 1 ) {
                throw new SpecException( "Invalid key:" + origKey + " has too many [] references.");
            }

            return new ArrayPathElement( elementKey );
        }
        else if ( keyToInspect.contains( "&" ) ) {

            if ( keyToInspect.contains("*") )
            {
                throw new SpecException( "Invalid key:" + origKey + ", Can't mix * with & ) ");
            }
            return new AmpPathElement( elementKey );
        }
        else if ( keyToInspect.contains("*" ) ) {

            int numOfStars = StringTools.countMatches(keyToInspect, "*");

            if(numOfStars == 1){
                return new StarSinglePathElement( elementKey );
            }
            else if(numOfStars == 2){
                return new StarDoublePathElement( elementKey );
            }
            else {
                return new StarRegexPathElement( elementKey );
            }
        }
        else if ( keyToInspect.contains("#" ) ) {
            return new HashPathElement( elementKey );
        }
        else {
            return new LiteralPathElement( elementKey );
        }
    }

    /**
     * Parse the dotNotation of the RHS.
     */
    public static List parseDotNotationRHS( String dotNotation ) {
        String fixedNotation = fixLeadingBracketSugar( dotNotation );
        List pathStrs = parseDotNotation( new LinkedList(), stringIterator( fixedNotation ), dotNotation );

        return parseList( pathStrs, dotNotation );
    }

    /**
     * @param refDotNotation the original dotNotation string used for error messages
     * @return List of PathElements based on the provided List keys
     */
    public static List parseList( List keys, String refDotNotation ) {
        ArrayList paths = new ArrayList<>();

        for( String key: keys ) {
            PathElement path = parseSingleKeyLHS( key );
            if ( path instanceof AtPathElement ) {
                throw new SpecException( "'.@.' is not valid on the RHS: " + refDotNotation );
            }
            paths.add( path );
        }

        return paths;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy