package org.springframework.roo.classpath;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.roo.metadata.MetadataIdentificationUtils;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.project.LogicalPath;
import org.springframework.roo.project.Path;
/**
* Produces metadata identification strings that represent a {@link JavaType}
* located in a particular {@link LogicalPath}.
* <p>
* The metadata identification strings separate the path name from the fully
* qualified type name via the presence of a question mark character ("?"). A
* question mark is used given it is reserved by {@link Path}. TODO these
* methods are not specific to physical types; either rename this class, move
* them somewhere more generic, and/or make them more specific, e.g. hardcode
* the "metadata class" arguments to that of physical types.
*
* @author Ben Alex
* @since 1.0
*/
public final class PhysicalTypeIdentifierNamingUtils {
private static final String PATH_SUFFIX = "?";
/**
* Creates a metadata ID from the given inputs
*
* @param metadataClass the fully-qualified name of the metadata class
* (required)
* @param projectType the fully-qualified name of the user project type to
* which the metadata relates (required)
* @param path the path to that type within the project (required)
* @return a non-blank ID
*/
public static String createIdentifier(final String metadataClass, final JavaType projectType,
final LogicalPath path) {
Validate.notNull(projectType, "Java type required");
Validate.notNull(path, "Path required");
return MetadataIdentificationUtils.create(metadataClass, path.getName() + PATH_SUFFIX
+ projectType.getFullyQualifiedTypeName());
}
/**
* Parses the instance key from the given metadata ID.
*
* @param metadataClass the fully-qualified name of the metadata type
* (required)
* @param metadataId the ID of the metadata instance (must identify an
* instance of the given metadata class)
* @return a non-blank key, as per
* {@link MetadataIdentificationUtils#getMetadataInstance(String)}
*/
private static String getInstanceKey(final String metadataClass, final String metadataId) {
Validate.isTrue(isValid(metadataClass, metadataId),
"Metadata id '%s' is not a valid %s identifier", metadataId, metadataClass);
return MetadataIdentificationUtils.getMetadataInstance(metadataId);
}
public static JavaType getJavaType(final String metadataIdentificationString) {
Validate.isTrue(metadataIdentificationString.contains("#"),
"Metadata identification string '%s' does not appear to be a valid identifier",
metadataIdentificationString);
final String instance =
MetadataIdentificationUtils.getMetadataInstance(metadataIdentificationString);
final int index = instance.indexOf("?");
return new JavaType(instance.substring(index + 1),
getModuleFromIdentificationString(metadataIdentificationString));
}
/**
* Returns the user project type with which the given metadata ID is
* associated.
*
* @param metadataClass the fully-qualified name of the metadata type
* (required)
* @param metadataId the ID of the metadata instance (must identify an
* instance of the given metadata class)
* @return a non-<code>null</code> type
*/
public static JavaType getJavaType(final String metadataClass, final String metadataId) {
final String instanceKey = getInstanceKey(metadataClass, metadataId);
return new JavaType(instanceKey.substring(instanceKey.indexOf(PATH_SUFFIX) + 1),
getModuleFromIdentificationString(metadataId));
}
/**
* Returns the name of the project module that contains the metadata item
* with the given id.
*
* @param metadataId must be a valid metadata instance id
* @return a non-<code>null</code> module name (blank means the root or only
* module)
* @since 1.2.0
*/
public static String getModule(final String metadataId) {
return getPath(metadataId).getModule();
}
/**
* Returns the {@link LogicalPath} of the metadata item with the given id.
*
* @param metadataId must be a valid metadata instance id
* @return a non-<code>null</code> path
*/
public static LogicalPath getPath(final String metadataId) {
Validate.isTrue(MetadataIdentificationUtils.isIdentifyingInstance(metadataId),
"Metadata id '%s' does not appear to be a valid identifier", metadataId);
final String instanceKey = MetadataIdentificationUtils.getMetadataInstance(metadataId);
final int index = instanceKey.indexOf("?");
return LogicalPath.getInstance(instanceKey.substring(0, index));
}
/**
* Parses the user project path from the given metadata ID.
*
* @param metadataClass the fully-qualified name of the metadata type
* (required)
* @param metadataId the ID of the metadata instance (must identify an
* instance of the given metadata class)
* @return a non-<code>null</code> path
*/
public static LogicalPath getPath(final String providesType,
final String metadataIdentificationString) {
Validate
.isTrue(
isValid(providesType, metadataIdentificationString),
"Metadata identification string '%s' does not appear to be a valid physical type identifier",
metadataIdentificationString);
final String instance =
MetadataIdentificationUtils.getMetadataInstance(metadataIdentificationString);
final int index = instance.indexOf("?");
return LogicalPath.getInstance(instance.substring(0, index));
}
/**
* Indicates whether the given metadata id appears to identify an instance
* of the given metadata class.
*
* @param metadataClass the fully-qualified name of the expected metadata
* type (can be blank)
* @param metadataId the ID to evaluate (can be blank)
* @return true only if the metadata ID appears to be valid
*/
public static boolean isValid(final String metadataClass, final String metadataId) {
return MetadataIdentificationUtils.isIdentifyingInstance(metadataId)
&& MetadataIdentificationUtils.getMetadataClass(metadataId).equals(metadataClass)
&& MetadataIdentificationUtils.getMetadataInstance(metadataId).contains(PATH_SUFFIX);
}
/**
* Constructor is private to prevent instantiation
*
* @since 1.2.0
*/
private PhysicalTypeIdentifierNamingUtils() {}
/**
* Extracts module name from a metadata identification string
*
* @param metadataId
* @return module name or null if metadataId is not a valid metadata identification string
*/
public static final String getModuleFromIdentificationString(String metadataId) {
return StringUtils.defaultString(StringUtils.substringBetween(metadataId, "#", ":"), "");
}
}