/*******************************************************************************
* Copyright (c) 2005, 2007 committers of openArchitectureWare and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* committers of openArchitectureWare - initial API and implementation
*******************************************************************************/
package org.eclipse.xtend.expression;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.internal.xtend.expression.parser.SyntaxConstants;
/**
* Utility class for retrieving information from various type name presentations
* used within Xtend's type system.
* <p>
* The following type formats can occur:
* <ul>
* <li> <code><typename></code>
* <li> <code><collectionTypeName>[<typename>]</code>
* <li>
* <code><collectionTypeName>[<metamodelname>!<typename>]</code>
* </ul>
* Examples:
* <ul>
* <li> <code>entities::Account</code>
* <li> <code>List[entities::Account]</code>
* </ul>
* <p>'<code><typename></code>' is the fully qualified name
* <code>namespace1::namespace2::name</code>
*
* @author Sven Efftinge (http://www.efftinge.de) - Initial implementation
* @author Arno Haase - Initial implementation
* @author Karsten Thoms - Documentation
* @since 4.0
*/
public class TypeNameUtil {
private static final String QUALIFIEDNAME_STRING = "(?:[^\\s.:()\\[\\]{}+\\-*/&|%$!\\\"\'=?]+::)*[^\\s.:()\\[\\]{}+\\-*/&|%!\"'=?]+";
/**
* This pattern is used to find the type name within possible query strings
*/
final static Pattern TYPE_PATTERN = Pattern.compile("\\A(?:(\\w+)\\[)?(?:(\\w+)!)?(" + QUALIFIEDNAME_STRING
+ ")(?:\\])?\\z");
final static Pattern GENERICLIST_PATTERN = Pattern.compile("\\A\\[L(" + QUALIFIEDNAME_STRING + ");");
/**
* Retrieves the collection type.
*
* @param name
* Qualified type string
* @return The name of the collection type if present ('List', 'Set'),
* otherwise <code>null</code>
*/
public static String getCollectionTypeName(final String name) {
String group = getGroup(name, TYPE_PATTERN, 1);
if (group == null) {
if (GENERICLIST_PATTERN.matcher(name).matches()) {
group = "List";
}
}
return group;
}
/**
* Retrieves the type name
*
* @param name
* Qualified type string
* @return The type's name
*/
public static String getTypeName(final String name) {
String group = getGroup(name, TYPE_PATTERN, 3);
if (group == null) {
group = getGroup(name, GENERICLIST_PATTERN, 1);
}
if (group == null) {
group = "";
}
return group;
}
private static String getGroup(final String input, final Pattern pattern, final int group) {
final Matcher m = pattern.matcher(input);
if (m.matches() && m.groupCount() >= group)
return m.group(group);
return null;
}
/**
* Gets the internal representation of a class name.
*
* @param class1
* A class instance for which the name should be retrieved
* @return Xtend's classname representation (
* <code>package1::package2::TheClassname</code>)
*/
public static String getName(final Class<?> class1) {
return class1.getName().replaceAll("\\.", SyntaxConstants.NS_DELIM);
}
/**
* Cuts the last segment from a qualified type name.
*
* @param fqn
* Qualified type name
* @return <pre>
* ns1::ns2::name -> ns1::ns2
* name -> <null>
* </pre>
*/
public static String withoutLastSegment(final String fqn) {
if (fqn.lastIndexOf(SyntaxConstants.NS_DELIM) == -1)
return null;
return fqn.substring(0, fqn.lastIndexOf(SyntaxConstants.NS_DELIM));
}
/**
* Retrieves only the last segment of a qualified name and therefore cuts
* the namespace part
*
* @param fqn
* Qualified type name
* @return <pre>
* ns1::ns2::name -> name
* name -> name
* </pre>
*/
public static String getLastSegment(final String fqn) {
if (fqn.lastIndexOf(SyntaxConstants.NS_DELIM) == -1)
return fqn;
return fqn.substring(fqn.lastIndexOf(SyntaxConstants.NS_DELIM) + SyntaxConstants.NS_DELIM.length());
}
/**
* Cuts the namespace qualification from the type string.
*
* @param fqn
* Qualified type string
* @return <pre>
* ns1::ns2::type -> type
* List[type] -> List[type]
* List[Metamodel!ns1::type] -> List[Metamodel!type]
* </pre>
*/
public static String getSimpleName(final String fqn) {
final String ct = getCollectionTypeName(fqn);
final String inner = getLastSegment(getTypeName(fqn));
final StringBuffer sb = new StringBuffer();
if (ct != null) {
sb.append(ct).append("[");
}
sb.append(inner);
if (ct != null) {
sb.append("]");
}
return sb.toString();
}
public static String getPackage(final String insertString) {
if (insertString == null || insertString.trim().length() == 0)
return null;
final int index = insertString.lastIndexOf(SyntaxConstants.NS_DELIM);
if (index != -1)
return insertString.substring(0, index);
return null;
}
/**
* Converts a Java qualified name (dot seperated) to Xtend qualified name
* ('::' seperated)
*
* @param javaTypeName
* A java qualifier
* @return All dots are replaced by '::'. Returns <code>null</code> if
* <tt>javaTypeName</tt> is null.
* @since 4.3.1
*/
public static String convertJavaTypeName(final String javaTypeName) {
if (javaTypeName == null)
return null;
else
return javaTypeName.replaceAll("\\.", SyntaxConstants.NS_DELIM);
}
}