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

org.eclipse.basyx.vab.modelprovider.VABPathTools Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (C) 2021 the Eclipse BaSyx Authors
 * 
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 * 
 * SPDX-License-Identifier: EPL-2.0
 ******************************************************************************/
package org.eclipse.basyx.vab.modelprovider;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation;
import org.eclipse.basyx.vab.exception.provider.MalformedRequestException;

/**
 * Utility functions to handle a VAB path
 * 
 * @author kuhn, espen
 * 
 */
public class VABPathTools {
	public static final String SEPERATOR = "/";

	/**
	 * Removes leading and trailing slashes
	 * 
	 * @param path
	 * @return
	 */
	public static String stripSlashes(String path) {
		while (path.startsWith("/")) {
			path = path.substring(1);
		}

		while (path.endsWith("/")) {
			path = path.substring(0, path.length() - 1);
		}
		return path;
	}

	/**
	 * Encodes sensitive characters, e.g. "/" and "#"
	 * 
	 * @param elem
	 * @return
	 */
	public static String encodePathElement(String elem) {
		try {
			return URLEncoder.encode(elem, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Decodes sensitive characters, e.g. "/" and "#"
	 * 
	 * @param elem
	 * @return
	 */
	public static String decodePathElement(String encodedElem) {
		try {
			return URLDecoder.decode(encodedElem, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Skips the first N entries of a path. E.g. for a/b/c skipping 2 means
	 * returning c
	 * 
	 * @param path
	 * @param toSkip
	 * @return
	 */
	public static String skipEntries(String path, int toSkip) {
		StringBuilder builder = new StringBuilder();
		String[] splitted = VABPathTools.splitPath(path);

		for (int i = toSkip; i < splitted.length; i++) {
			builder.append(splitted[i]);

			// Don't add slash at last step
			if (i < splitted.length - 1) {
				builder.append("/");
			}

		}

		return builder.toString();
	}

	/**
	 * Returns the Nth entry of a path, e.g. the second entry of a/b/c is
	 * c
	 * 
	 * @param path
	 * @param entry
	 * @return
	 */
	public static String getEntry(String path, int entry) {
		return VABPathTools.splitPath(path)[entry];
	}

	/**
	 * Split a path into path elements, e.g. /a/b/c -> [ a, b, c ]
	 */
	public static String[] splitPath(String path) {
		// Return null result for null argument
		if (path == null) {
			return null;
		}

		// includes null-values, "" and "/";
		if (VABPathTools.isEmptyPath(path)) {
			return new String[] {};
		}

		// Remove leading separator, otherwise /a leads to {"", "a"}
		String fixedPath = removePrefix(path, SEPERATOR);

		String[] splitted = fixedPath.split(SEPERATOR);
		List nonEmptySplitted = new ArrayList<>();

		// Remove empty entries
		for (String s : splitted) {
			if (!s.isEmpty()) {
				nonEmptySplitted.add(s);
			}
		}
		return nonEmptySplitted.toArray(new String[nonEmptySplitted.size()]);
	}

	/**
	 * Remove the last element from the path
	 */
	public static String getParentPath(String path) {
		// Return null result for null argument
		if (path == null) {
			return null;
		}

		if (isEmptyPath(path)) {
			return "";
		}
		int lastIndex = path.lastIndexOf(SEPERATOR);
		if (lastIndex == path.length() - 1) {
			lastIndex = path.lastIndexOf(SEPERATOR, path.length() - 2);
		}
		if (lastIndex >= 0) {
			return removePrefix(path.substring(0, lastIndex), SEPERATOR);
		} else {
			return "";
		}
	}

	/**
	 * Get the last element of a path. Return "" if there is no element in the path
	 */
	public static String getLastElement(String path) {
		// Return null result for null argument
		if (path == null) {
			return null;
		}

		String[] elements = splitPath(path);
		if (elements.length > 0) {
			return elements[elements.length - 1];
		} else {
			return "";
		}
	}

	/**
	 * Remove prefix from beginning of path
	 */
	public static String removePrefix(String path, String prefix) {
		// Return null result for null argument
		if (path == null) {
			return null;
		}

		if (VABPathTools.isEmptyPath(path)) {
			// same result as for any other "empty" path, like "" and "/"
			return "";
		}
		if (path.startsWith(prefix)) {
			return path.substring(prefix.length());
		} else {
			return path;
		}
	}

	public static String append(String path, String element) {
		// Return null result for null argument
		if (path == null || element == null) {
			return null;
		}

		if (path.lastIndexOf(SEPERATOR) == path.length() - 1) {
			return path + element;
		} else {
			return path + SEPERATOR + element;
		}
	}

	/**
	 * Build and return a path with pathElements[startIndex] as the root element
	 */
	public static String buildPath(String[] pathElements, int startIndex) {
		// Return null result for null argument
		if (pathElements == null) {
			return null;
		}

		if (startIndex >= pathElements.length) {
			return "";
		}

		// This will store the resulting path
		StringBuilder result = new StringBuilder();

		// Build path
		for (int i = startIndex; i < pathElements.length; i++)
			result.append(pathElements[i] + SEPERATOR);

		// Remove last '/'
		result.deleteCharAt(result.length() - 1);

		// Return created path
		return result.toString();
	}

	/**
	 * Check if the path to an VAB elements leads to the invocation of an operation. In this case, the
	 * element path conforms to /aas/submodels/{subModelId}/submodelElements/{operationId}/invoke
	 */
	public static boolean isOperationInvokationPath(String path) {
		// null-Paths are no operation paths
		if (path == null) {
			return false;
		}

		// Split path
		String[] pathElements = splitPath(path);
		
		if(pathElements.length == 0) {
			return false;
		}

		// Check if last path element is "invoke" or "operations" is contained anywhere
		return pathElements[pathElements.length - 1].startsWith(Operation.INVOKE) || isOperationPath(path);
	}

	private static boolean isOperationPath(String path) {
		String lowerCasePath = path.toLowerCase();
		return lowerCasePath.startsWith("operations/") || path.toLowerCase().contains("/operations/");
	}

	/**
	 * Check, if the path does not contain any elements.
	 */
	public static boolean isEmptyPath(String path) {
		return path.equals("") || path.equals("/");
	}

	/**
	 * Gets the first endpoint of a path.
	 * @path 
	 * 		A path that can contain 0..* endpoints.
	 * @return
	 * 		The first address entry of a path. The address entry is the first endpoint combined with a protocol.
	 * 		If there is no protocol defined, the address entry is empty ("").
	 * 		E.g. basyx://127.0.0.1:6998//https://localhost/test/ will return basyx://127.0.0.1:6998, 
	 * 		https://localhost/test//basyx://127.0.0.1:6998/ will return https://localhost/test
	 * 		and http://localhost/test/ will return "". 
	 */
	public static String getFirstEndpoint(String fullPath) {
		// Return null result for null argument
		if (fullPath == null) {
			return null;
		}

		if (isEmptyPath(fullPath) || !fullPath.contains("//")) {
			return "";
		} else {
			String[] splitted = fullPath.split("//");
			return splitted[0] + "//" + splitted[1];
		}
	}

	/**
	 * Removes the first endpoint from a path. See {@link #getAddressEntry}
* @path * @return * The first endpoint. E.g. basyx://127.0.0.1:6998//https://localhost/test/ will return * https://localhost/test/. * */ public static String removeFirstEndpoint(String fullPath) { // Return null result for null argument if (fullPath == null) { return null; } if (isEmptyPath(fullPath)) { return ""; } else if (!fullPath.contains("//")) { return fullPath; } else { String firstEndpoint = fullPath.replaceFirst(getFirstEndpoint(fullPath), ""); if (firstEndpoint.startsWith("//")) { firstEndpoint = firstEndpoint.replaceFirst("//", ""); } return firstEndpoint; } } /** * Concatenate two paths */ public static String concatenatePaths(String... paths) { // Return null result for null argument if (paths == null || paths.length == 0) { return null; } // Store result StringBuffer result = new StringBuffer(); // Flag that indicates whether processed path segment is first segment boolean isFirst = true; // Process all path segments for (String pathSegment : paths) { // Return empty result, if any element is null if (pathSegment == null) { return null; } // Remove leading and trailing "/" from pathsegment while (pathSegment.endsWith("/")) pathSegment = pathSegment.substring(0, pathSegment.length() - 1); while (pathSegment.startsWith("/")) pathSegment = pathSegment.substring(1); // Add path to result; if its first segment, do not split with "'" if (!isFirst) result.append("/"); else isFirst = false; result.append(pathSegment); } // Return combined path return result.toString(); } /** * Checks if path is null, if yes throw exception * * @param path */ public static void checkPathForNull(String path) throws MalformedRequestException { if (path == null) { throw new MalformedRequestException("Path is not allowed to be null"); } } /** * Strips the last path element if it is "invoke" * * @param path * @return path without last element "invoke" or unchanged path */ public static String stripInvokeFromPath(String path) { if(path == null) return null; if(getLastElement(path).startsWith(Operation.INVOKE)) { return getParentPath(path); } return path; } /** * Gets the path from a URL * e.g "http://localhost:8080/path/to/test.file" results in "/path/to/test.file" * * @param url * @return the path from the URL */ public static String getPathFromURL(String url) { if(url == null) { return null; } if(url.contains("://")) { // Find the ":" and and remove the "http://" from the url int index = url.indexOf(":") + 3; url = url.substring(index); // Find the first "/" from the URL (now without the "http://") and remove everything before that index = url.indexOf("/"); url = url.substring(index); // Recursive call to deal with more than one server parts // (e.g. basyx://127.0.0.1:6998//https://localhost/test/) return getPathFromURL(url); } else { // Make sure the path has a / at the start if(!url.startsWith("/")) { url = "/" + url; } return url; } } /** * Harmonizes a path so that it will always and with the suffix and no ending * slash (even if the suffix contains one). * * @param path * to harmonize * @param suffix * to check for existance and append if necessary * @return harmonized path */ public static String harmonizePathWithSuffix(String path, String suffix) { String strippedPath = stripSlashes(path); String strippedSuffix = stripSlashes(suffix); if (strippedPath.endsWith("/" + strippedSuffix)) { return strippedPath; } else { return VABPathTools.concatenatePaths(strippedPath, strippedSuffix); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy