/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.sdo.helper.extension;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.logging.AbstractSessionLog;

/**
 * <p><b>Purpose</b>: Common functions in support of SDO.
 * <p><b>Responsibilities</b>:
 * <ul>
 * <li> JAXB 1.0 Name Mangling algorithm functions are provided to support generation of valid class/method names..
 * <li> JSR-222 JAXB 2.0 Java Package Name generation algorithm function follows https://jaxb.dev.java.net/spec-download.html
 * in section D.5.1 "Mapping from a Namespace URI"
 * </ul>
 */
public class SDOUtil {

    /** Valid hexadecimal digits */
    private static final String HEXADECIMAL_DIGITS = "0123456789abcdefABCDEF";
    /** Warning string to signify that the input to the package generator may not be a valid URI */
    private static final String INVALID_URI_WARNING = "SDOUtil: The URI [{0}] used for java package name generation is invalid - generating [{1}].";

    /** NCName start character class content - used to compose {@link #XML_NCNAME_VALIDATION_PATTERN}. */
    private static final String XML_NCNAME_START_CHAR_GROUP =
            "A-Z_a-z\\x{C0}-\\x{D6}\\x{D8}-\\x{F6}\\x{F8}-\\x{2FF}\\x{370}-\\x{37D}\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFFD}\\x{10000}-\\x{EFFFF}";
    /** NCName character class content - used to compose {@link #XML_NCNAME_VALIDATION_PATTERN}. */
    private static final String XML_NCNAME_CHAR_GROUP =
            "\\-.0-9\\x{B7}\\x{300}-\\x{36F}\\x{203F}-\\x{2040}";

    /**
     * Pattern for validation of XML non-colonial name (NCName).
     * @see <a href="http://www.w3.org/TR/REC-xml-names/#NT-NCName">http://www.w3.org/TR/REC-xml-names/#NT-NCName</a>
     */
    private static final Pattern XML_NCNAME_VALIDATION_PATTERN = Pattern.compile(
            "^[ " + XML_NCNAME_START_CHAR_GROUP + "][" + XML_NCNAME_START_CHAR_GROUP + XML_NCNAME_CHAR_GROUP + "]*$");

    private static final String IS = "is";
    private static final String GET = "get";
    private static final String SET = "set";

    /**
     * INTERNAL:
     * Search Java reserved name arrays and report (but don't fix) any naming collisions
     */
    private static void preProcessJavaReservedNames(String name) {
        preProcessReservedNames(name, SDOConstants.javaReservedWordsList, "sdo_type_generation_warning_class_name_violates_java_spec");
    }

    /**
     * INTERNAL:
     * Search SDO reserved name arrays and report (but don't fix) any naming collisions
     */
    private static void preProcessSDOReservedNames(String name) {
        preProcessReservedNames(name, SDOConstants.sdoInterfaceReservedWordsList, "sdo_type_generation_warning_class_name_violates_sdo_spec");
    }

    /**
     * INTERNAL:
     * Search reserved name arrays and report (but don't fix) any naming collisions
     * @param wordArray
     * @param warningLogKey
     */
    private static void preProcessReservedNames(String name, String[] wordArray, String warningLogKey) {
        // search the reserved words list and recommend alternatives
        for(int i=0; i < wordArray.length; i++) {
            if(wordArray[i].equalsIgnoreCase(name)) {
                AbstractSessionLog.getLog().log(AbstractSessionLog.WARNING, warningLogKey, //
                    new Object[] { "SDOUtil", name, wordArray[i]});
            }
        }
    }


    /** allow _ underscores in class/function names */
    private static boolean asWordSeparator = false;

    /**
     * INTERNAL:
     * Get default package name when no targetNamespace URI exists.<br>
     * This function follows the JSR-222 JAXB 2.0 algorithm from https://jaxb.dev.java.net/spec-download.html<br>
     * @return default Java package name String
     */
    public static String getDefaultPackageName() {
        return getPackageNameFromURI(SDOConstants.EMPTY_STRING);
    }

    /**
     * INTERNAL:
     * Get default package name from a namespace URI.<br>
     * This function follows the JSR-222 JAXB 2.0 algorithm from https://jaxb.dev.java.net/spec-download.html.<br>
     * @param uriString - a namespace URL or URN
     * @return Java package name String
     */
    public static String getPackageNameFromURI(String uriString) {
        String strToken;
        String prefix;
        int position = 0;
        StringBuffer pkgName = new StringBuffer();
        if (null == uriString || uriString.equals(SDOConstants.EMPTY_STRING)) {
            AbstractSessionLog.getLog().log(AbstractSessionLog.FINEST, INVALID_URI_WARNING,//
                    new Object[] { uriString, SDOConstants.JAVA_TYPEGENERATION_DEFAULT_PACKAGE_NAME }, false);
            return SDOConstants.JAVA_TYPEGENERATION_DEFAULT_PACKAGE_NAME;
        }

        /**
         * Step 1: (Remove the schema and ":" part)
         * An XML namespace is represented by a URI. Since XML Namespace will be
         *     mapped to a Java package, it is necessary to specify a default mapping from a
         *     URI to a Java package name. The URI format is described in [RFC2396].
         *     The following steps describe how to map a URI to a Java package name. The
         *     example URI, http://example.org/go/file.xsd, is used to
         *     illustrate each step.
         *     1. Remove the scheme and ":" part from the beginning of the URI, if present.
         * Since there is no formal syntax to identify the optional URI scheme, restrict
         *     the schemes to be removed to case insensitive checks for schemes
         *     "http" and "urn".
         *     //example.org/go/file.xsd
         */
        // Remove only urn: and http: schemes - retain ftp, file, gopher, mail, news, telnet
        URI uri;
        String originalUriString = uriString;
        String schemePrefix;
        // Save error state so that we can emit a warning after the URI has been processed
        boolean invalidOriginalFormat = false;
        // Save whether we are a supported urn or http scheme
    boolean invalidScheme = false;
        try {
            // Creating a URI object and catching a syntax exception may be a performance hit
            uri = new URI(uriString);
            schemePrefix = uri.getScheme();
            // Remove http or urn schemes for valid URI's
      if(null != schemePrefix){
        if((schemePrefix.equalsIgnoreCase("http") || schemePrefix.equalsIgnoreCase("urn"))) {
          uriString = uri.getSchemeSpecificPart();
        }else{
          invalidScheme = true;
        }
            }
        } catch (NullPointerException npe) {
            AbstractSessionLog.getLog().log(AbstractSessionLog.FINEST, INVALID_URI_WARNING,//
                    new Object[] { "null", SDOConstants.JAVA_TYPEGENERATION_DEFAULT_PACKAGE_NAME }, false);
            return SDOConstants.JAVA_TYPEGENERATION_DEFAULT_PACKAGE_NAME;
        } catch (URISyntaxException use) {
            // Warn that the URI is invalid, but process the string into a valid package anyway
            invalidOriginalFormat = true;
            // Remove http or urn schemes for invalid URI's
            if (uriString.length() > 4) {
                prefix = uriString.substring(0, 4);
                if (prefix.equalsIgnoreCase("urn:")) {
                    uriString = uriString.substring(4);
                } else {
                    prefix = uriString.substring(0, 5);
                    if (prefix.equalsIgnoreCase("http:")) {
                        uriString = uriString.substring(5);
                    }
                }
            }
        } finally {
            /**
             * Step 2: remove trailing file type, one of .?? or .??? or .html.
             * //example.org/go/file
             * Note: The trailing host fragment will be removed for non http|urn schemes such as file:.
             */
            int potentialPathSepIndex = uriString.lastIndexOf('/'); // Don't handle ? param separator on purpose
            int potentialHostSepIndex = uriString.indexOf('/');
            int potentialFileExtIndex = uriString.lastIndexOf('.');
            /**
             * When to remove the last .ext or trailing host fragment.
             * Valid scheme    |  has file ext    = remove/keep last {.[^.]+} fragment
             * 0 | 0 Remove host prefix            ie: file://site.com -> file.site
             * 0 | 1 Remove file ext                ie: file://site.com/file.xsd -> file.com.site
             * 1 | 0 Don't remove host prefix    ie: urn://site.com -> com.site
             * 1 | 1 Remove file ext                ie: urn://site.com/file.xsd -> com.site
             */
            // Don't Remove trailing host fragment for http|urn schemes
            if((invalidScheme && potentialFileExtIndex != -1) || //
                ((potentialFileExtIndex != -1 && potentialPathSepIndex != -1 && //
                potentialHostSepIndex != -1 && (potentialPathSepIndex - potentialHostSepIndex) > 1))) { // -1's are handled
                String extension = uriString.substring(potentialFileExtIndex);
        if (extension.length() == 3 || extension.length() == 4    || extension.equalsIgnoreCase(".html")) {
                    uriString = uriString.substring(0, potentialFileExtIndex);
                }
            }

            /**
             * Step 3: (split string into word list) 3. Parse the remaining
             * String into a list of strings using / and : as separators
             * Treat consecutive separators as a single separator.
             * {"example.org", "go", "file" }
             */
            StringTokenizer aTokenizer = new StringTokenizer(uriString, "/:");
            int length = aTokenizer.countTokens();
            if (length == 0) {
                return SDOConstants.JAVA_TYPEGENERATION_DEFAULT_PACKAGE_NAME;
            }

            /**
             * Step 4: (unescape each escape sequence octet) 4. For each string
             * in the list produced by previous step, unescape each escape
             * sequence octet. {"example.org", "go", "file" } Generating a
             * Java package name 4/19/06 JAXB 2.0 - Final Release 341
             */
            ArrayList<String> strings = new ArrayList<String>(length);
            while (aTokenizer.hasMoreTokens()) {
                strToken = aTokenizer.nextToken();
                strings.add(decodeUriHexadecimalEscapeSequence(strToken));
            }

            /**
             * Step 5: replace [-] with [.] if the scheme is a URN 5. If the
             * scheme is a urn, replace all dashes, -, occurring in the
             * first component with [.].2
             */

            /**
             * Step 6: Apply algorithm described in Section 7.7 Unique Package
             * Names in [JLS] to derive a unique package name from the
             * potential internet domain name contained within the first
             * component. The internet domain name is reversed, component by
             * component. Note that a leading www. is not considered part of
             * an internet domain name and must be dropped. If the first
             * component does not contain either one of the top-level domain
             * names, for example, com, gov, net, org, edu, or one of the
             * English two-letter codes identifying countries as specified in
             * ISO Standard 3166, 1981, this step must be skipped. {org,
             * example, go, file}
             */
            strToken = strings.remove(0).toLowerCase();
            // Reuse the Tokenizer - tokenize on package separator
            aTokenizer = new StringTokenizer(strToken, ".");
            // Check for URI's that are composed only of metacharacter package separators
            if(aTokenizer.countTokens() < 1) {
                AbstractSessionLog.getLog().log(AbstractSessionLog.FINEST, INVALID_URI_WARNING,//
                        new Object[] { uriString, SDOConstants.JAVA_TYPEGENERATION_DEFAULT_PACKAGE_NAME }, false);
                return SDOConstants.JAVA_TYPEGENERATION_DEFAULT_PACKAGE_NAME;
            } else {
                while (aTokenizer.hasMoreTokens()) {
                    strToken = aTokenizer.nextToken();
                    if (!strToken.equals("www")) {
                        strings.add(0, strToken);
                    }
                }
            }

            /**
             * Step 7: (convert each string to be all lower case) 7. For each
             * string in the list, convert each string to be all lower case.
             * {org, example, go, file }
             */
            position = 0;
            for (String aString : strings) {
                strings.set(position++, aString.toLowerCase());
            }

            /**
             * Step 8: (convert each string to a valid identifier) 8. For each
             * string remaining, the following conventions are adopted from
             * [JLS] Section 7.7, Unique Package Names. Follow step 8a-c
             * below.
             */
            position = 0;
            for (String aString : strings) {
                StringBuffer buffer = new StringBuffer();

                /**
                 * Step 8a: If the string component contains a hyphen, or any other
                 * special character not allowed in an identifier, convert it
                 * into an underscore.
                 */
                for (int j = 0; j < aString.length(); j++) {
                    char charToken = aString.charAt(j);
                    if (Character.isJavaIdentifierPart(charToken)) {
                        buffer.append(charToken);
                    } else {
                        buffer.append('_');
                    }
                }

                /**
                 * Step 8b:
                 * From the Java Language Specification section 7.7 b. If any of
                 * the resulting package name components are keywords then
                 * append underscore to them.
                 * We are not performing this step here - and are allowing all java reserved keywords to pass
                 * See the enum com.sun.tools.javac.parser.Token for a list of keywords
                 */

                /**
                 * Step 8c: If any of the resulting package name components start with
                 * a digit, or any other character that is not allowed as an
                 * initial character of an identifier, have an underscore
                 * prefixed to the component. {org, example, go, file }
                 */
                if (!Character.isJavaIdentifierStart(buffer.charAt(0))) {
                    buffer.insert(0, '_');
                }
                if (position++ != 0) {
                    buffer.insert(0, '.');
                }

                pkgName.append(buffer.toString());
            }
            if(invalidOriginalFormat) {
                AbstractSessionLog.getLog().log(AbstractSessionLog.FINEST,//
                        INVALID_URI_WARNING, new Object[] { originalUriString, pkgName }, false);
            }
        }
        return pkgName.toString();
    }

    /**
     * INTERNAL:
     * Decode Hexadecimal "%hh" escape sequences in a URI.
     * All escape codes must be valid 2 digit sequences.
     *
     * @param uri - URI component
     * @return URI component with escape sequence decoded into a
     */
    private static String decodeUriHexadecimalEscapeSequence(String uri) {
        // This function is used by the Java Package Name generation algorithm that implements JAXB 2.0 D.5.1
        StringBuffer sb = new StringBuffer(uri.length());
        for (int index = 0; index < uri.length(); index++) {
            char c = uri.charAt(index);
            // Escape sequence found - get the hex value and convert
            if (c == '%') {
                if (((index + 2) < uri.length()) && //
                    HEXADECIMAL_DIGITS.indexOf(uri.charAt(index + 1)) >= 0 &&//
                    HEXADECIMAL_DIGITS.indexOf(uri.charAt(index + 2)) >= 0) {
                    // Look ahead 2 digits
                    String g = uri.substring(index + 1, index + 3);
                    // Convert base 16 to base 10 to char and append
                    sb.append((char)Integer.parseInt(g, 16));
                    /**
                     * Increase the index by 2 - so we skip the 2 digit hex code after the %
                     * See JAXB 2.0 spec p.348 section D.5.1.4
                     * "For each string in the list produced by step 3.  Unescape each escape sequence octet.
                     * IE: North%20America should be "North America" and later in step 8
                     * "north_america" not "north_20america"
                     */
                    index+=2;
                } else {
                    sb.append(c);
                }
            } else {
                sb.append(c);
            }
        }
        return (sb.toString());
    }


    /**
     * INTERNAL:
     * Return a valid Java class name or method name for a given string
     * @param s
     * @param isClass (flag whether called from a method context)
     * @return
     */
    public static String className(String s, boolean isClass) {
        return className(s, true, isClass, true);
    }

    /**
     * INTERNAL:
     * Return a valid Java class name or method name for a given string
     * @param s
     * @param isClass (flag whether called from a method context)
     * @param flag
     * @return
     */
    public static String className(String s, boolean flag, boolean isClass, boolean logOn) {
        // 1) warn if the class conflicts with any Java reserved words
        preProcessJavaReservedNames(s);
        // 2) warn if the class conflicts with any SDO reserved words
        preProcessSDOReservedNames(s);

        String[] as = getWordList(s);
        StringBuffer stringbuffer = new StringBuffer();
        StringBuffer stringbuffer1 = new StringBuffer();
        if (as.length == 0) {
            return stringbuffer.toString();
        }

        for (int i = 0; i < as.length; i++) {
            char[] ac = as[i].toCharArray();
            if (Character.isLowerCase(ac[0])) {
                ac[0] = Character.toUpperCase(ac[0]);
            }
            for (int j = 0; j < ac.length; j++) {
                if ((ac[j] >= ' ') && (ac[j] < '\177')) {
                    if ((ac[j] != '_') || !asWordSeparator) {
                        stringbuffer.append(ac[j]);
                    }
                    continue;
                }
                if (flag) {
                    stringbuffer.append(escapeUnicode(stringbuffer1, ac[j]));
                } else {
                    stringbuffer.append(ac[j]);
                }
            }
        }

        String normalizedName = stringbuffer.toString();
        // report a warning whether we were required to normalize the name (beyond initial capitalization)
        if(!s.equals(normalizedName) && logOn) {
            // log changes
            int logLevel;
            // log capitalization-only changes at a lower level
            if(!s.equalsIgnoreCase(normalizedName)) {
                logLevel = AbstractSessionLog.INFO;
            } else {
                logLevel = AbstractSessionLog.FINER;
            }

            // report differently depending on whether the input was a class or function name
            if(isClass) {
                AbstractSessionLog.getLog().log(logLevel, //
                    "sdo_type_generation_modified_class_naming_format_to",
                    new Object[] { "SDOUtil", s, normalizedName});
            } else {
                AbstractSessionLog.getLog().log(logLevel, //
                        "sdo_type_generation_modified_function_naming_format_to",
                        new Object[] { "SDOUtil", s, normalizedName});
            }
        }

        return normalizedName;
    }

    /**
     * INTERNAL:
     * Return a valid Java method name for a given string
     * @param s
     * @return
     */
    public static String methodName(String s) {
        return methodName(s, true);
    }

    /**
     * INTERNAL:
     * Return a valid Java method name for a given string
     * @param s
     * @param flag
     * @return
     */
    public static String methodName(String s, boolean flag) {
        return className(s, flag, false, true);
    }

    /**
     * INTERNAL:
     * Return a valid Java set method name for a given string
     * @param s
     * @return
     */
    public static String setMethodName(String s) {
        StringBuffer stringbuffer = new StringBuffer();
        stringbuffer.append(SET).append(methodName(s));
        return stringbuffer.toString();
    }

    /**
     * INTERNAL:
     * Return a valid Java get method name for a given string. This method will check
     * the returnType to see if it is a boolean/Boolean:  if so, 'is' will be used in
     * the method name instead of 'get'.
     *
     * @param s
     * @param returnType
     * @return
     */
    public static String getMethodName(String s, String returnType) {
        StringBuffer stringBuffer = new StringBuffer();
        if (returnType.equals(ClassConstants.PBOOLEAN.getName()) || returnType.equals(ClassConstants.BOOLEAN.getName())) {
            stringBuffer.append(IS);
        } else {
            stringBuffer.append(GET);
        }
        stringBuffer.append(SDOUtil.className(s, true, false, false));
        return stringBuffer.toString();
    }

    /**
     * INTERNAL:
     * Return a valid Java get method name for a given string. This method will NOT check
     * the returnType to see if it is a boolean/Boolean and all method names will start with
     * "GET"
     *
     * @param s
     * @param returnType
     * @return
     */
    public static String getBooleanGetMethodName(String s, String returnType){
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(SDOUtil.GET);
        stringBuffer.append(SDOUtil.className(s, true, false, false));
        return stringBuffer.toString();
    }

    /**
     * INTERNAL:
     * @param s
     * @return
     */
    public static String constantName(String s) {
        StringBuffer stringbuffer = new StringBuffer();
        String[] as = getWordList(s);
        if (as.length > 0) {
            stringbuffer.append(as[0].toUpperCase());
            for (int i = 1; i < as.length; i++) {
                stringbuffer.append('_');
                stringbuffer.append(as[i].toUpperCase());
            }
        }
        return stringbuffer.toString();
    }

    /**
     *
     * @param s
     * @return
     */
    private static String[] getWordList(String s) {
        java.util.List arraylist = new ArrayList();
        int i = s.length();
        int j = 0;
        do {
            if (j >= i) {
                break;
            }
            for (; (j < i) && isPunct(s.charAt(j)); j++) {
            }
            if (j >= i) {
                break;
            }
            int k = nextBreak(s, j);
            String s1 = (k != -1) ? s.substring(j, k) : s.substring(j);
            arraylist.add(escape(s1));
            if (k == -1) {
                break;
            }
            j = k;
        } while (true);
        return (String[])arraylist.toArray(new String[0]);
    }

    private static boolean isPunct(char c) {
        if ((c == '-') || (c == '.') || (c == ':') || (c == '\267') || (c == '\u0387') || (c == '\u06DD') || (c == '\u06DE')) {
            return true;
        }
        return (c == '_') && asWordSeparator;
    }

    private static boolean isUncased(char c) {
        return Character.isLetter(c) && !Character.isUpperCase(c) && !Character.isLowerCase(c);
    }

    private static int nextBreak(String s, int i) {
        int j = s.length();
        for (int k = i; k < j; k++) {
            char c = s.charAt(k);
            if (((c == '_') && !asWordSeparator) || (k >= (j - 1))) {
                continue;
            }
            char c1 = s.charAt(k + 1);
            if ((c1 == '_') && !asWordSeparator) {
                continue;
            }
            if (isPunct(c1)) {
                return k + 1;
            }
            if (Character.isDigit(c) && !Character.isDigit(c1)) {
                return k + 1;
            }
            if (!Character.isDigit(c) && Character.isDigit(c1)) {
                return k + 1;
            }
            if (Character.isLowerCase(c) && !Character.isLowerCase(c1)) {
                return k + 1;
            }
            if (k < (j - 2)) {
                char c2 = s.charAt(k + 2);
                if ((c2 == '_') && !asWordSeparator) {
                    continue;
                }
                if (Character.isUpperCase(c) && Character.isUpperCase(c1) && Character.isLowerCase(c2)) {
                    return k + 1;
                }
            }
            if (Character.isLetter(c) && !Character.isLetter(c1)) {
                return k + 1;
            }
            if (!Character.isLetter(c) && Character.isLetter(c1)) {
                return k + 1;
            }
            if (isUncased(c) && !isUncased(c1)) {
                return k + 1;
            }
            if (!isUncased(c) && isUncased(c1)) {
                return k + 1;
            }
        }
        return -1;
    }

    private static String escape(String s) {
        int i = s.length();
        for (int j = 0; j < i; j++) {
            if (!Character.isJavaIdentifierPart(s.charAt(j))) {
                StringBuffer stringbuffer = new StringBuffer(s.substring(0, j));
                escape(stringbuffer, s, j);
                return stringbuffer.toString();
            }
        }
        return s;
    }

    private static void escape(StringBuffer stringbuffer, String s, int i) {
        int j = s.length();
        for (int k = i; k < j; k++) {
            char c = s.charAt(k);
            if (Character.isJavaIdentifierPart(c)) {
                stringbuffer.append(c);
                continue;
            }
            stringbuffer.append("_");
            if (c <= '\017') {
                stringbuffer.append("000");
            } else if (c <= '\377') {
                stringbuffer.append("00");
            } else if (c <= '\u0FFF') {
                stringbuffer.append("0");
            }
            stringbuffer.append(Integer.toString(c, 16));
        }
    }

    private static String escapeUnicode(StringBuffer stringbuffer, char c) {
        String s = Integer.toString(c, 16);
        int i = s.length();
        stringbuffer.setLength(6);
        stringbuffer.setCharAt(0, '\\');
        stringbuffer.setCharAt(1, 'u');
        int j = 2;
        for (int k = i; k < 4;) {
            stringbuffer.setCharAt(j, '0');
            k++;
            j++;
        }

        stringbuffer.replace(j, 6, s);
        return stringbuffer.toString();
    }

    public static String getJavaTypeForProperty(SDOProperty property) {
        if (property.isMany() || property.getType().isXsdList()) {
            return "java.util.List";
        } else {
            SDOType propertyType = property.getType();
            if(propertyType.isDataType()) {
                Class<?> instanceClass = propertyType.getInstanceClass();
                if (ClassConstants.ABYTE.equals(instanceClass)) {
                    return "Byte[]";
                } else if (ClassConstants.APBYTE.equals(instanceClass)) {
                    return "byte[]";
                }
            }
            return propertyType.getInstanceClassName();
        }
    }

    public static String getBuiltInType(String typeName) {
        if ((typeName.equals(ClassConstants.PBOOLEAN.getName())) || (typeName.equals(ClassConstants.BOOLEAN.getName()))) {
            return "Boolean";
        } else if ((typeName.equals(ClassConstants.PBYTE.getName())) || (typeName.equals(ClassConstants.BYTE.getName()))) {
            return "Byte";
        } else if (typeName.equals("byte[]") || typeName.equals("Byte[]") ||  (typeName.equals(ClassConstants.APBYTE.getName())) || (typeName.equals(ClassConstants.ABYTE.getName()))) {
            return "Bytes";
        } else if ((typeName.equals(ClassConstants.PCHAR.getName())) || (typeName.equals(ClassConstants.CHAR.getName()))) {
            return "Char";
        } else if ((typeName.equals(ClassConstants.PDOUBLE.getName())) || (typeName.equals(ClassConstants.DOUBLE.getName()))) {
            return "Double";
        } else if ((typeName.equals(ClassConstants.PFLOAT.getName())) || (typeName.equals(ClassConstants.FLOAT.getName()))) {
            return "Float";
        } else if ((typeName.equals(ClassConstants.PLONG.getName())) || (typeName.equals(ClassConstants.LONG.getName()))) {
            return "Long";
        } else if ((typeName.equals(ClassConstants.PSHORT.getName())) || (typeName.equals(ClassConstants.SHORT.getName()))) {
            return "Short";
        } else if ((typeName.equals(ClassConstants.PINT.getName())) || (typeName.equals(ClassConstants.INTEGER.getName()))) {
            return "Int";
        } else if (typeName.equals(ClassConstants.STRING.getName())) {
            return "String";
        } else if (typeName.equals(ClassConstants.BIGINTEGER.getName())) {
            return "BigInteger";
        } else if (typeName.equals(ClassConstants.BIGDECIMAL.getName())) {
            return "BigDecimal";
        } else if (typeName.equals(ClassConstants.UTILDATE.getName())) {
            return "Date";
        } else if (typeName.equals("java.util.List")) {
            return "List";
        }
        return null;
    }

    /**
     * INTERNAL:
     * Validates whether given string is a valid XML non-colonial name (NCName).
     * @param name string
     * @return {@code true} given string is a valid NCName
     * @see <a href="http://www.w3.org/TR/REC-xml-names/#NT-NCName">http://www.w3.org/TR/REC-xml-names/#NT-NCName</a>
     */
    public static boolean isValidXmlNCName(String name) {
        return XML_NCNAME_VALIDATION_PATTERN.matcher(name).matches();
    }
}
