package org.marketcetera.module;
import org.marketcetera.util.misc.ClassVersion;
import org.marketcetera.util.log.I18NBoundMessage1P;
import org.marketcetera.util.log.I18NBoundMessage2P;
import org.marketcetera.util.log.I18NBoundMessage3P;
import org.marketcetera.util.log.I18NMessage1P;
/* $License$ */
/**
* Utilities to parse URNs used by the modules.
*
*
* @author anshul@marketcetera.com
* @version $Id: URNUtils.java 16154 2012-07-14 16:34:05Z colin $
* @since 1.0.0
*/
@ClassVersion("$Id: URNUtils.java 16154 2012-07-14 16:34:05Z colin $") //$NON-NLS-1$
public final class URNUtils {
/**
* The special keyword <code>this</code> that can be used within URNs
* by a {@link DataFlowRequester module} when creating data flows.
* The element of the URN with the <code>this</code>
* keyword is replaced with the respective element from the requesting
* module's URN.
*/
public static final String THIS = "this"; //$NON-NLS-1$
/**
* Validates the supplied providerURN.
*
* @param inURN the provider URN
*
* @throws InvalidURNException if the supplied URN is invalid
*/
public static void validateProviderURN(ModuleURN inURN)
throws InvalidURNException {
validateProviderURN(inURN, Messages.INCOMPLETE_PROVIDER_URN, false);
}
/**
* Validates the supplied provider URN.
*
* @param inURN the provider URN
* @param inIncompleteURNMessage the message code to use when throwing
* errors that indicate incomplete URNs
* @param inIsPrefix true, if the supplied URN should be validated
* as a prefix of an instance URN, false if it should be validated
* as an absolute provider URN.
*
* @throws InvalidURNException if the URN is invalid.
*/
private static void validateProviderURN(
ModuleURN inURN,
I18NMessage1P inIncompleteURNMessage,
boolean inIsPrefix)
throws InvalidURNException {
//verify that its not null
if(inURN == null) {
throw new InvalidURNException(new I18NBoundMessage1P(
Messages.EMPTY_URN, "")); //$NON-NLS-1$
}
//verify the scheme
verifyScheme(inURN);
//verify the provider type
String provType = inURN.providerType();
if(provType == null) {
throw new InvalidURNException(new I18NBoundMessage1P(
inIncompleteURNMessage, inURN.toString()));
}
//verify that provider type is a java identifier
if(!isValidIdentifier(provType)) {
throw new InvalidURNException(new I18NBoundMessage2P(
Messages.INVALID_PROVIDER_TYPE, inURN.toString(),provType));
}
//now verify the provider name
String provName = inURN.providerName();
if(provName == null) {
throw new InvalidURNException(new I18NBoundMessage1P(
inIncompleteURNMessage, inURN.toString()));
}
//verify that provider name is a java identifier
if(!isValidIdentifier(provName)) {
throw new InvalidURNException(new I18NBoundMessage2P(
Messages.INVALID_PROVIDER_NAME, inURN.toString(),provName));
}
if(!inIsPrefix && inURN.instanceURN()) {
throw new InvalidURNException(new I18NBoundMessage1P(
Messages.PROVIDER_URN_HAS_INSTANCE, inURN.toString()));
}
}
/**
* Verifies the URN scheme.
*
* @param inURN the URN to verify
*
* @throws InvalidURNException if the URN has an invalid scheme.
*/
private static void verifyScheme(ModuleURN inURN)
throws InvalidURNException {
if(!ModuleURN.SCHEME.equals(inURN.scheme())) {
throw new InvalidURNException(new I18NBoundMessage3P(
Messages.INVALID_URN_SCHEME, inURN.scheme(),
inURN.toString(), ModuleURN.SCHEME));
}
}
/**
* Validates the supplied instance URN.
*
* @param inURN the module instance URN
*
* @throws InvalidURNException If the module URN is invalid.
*/
public static void validateInstanceURN(ModuleURN inURN)
throws InvalidURNException {
validateInstanceURN(inURN, null);
}
/**
* Validates the module instance URN.
*
* @param inURN the module instance URN.
* @param inProviderURN the module provider URN. If not null,
* the module URN is verified to have this URN as its prefix.
*
* @throws InvalidURNException if the module URN is invalid.
*/
public static void validateInstanceURN(ModuleURN inURN,
ModuleURN inProviderURN)
throws InvalidURNException {
validateProviderURN(inURN, Messages.INCOMPLETE_INSTANCE_URN, true);
if(!inURN.instanceURN()) {
throw new InvalidURNException(new I18NBoundMessage1P(
Messages.INCOMPLETE_INSTANCE_URN, inURN.toString()));
}
String instanceName = inURN.instanceName();
if(!isValidIdentifier(instanceName)) {
throw new InvalidURNException(new I18NBoundMessage2P(
Messages.INVALID_INSTANCE_URN, inURN.toString(),
instanceName));
}
if (inProviderURN != null) {
validateInstanceOf(inURN, inProviderURN);
}
}
/**
* Validates that the module instance with the specified URN is
* from the provider with the specified provider URN.
*
* @param inInstanceURN the instance URN
* @param inProviderURN the provider URN
*
* @throws InvalidURNException if the module instance is not
* from the specified provider URN
*/
private static void validateInstanceOf(ModuleURN inInstanceURN,
ModuleURN inProviderURN)
throws InvalidURNException {
if(!inProviderURN.parentOf(inInstanceURN)) {
throw new InvalidURNException(new I18NBoundMessage2P(
Messages.INSTANCE_PROVIDER_URN_MISMATCH,
inInstanceURN.toString(), inProviderURN.toString()));
}
}
/**
* Expands any 'this' keywords in the requested URN,
* with corresponding elements from the requester URN,
* if a requester is supplied.
*
* @param inRequester the URN of the module requesting the data flow
* @param inURN the URN that needs to be processed
*
* @return the URI that should be used to lookup the module
*
* @throws InvalidURNException if the supplied URN is invalid
*/
static ModuleURN processURN(ModuleURN inRequester, ModuleURN inURN)
throws InvalidURNException {
verifyScheme(inURN);
//If no requester, nothing to expand in the URN, return it as is.
if(inRequester == null) {
return inURN;
}
String providerType = THIS.equals(inURN.providerType())
? inRequester.providerType()
: inURN.providerType();
String providerName = THIS.equals(inURN.providerName())
? inRequester.providerName()
: inURN.providerName();
String instanceName = THIS.equals(inURN.instanceName())
? inRequester.instanceName()
: inURN.instanceName();
if(providerType == null &&
providerName == null &&
instanceName == null) {
throw new InvalidURNException(new I18NBoundMessage1P(
Messages.INCOMPLETE_INSTANCE_URN,inURN.toString()));
}
inURN = new ModuleURN(providerType, providerName, instanceName);
return inURN;
}
/**
* Returns true if the supplied identifier is a valid identifier.
* Do note <code>this</code> is a reserved name and is not
* a valid identifier.
*
* @param inIdentifier the identifier that needs to be validated
*
* @return true if the supplied identifier is a java identifier,
* false otherwise.
*/
private static boolean isValidIdentifier(String inIdentifier) {
final char[] chars = inIdentifier.toCharArray();
for(int i = 0; i < chars.length; i++) {
if(i == 0) {
if(!Character.isJavaIdentifierStart(chars[i])) {
return false;
}
} else {
if(!Character.isJavaIdentifierPart(chars[i])) {
return false;
}
}
}
return !THIS.equals(inIdentifier);
}
/**
* This is a utility class, no instances can be created
*/
private URNUtils() {
}
}