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

io.atlasmap.core.AtlasPath Maven / Gradle / Ivy

/**
 * Copyright (C) 2017 Red Hat, 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 io.atlasmap.core;

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

public class AtlasPath {
    public static final String PATH_SEPARATOR = "/";
    public static final String PATH_SEPARATOR_ESCAPED = "/";
    public static final String PATH_ARRAY_START = "[";
    public static final String PATH_ARRAY_END = "]";
    public static final String PATH_LIST_START = "<";
    public static final String PATH_LIST_END = ">";
    public static final String PATH_MAP_START = "{";
    public static final String PATH_MAP_END = "}";

    private static final Pattern PATTERN_INDEXED_COLLECTION = Pattern.compile(
            ".*[\\" + PATH_ARRAY_START + PATH_LIST_START + PATH_MAP_START + "][0-9]+"
            + "[\\" + PATH_ARRAY_END + PATH_LIST_END + PATH_MAP_END + "]$");

    private List segments = new ArrayList<>();
    private String originalPath = null;

    public AtlasPath(String p) {
        String path = p;
        this.originalPath = path;
        if (path != null && !"".equals(path)) {
            if (path.startsWith(PATH_SEPARATOR)) {
                path = path.replaceFirst(PATH_SEPARATOR, "");
            }
            if (path.contains(PATH_SEPARATOR)) {
                String[] parts = path.split(PATH_SEPARATOR_ESCAPED, 512);
                for (String part : parts) {
                    getSegments().add(part);
                }
            } else if (!path.isEmpty()) {
                getSegments().add(path);
            }
        }
    }

    private AtlasPath() {
    }

    public List getSegmentContexts(boolean includeLeadingSlashSegment) {
        List contexts = new LinkedList<>();
        String segmentPath = "";
        SegmentContext previousContext = null;
        int index = 0;

        List newSegments = this.getSegments();
        if (includeLeadingSlashSegment) {
            newSegments.add(0, "");
        }

        for (String s : newSegments) {
            SegmentContext c = new SegmentContext();
            segmentPath += PATH_SEPARATOR + s;
            c.setPathUtil(this);
            c.setSegment(s);
            c.setSegmentIndex(index);
            c.setSegmentPath(segmentPath);
            if (previousContext != null) {
                c.setPrev(previousContext);
                previousContext.setNext(c);

            }
            contexts.add(c);
            previousContext = c;
            if (index == 0 && includeLeadingSlashSegment) {
                segmentPath = "";
            }
            index++;
        }
        return contexts;
    }

    public AtlasPath appendField(String fieldName) {
        this.segments.add(fieldName);
        return this;
    }

    public List getSegments() {
        return this.segments;
    }

    public String getLastSegment() {
        if (segments.isEmpty()) {
            return null;
        }
        return segments.get(segments.size() - 1);
    }

    public boolean hasParent() {
        return segments.size() > 1;
    }

    public static String removeCollectionIndexes(String path) {
        AtlasPath pathUtil = new AtlasPath(path);
        String cleanedPath = "";
        for (String s : pathUtil.getSegments()) {
            cleanedPath += PATH_SEPARATOR + removeCollectionIndex(s);
        }
        return cleanedPath;
    }

    public static String removeCollectionIndex(String segment) {
        if (segment == null) {
            return null;
        }

        if (segment.contains(PATH_ARRAY_START) && segment.contains(PATH_ARRAY_END)) {
            return segment.substring(0, segment.indexOf(PATH_ARRAY_START) + 1)
                    + segment.substring(segment.indexOf(PATH_ARRAY_END));
        }

        if (segment.contains(PATH_LIST_START) && segment.contains(PATH_LIST_END)) {
            return segment.substring(0, segment.indexOf(PATH_LIST_START) + 1)
                    + segment.substring(segment.indexOf(PATH_LIST_END));
        }

        if (segment.contains(PATH_MAP_START) && segment.contains(PATH_MAP_END)) {
            return segment.substring(0, segment.indexOf(PATH_MAP_START) + 1)
                    + segment.substring(segment.indexOf(PATH_MAP_END));
        }

        return segment;
    }

    public boolean hasCollection() {
        for (String seg : getSegments()) {
            if (isCollectionSegment(seg)) {
                return true;
            }
        }
        return false;
    }

    public Boolean isIndexedCollection() {
        boolean hasCollection = false;
        for (String seg : getSegments()) {
            if (isCollectionSegment(seg)) {
                hasCollection = true;
                if (indexOfSegment(seg) == null) {
                    return false;
                }
            }
        }
        return hasCollection;
    }

    public Boolean isRoot() {
        return segments.size() == 0;
    }

    public Boolean isCollectionRoot() {
        return isCollectionSegment(getLastSegment());
    }

    public String getLastSegmentParent() {
        if (segments.isEmpty() || segments.size() == 1) {
            return null;
        }

        return segments.get(segments.size() - 2);
    }

    public AtlasPath getLastSegmentParentPath() {
        if (segments.isEmpty() || segments.size() == 1) {
            return null;
        }

        AtlasPath parentPath = new AtlasPath();
        for (int i = 0; i < segments.size() - 1; i++) {
            parentPath.appendField(segments.get(i));
        }
        return parentPath;
    }

    public AtlasPath deCollectionify(String collectionSegment) {
        if (segments.isEmpty() || segments.size() == 1) {
            return null;
        }

        AtlasPath j = new AtlasPath();
        boolean collectionFound = false;
        for (String part : segments) {
            if (collectionFound) {
                j.appendField(part);
            }
            String cleanedPart = cleanPathSegment(part);
            if (cleanedPart != null && cleanedPart.equals(cleanPathSegment(collectionSegment))) {
                collectionFound = true;
            }
        }
        return j;
    }

    public AtlasPath deParentify() {
        if (segments.isEmpty() || segments.size() == 1) {
            return null;
        }

        AtlasPath j = new AtlasPath();
        for (int i = 1; i < segments.size(); i++) {
            j.appendField(segments.get(i));
        }
        return j;
    }

    /**
     * Remove all decoration other than path name from path segment expression.
     * This removes namespace prefixes and leading @ symbol for attributes, as well as
     * collection suffixes like [], [1], <> and etc.
     *
     * @param pathSeg path segment expression string
     * @return stripped segment name
     */
    public static String cleanPathSegment(String pathSeg) {
        String pathSegment = pathSeg;
        if (pathSegment == null) {
            return null;
        }

        // strip namespace if there is one
        if (pathSegment.contains(":")) {
            pathSegment = pathSegment.substring(pathSegment.indexOf(":") + 1);
        }

        // strip leading @ symbol if there is one
        if (pathSegment.startsWith("@")) {
            pathSegment = pathSegment.substring(1);
        }

        if (pathSegment.contains(PATH_ARRAY_START) && pathSegment.endsWith(PATH_ARRAY_END)) {
            return pathSegment.substring(0, pathSegment.indexOf(PATH_ARRAY_START, 0));
        }

        if (pathSegment.contains(PATH_LIST_START) && pathSegment.endsWith(PATH_LIST_END)) {
            return pathSegment.substring(0, pathSegment.indexOf(PATH_LIST_START, 0));
        }

        if (pathSegment.contains(PATH_MAP_START) && pathSegment.endsWith(PATH_MAP_END)) {
            return pathSegment.substring(0, pathSegment.indexOf(PATH_MAP_START, 0));
        }

        return pathSegment;
    }

    public static String getAttribute(String pathSeg) {
        return pathSeg.substring(1);
    }

    public static Boolean isCollectionSegment(String pathSegment) {
        if (pathSegment == null) {
            return false;
        }

        if (pathSegment.contains(PATH_ARRAY_START) && pathSegment.endsWith(PATH_ARRAY_END)) {
            return true;
        }

        if (pathSegment.contains(PATH_LIST_START) && pathSegment.endsWith(PATH_LIST_END)) {
            return true;
        }

        return pathSegment.contains(PATH_MAP_START) && pathSegment.endsWith(PATH_MAP_END);
    }

    public static Boolean isIndexedCollectionSegment(String pathSegment) {
        return PATTERN_INDEXED_COLLECTION.matcher(pathSegment).matches();
    }

    public static Boolean isAttributeSegment(String pathSegment) {
        return pathSegment != null && pathSegment.startsWith("@");
    }

    /**
     * Return collection index in the path segment expression passed in as an argument.
     * This returns null if specified path segment expression doesn't have an index, or not
     * a collection.
     *
     * @param pathSegment path segment expression
     * @return collection index of specified path segment
     */
    public static Integer indexOfSegment(String pathSegment) {
        if (pathSegment == null) {
            return null;
        }

        if (pathSegment.contains(PATH_ARRAY_START) && pathSegment.endsWith(PATH_ARRAY_END)) {
            int start = pathSegment.indexOf(PATH_ARRAY_START, 0) + 1;
            String index = pathSegment.substring(start, pathSegment.indexOf(PATH_ARRAY_END, start));
            if (index != null && index.length() > 0) {
                return Integer.valueOf(index);
            }
            return null;
        }

        if (pathSegment.contains(PATH_LIST_START) && pathSegment.endsWith(PATH_LIST_END)) {
            int start = pathSegment.indexOf(PATH_LIST_START, 0) + 1;
            String index = pathSegment.substring(start, pathSegment.indexOf(PATH_LIST_END, start));
            if (index != null && index.length() > 0) {
                return Integer.valueOf(index);
            }
            return null;
        }

        return null;
    }

    public Integer getCollectionIndex(String segment) {
        for (String part : getSegments()) {
            String cleanedPart = cleanPathSegment(part);
            if (cleanedPart != null && cleanedPart.equals(cleanPathSegment(segment))
                    && ((part.contains(PATH_ARRAY_START) && part.contains(PATH_ARRAY_END))
                            || (part.contains(PATH_LIST_START) && (part.contains(PATH_LIST_END))))) {
                return indexOfSegment(part);
            }
        }

        return null;
    }

    public String getCollectionSegment() {
        for (String part : getSegments()) {
            if (AtlasPath.isCollectionSegment(part)) {
                return part;
            }
        }
        return null;
    }

    public void setCollectionIndex(String segment, Integer index) {
        if (segment == null) {
            throw new IllegalArgumentException("PathUtil segment cannot be null");
        }

        if (index < 0) {
            throw new IllegalArgumentException("PathUtil index must be a positive integer");
        }

        if (segment.contains(PATH_ARRAY_START) && segment.contains(PATH_ARRAY_END)) {
            for (int i = 0; i < getSegments().size(); i++) {
                String part = cleanPathSegment(getSegments().get(i));
                if (part != null && part.equals(cleanPathSegment(segment))) {
                    getSegments().set(i, cleanPathSegment(segment) + PATH_ARRAY_START + index + PATH_ARRAY_END);
                }
            }
        } else if (segment.contains(PATH_LIST_START) && segment.contains(PATH_LIST_END)) {
            for (int i = 0; i < getSegments().size(); i++) {
                String part = cleanPathSegment(getSegments().get(i));
                if (part != null && part.equals(cleanPathSegment(segment))) {
                    getSegments().set(i, cleanPathSegment(segment) + PATH_LIST_START + index + PATH_LIST_END);
                }
            }
        } else {
            throw new IllegalArgumentException("PathUtil segment is not a List or Array segment");
        }
    }

    public void setVacantCollectionIndex(Integer index) {
        // TODO need rework for nested collection
        // https://github.com/atlasmap/atlasmap/issues/435
        for (int i=0; i 1) {
            builder.append(PATH_SEPARATOR);
        }

        for (String part : getSegments()) {
            builder.append(part);
            if (i < (getSegments().size() - 1)) {
                builder.append(PATH_SEPARATOR);
            }
            i++;
        }
        return builder.toString();
    }

    public String getOriginalPath() {
        return originalPath;
    }

    /**
     * Returns true if specified path segment is array segment, otherwise false.
     *
     * @param segment path segment expression
     * @return true for array segment, otherwise false
     */
    public static boolean isArraySegment(String segment) {
        return isCollectionSegment(segment) && segment.contains(PATH_ARRAY_START);
    }

    /**
     * Returns true if specified path segment is list segment, otherwise false.
     *
     * @param segment path segment expression
     * @return true for list segment, otherwise false
     */
    public static boolean isListSegment(String segment) {
        return isCollectionSegment(segment) && segment.contains(PATH_LIST_START);
    }

    /**
     * Returns true if specified path segment is map segment, otherwise false.
     *
     * @param segment path segment expression
     * @return true for map segment, otherwise false
     */
    public static boolean isMapSegment(String segment) {
        return isCollectionSegment(segment) && segment.contains(PATH_MAP_START);
    }

    public static class SegmentContext {

        protected String segment;
        protected String segmentPath;
        protected int segmentIndex;

        protected SegmentContext prev;
        protected SegmentContext next;
        protected AtlasPath pathUtil;

        public String getSegment() {
            return segment;
        }

        public void setSegment(String segment) {
            this.segment = segment;
        }

        public String getSegmentPath() {
            return segmentPath;
        }

        public void setSegmentPath(String segmentPath) {
            this.segmentPath = segmentPath;
        }

        public int getSegmentIndex() {
            return segmentIndex;
        }

        public void setSegmentIndex(int segmentIndex) {
            this.segmentIndex = segmentIndex;
        }

        public SegmentContext getPrev() {
            return prev;
        }

        public void setPrev(SegmentContext prev) {
            this.prev = prev;
        }

        public SegmentContext getNext() {
            return next;
        }

        public void setNext(SegmentContext next) {
            this.next = next;
        }

        public void setPathUtil(AtlasPath pathUtil) {
            this.pathUtil = pathUtil;
        }

        public AtlasPath getPathUtil() {
            return pathUtil;
        }

        public boolean hasParent() {
            return this.prev != null;
        }

        public boolean hasChild() {
            return this.next != null;
        }

        @Override
        public String toString() {
            return "SegmentContext [segment=" + segment + ", segmentPath=" + segmentPath + ", segmentIndex="
                    + segmentIndex + "]";
        }
    }

    public static boolean isCollection(String path) {
        return new AtlasPath(path).hasCollection();
    }

    public static String overwriteCollectionIndex(String path, int index) {
        String newPath = "";
        for (SegmentContext sg : new AtlasPath(path).getSegmentContexts(false)) {
            String segment = sg.getSegment();
            if (AtlasPath.isCollection(segment)) {
                if (segment.contains(PATH_ARRAY_START) && segment.contains(PATH_ARRAY_END)) {
                    segment = cleanPathSegment(segment) + PATH_ARRAY_START + index + PATH_ARRAY_END;
                } else if (segment.contains(PATH_LIST_START) && segment.contains(PATH_LIST_END)) {
                    segment = cleanPathSegment(segment) + PATH_LIST_START + index + PATH_LIST_END;
                }
            }
            newPath += PATH_SEPARATOR + segment;
        }
        return newPath;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy