Issue #369: Move isTypeName and isFeatureName to public API
- Moved the two methods to the public TypeSystemUtil class
- Deprecate them in the old place and mark them for removal in next major version
diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemUtils.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemUtils.java
index 35070e2..bde4ade 100644
--- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemUtils.java
+++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemUtils.java
@@ -21,10 +21,10 @@
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
-import java.util.StringTokenizer;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
+import org.apache.uima.util.TypeSystemUtil;
/**
* Type Utilities - all static, so class is abstract to prevent creation Used by Feature Path
@@ -233,40 +233,43 @@
public void setErrorPosition(int errorPosition) {
this.errorPosition = errorPosition;
}
-
}
+ /**
+ * @deprecated Use {@link TypeSystemUtil#isFeatureName} instead
+ */
+ @SuppressWarnings("javadoc")
+ @Deprecated
public static boolean isIdentifier(String s) {
- if (s == null) {
- return false;
- }
- final int len = s.length();
- if (len == 0) {
- return false;
- }
- int pos = 0;
- // Check that the first character is a letter.
- if (!isIdentifierStart(s.charAt(pos))) {
- return false;
- }
- ++pos;
- while (pos < len) {
- if (!isIdentifierChar(s.charAt(pos))) {
- return false;
- }
- ++pos;
- }
- return true;
+ return TypeSystemUtil.isFeatureName(s);
}
+ /**
+ * @deprecated To be removed without replacement.
+ * @forRemoval 4.0.0
+ */
+ @SuppressWarnings("javadoc")
+ @Deprecated
static boolean isNonQualifiedName(String s) {
return isIdentifier(s);
}
+ /**
+ * @deprecated To be removed without replacement.
+ * @forRemoval 4.0.0
+ */
+ @SuppressWarnings("javadoc")
+ @Deprecated
static boolean isIdentifierStart(char c) {
return Character.isLetter(c);
}
+ /**
+ * @deprecated To be removed without replacement.
+ * @forRemoval 4.0.0
+ */
+ @SuppressWarnings("javadoc")
+ @Deprecated
static boolean isIdentifierChar(char c) {
return (Character.isLetter(c) || Character.isDigit(c) || (c == '_'));
}
@@ -280,28 +283,12 @@
* @param name
* The name to check.
* @return <code>true</code> iff <code>name</code> is a possible type name.
+ * @deprecated Use {@link TypeSystemUtil#isTypeName(String)} instead
+ * @forRemoval 4.0.0
*/
+ @Deprecated
static boolean isTypeName(String name) {
- // Create a string tokenizer that will split the string at the name
- // space
- // boundaries. We need to see the delimiters to make sure there are no
- // gratuitous delimiters at the beginning or the end.
- StringTokenizer tok = new StringTokenizer(name, NAMESPACE_SEPARATOR_AS_STRING, true);
- // Loop over the tokens and check that every item is an identifier.
- while (tok.hasMoreTokens()) {
- // Any subsequence must start with an identifier.
- if (!isIdentifier(tok.nextToken())) {
- return false;
- }
- // If there is a next token, it must be a separator.
- if (tok.hasMoreTokens()) {
- // A sequence can not end in a separator.
- if (!tok.nextToken().equals(NAMESPACE_SEPARATOR_AS_STRING) || !tok.hasMoreTokens()) {
- return false;
- }
- }
- }
- return true;
+ return TypeSystemUtil.isTypeName(name);
}
static boolean isTypeNameSpaceName(String name) {
@@ -357,16 +344,17 @@
if (path.isEmpty()) {
return status;
}
+
// Pop the next feature name from the stack and check if it's defined for the current type.
- String featName = path.pop();
- FeatureImpl fi = type.getFeatureByBaseName(featName);
+ var featName = path.pop();
+ var fi = type.getFeatureByBaseName(featName);
if (fi != null) {
// If feature is defined, we can continue directly.
return isPathValid(fi.getRangeImpl(), path, status);
}
+
// If feature is not defined for type, check to see if there are any subtypes for which the
// path is defined (possible).
-
return isPathValidInSubtypes(type, featName, path);
}
@@ -399,9 +387,8 @@
for (TypeImpl subtype : type.getDirectSubtypes()) {
FeatureImpl fi = subtype.getFeatureByBaseName(fName);
if (fi != null) {
- if (PathValid.POSSIBLE == isPathValid(fi.getRangeImpl(), nextPath, PathValid.POSSIBLE)) { // check
- // subsequent
- // types.
+ // check subsequent types.
+ if (PathValid.POSSIBLE == isPathValid(fi.getRangeImpl(), nextPath, PathValid.POSSIBLE)) {
return PathValid.POSSIBLE;
} else {
continue; // try another subtype
diff --git a/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java b/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java
index 59b9d84..5c05044 100644
--- a/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java
+++ b/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java
@@ -24,6 +24,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.StringTokenizer;
import org.apache.uima.ResourceSpecifierFactory;
import org.apache.uima.UIMAFramework;
@@ -42,6 +43,8 @@
public class TypeSystemUtil {
+ private static final String NAMESPACE_SEPARATOR_AS_STRING = "" + TypeSystem.NAMESPACE_SEPARATOR;
+
/**
* Loads type system descriptions and resolves their imports. For example when you place a
* {@link TypeSystemDescriptionProvider} implementation and place the type system descriptions it
@@ -206,4 +209,74 @@
return lts.ll_getStringSet(lts.ll_getCodeForType(aType));
}
+ /**
+ * @return if the given {@code name} is a valid feature name. Does not check if the feature
+ * actually exists!
+ * @param name
+ * The name to check.
+ */
+ public static boolean isFeatureName(String name) {
+
+ return isIdentifier(name);
+ }
+
+ /**
+ * Check if {@code name} is a possible type name. Does not check if this type actually exists!
+ *
+ * @param name
+ * The name to check.
+ * @return <code>true</code> iff <code>name</code> is a possible type name.
+ */
+ public static boolean isTypeName(String name) {
+ // Create a string tokenizer that will split the string at the name space
+ // boundaries. We need to see the delimiters to make sure there are no
+ // gratuitous delimiters at the beginning or the end.
+ var tok = new StringTokenizer(name, NAMESPACE_SEPARATOR_AS_STRING, true);
+ // Loop over the tokens and check that every item is an identifier.
+ while (tok.hasMoreTokens()) {
+ // Any subsequence must start with an identifier.
+ if (!isIdentifier(tok.nextToken())) {
+ return false;
+ }
+ // If there is a next token, it must be a separator.
+ if (tok.hasMoreTokens()) {
+ // A sequence can not end in a separator.
+ if (!tok.nextToken().equals(NAMESPACE_SEPARATOR_AS_STRING) || !tok.hasMoreTokens()) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static boolean isIdentifier(String s) {
+ if (s == null) {
+ return false;
+ }
+ final int len = s.length();
+ if (len == 0) {
+ return false;
+ }
+ int pos = 0;
+ // Check that the first character is a letter.
+ if (!isIdentifierStart(s.charAt(pos))) {
+ return false;
+ }
+ ++pos;
+ while (pos < len) {
+ if (!isIdentifierChar(s.charAt(pos))) {
+ return false;
+ }
+ ++pos;
+ }
+ return true;
+ }
+
+ private static boolean isIdentifierStart(char c) {
+ return Character.isLetter(c);
+ }
+
+ private static boolean isIdentifierChar(char c) {
+ return (Character.isLetter(c) || Character.isDigit(c) || (c == '_'));
+ }
}