blob: b1399f1f90be018a27f9656dbb083113b638e968 [file] [log] [blame]
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you 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 org.apache.sling.scripting.bundle.tracker;
import java.util.Objects;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.framework.Version;
/**
* The {@code ResourceTypeParser} provides methods for parsing resource type strings.
*
* <p>The following patterns are supported:</p>
* <ol>
* <li><tt>a/b/c</tt> - path-based</li>
* <li><tt>a/b/c/1.0.0</tt> - path-based, versioned</li>
* <li><tt>a.b.c</tt> - Java package name</li>
* <li><tt>a.b.c/1.0.0</tt> - Java package name, versioned</li>
* <li><tt>a</tt> - flat (sub-set of path-based)</li>
* </ol>
*/
public final class ResourceType {
private static final Pattern versionPattern = Pattern.compile("[\\d\\.]+(-.*)*$");
private final String type;
private final String version;
private final String resourceLabel;
private final String toString;
private ResourceType(@NotNull String type, @Nullable String version) {
this.type = type;
this.version = version;
if (type.lastIndexOf('/') != -1) {
resourceLabel = type.substring(type.lastIndexOf('/') + 1);
} else if (type.lastIndexOf('.') != -1) {
resourceLabel = type.substring(type.lastIndexOf('.') + 1);
} else {
resourceLabel = type;
}
toString = type + (version == null ? "" : "/" + version);
}
/**
* Returns a resource type's label. The label is important for script selection, since it will provide the name of the main script
* for this resource type. For more details check the Apache Sling
* <a href="https://sling.apache.org/documentation/the-sling-engine/url-to-script-resolution.html#scripts-for-get-requests">URL to
* Script Resolution</a> page
*
* @return the resource type label
*/
@NotNull
public String getResourceLabel() {
return resourceLabel;
}
/**
* Returns the resource type string, without any version information.
*
* @return the resource type string
*/
@NotNull
public String getType() {
return type;
}
/**
* Returns the version, if available.
*
* @return the version, if available; {@code null} otherwise
*/
@Nullable
public String getVersion() {
return version;
}
@Override
public String toString() {
return toString;
}
/**
* Given a {@code resourceTypeString}, this method will extract a {@link ResourceType} object.
* <p>The accepted patterns are:</p>
* <ol>
* <li><tt>a/b/c</tt> - path-based</li>
* <li><tt>a/b/c/1.0.0</tt> - path-based, versioned</li>
* <li><tt>a.b.c</tt> - Java package name</li>
* <li><tt>a.b.c/1.0.0</tt> - Java package name, versioned</li>
* <li><tt>a</tt> - flat (sub-set of path-based)</li>
* </ol>
*
* @param resourceTypeString the resource type string to parse
* @return a {@link ResourceType} object
* @throws IllegalArgumentException if the {@code resourceTypeString} cannot be parsed
*/
@NotNull
public static ResourceType parseResourceType(@NotNull String resourceTypeString) {
String type = StringUtils.EMPTY;
String version = null;
if (StringUtils.isNotEmpty(resourceTypeString)) {
int lastSlash = resourceTypeString.lastIndexOf('/');
if (lastSlash != -1 && !resourceTypeString.endsWith("/")) {
String versionString = resourceTypeString.substring(lastSlash + 1);
if (versionPattern.matcher(versionString).matches()) {
try {
version = Version.parseVersion(versionString).toString();
type = resourceTypeString.substring(0, lastSlash);
} catch (IllegalArgumentException e) {
type = resourceTypeString;
}
} else {
type = resourceTypeString;
}
} else {
type = resourceTypeString;
}
}
if (StringUtils.isEmpty(type)) {
throw new IllegalArgumentException(String.format("Cannot extract a type for the resourceTypeString %s.", resourceTypeString));
}
return new ResourceType(type, version);
}
@Override
public int hashCode() {
return Objects.hash(type, version, resourceLabel);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ResourceType) {
ResourceType other = (ResourceType) obj;
return Objects.equals(type, other.type) && Objects.equals(version, other.version) && Objects.equals(resourceLabel,
other.resourceLabel);
}
return false;
}
}