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

io.katharsis.request.path.PathBuilder Maven / Gradle / Ivy

There is a newer version: 2.6.3
Show newest version
package io.katharsis.request.path;

import io.katharsis.resource.exception.ResourceException;
import io.katharsis.resource.exception.ResourceFieldNotFoundException;
import io.katharsis.resource.exception.ResourceNotFoundException;
import io.katharsis.resource.field.ResourceField;
import io.katharsis.resource.registry.RegistryEntry;
import io.katharsis.resource.registry.ResourceRegistry;
import io.katharsis.utils.StringUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * Builder responsible for parsing URL path.
 */
public class PathBuilder {
    public static final String SEPARATOR = "/";
    public static final String RELATIONSHIP_MARK = "relationships";

    private final ResourceRegistry resourceRegistry;

    public PathBuilder(ResourceRegistry resourceRegistry) {
        this.resourceRegistry = resourceRegistry;
    }

    /**
     * Parses path provided by the application. The path provided cannot contain neither hostname nor protocol. It
     * can start or end with slash e.g. /tasks/1/ or tasks/1.
     *
     * @param path Path to be parsed
     * @return doubly-linked list which represents path given at the input
     */
    public JsonPath buildPath(String path) {
        String[] strings = splitPath(path);
        if (strings.length == 0 || (strings.length == 1 && "".equals(strings[0]))) {
            throw new ResourceException("Path is empty");
        }

        JsonPath previousJsonPath = null, currentJsonPath = null;
        PathIds pathIds;
        boolean relationshipMark;
        String elementName;

        for (int currentElementIdx = 0; currentElementIdx < strings.length; ) {
            elementName = null;
            pathIds = null;
            relationshipMark = false;

            if (RELATIONSHIP_MARK.equals(strings[currentElementIdx])) {
                relationshipMark = true;
                currentElementIdx++;
            }

            if (currentElementIdx < strings.length && !RELATIONSHIP_MARK.equals(strings[currentElementIdx])) {
                elementName = strings[currentElementIdx];
                currentElementIdx++;
            }

            if (currentElementIdx < strings.length && !RELATIONSHIP_MARK.equals(strings[currentElementIdx])) {
                pathIds = createPathIds(strings[currentElementIdx]);
                currentElementIdx++;
            }
            RegistryEntry entry = resourceRegistry.getEntry(elementName);
            if (previousJsonPath != null) {
                currentJsonPath = getNonResourcePath(previousJsonPath, elementName, relationshipMark);
                if (pathIds != null) {
                    throw new ResourceException("RelationshipsPath and FieldPath cannot contain ids");
                }
            } else if (entry != null && !relationshipMark) {
                currentJsonPath = new ResourcePath(elementName);
            } else {
                throw new ResourceNotFoundException(path);
            }

            if (pathIds != null) {
                currentJsonPath.setIds(pathIds);
            }
            if (previousJsonPath != null) {
                previousJsonPath.setChildResource(currentJsonPath);
                currentJsonPath.setParentResource(previousJsonPath);
            }
            previousJsonPath = currentJsonPath;
        }

        return currentJsonPath;
    }

    private JsonPath getNonResourcePath(JsonPath previousJsonPath, String elementName, boolean relationshipMark) {
        String previousElementName = previousJsonPath.getElementName();
        RegistryEntry previousEntry = resourceRegistry.getEntry(previousElementName);
        Set resourceFields = previousEntry.getResourceInformation().getRelationshipFields();
        for (ResourceField field : resourceFields) {
            if (field.getJsonName().equals(elementName)) {
                if (relationshipMark) {
                    return new RelationshipsPath(elementName);
                } else {
                    return new FieldPath(elementName);
                }
            }
        }
        //TODO: Throw different exception? element name can be null..
        throw new ResourceFieldNotFoundException(elementName);
    }

    private static PathIds createPathIds(String idsString) {
        List pathIds = Arrays.asList(idsString.split(PathIds.ID_SEPARATOR_PATTERN));
        return new PathIds(pathIds);
    }

    private static String[] splitPath(String path) {
        if (path.startsWith(SEPARATOR)) {
            path = path.substring(1);
        }
        if (path.endsWith(SEPARATOR)) {
            path = path.substring(0, path.length());
        }
        return path.split(SEPARATOR);
    }

    /**
     * Creates a path using the provided JsonPath structure.
     *
     * @param jsonPath JsonPath structure to be parsed
     * @return String representing structure provided in the input
     */
    public static String buildPath(JsonPath jsonPath) {
        List urlParts = new LinkedList();

        JsonPath currentJsonPath = jsonPath;
        String pathPart;
        do {
            if (currentJsonPath instanceof RelationshipsPath) {
                pathPart = RELATIONSHIP_MARK + SEPARATOR + currentJsonPath.getElementName();
            } else if (currentJsonPath instanceof FieldPath) {
                pathPart = currentJsonPath.getElementName();
            } else {
                pathPart = currentJsonPath.getElementName();
                if (currentJsonPath.getIds() != null) {
                    pathPart += SEPARATOR + mergeIds(currentJsonPath.getIds());
                }
            }
            urlParts.add(pathPart);

            currentJsonPath = currentJsonPath.getParentResource();
        } while (currentJsonPath != null);
        Collections.reverse(urlParts);

        return SEPARATOR + StringUtils.join(SEPARATOR, urlParts) + SEPARATOR;
    }

    private static String mergeIds(PathIds ids) {
        return StringUtils.join(PathIds.ID_SEPARATOR, ids.getIds());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy