blob: 16a9f96deb96b8553223f396f485dce56ee487f3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* 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:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.sdk.util.signature;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IPackageDeclaration;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.sdk.util.internal.SdkUtilActivator;
import org.eclipse.scout.sdk.util.type.TypeUtility;
public class ImportValidator implements IImportValidator {
private final Map<String/* simpleName */, String/* packageName */> m_initialImports;
private final Map<String/* simpleName */, String/* packageName */> m_newImports;
private final String m_packageName; // can be null
private static final Pattern EXT_REGEX = Pattern.compile("^\\+.*$");
private static final Pattern EXT_REPL_REGEX = Pattern.compile("^\\+");
private static final Pattern PLAIN_REPL_REGEX = Pattern.compile("^[\\[\\+]*");
private static final String EXT_PREFIX = "? extends ";
public ImportValidator(Map<String/* simpleName */, String/* packageName */> initialImports, String packageName) {
if (initialImports == null) {
m_initialImports = Collections.emptyMap();
}
else {
m_initialImports = Collections.unmodifiableMap(initialImports);
}
m_newImports = new HashMap<String, String>();
m_packageName = packageName;
}
public ImportValidator() {
this((String) null);
}
public ImportValidator(String packageName) {
this(new HashMap<String, String>(0), packageName);
}
public ImportValidator(ICompilationUnit icu) {
this(getUsedImportsFromIcu(icu), getPackageFromIcu(icu));
}
protected static String getPackageFromIcu(ICompilationUnit icu) {
String pck = null;
try {
IPackageDeclaration[] packageDeclarations = icu.getPackageDeclarations();
if (packageDeclarations != null && packageDeclarations.length > 0) {
pck = packageDeclarations[0].getElementName();
}
}
catch (JavaModelException e) {
SdkUtilActivator.logWarning("could not get package of compilation unit '" + icu.getElementName() + "'!", e);
}
return pck;
}
protected static Map<String, String> getUsedImportsFromIcu(ICompilationUnit icu) {
Map<String, String> usedImps = new HashMap<String, String>();
collectExistingImportsFromIcu(icu, usedImps);
collectTypesInPackage(TypeUtility.getPackage(icu), usedImps);
return usedImps;
}
protected static void collectExistingImportsFromIcu(ICompilationUnit icu, Map<String, String> usedImps) {
try {
IImportDeclaration[] imports = icu.getImports();
if (imports.length > 0) {
Map<String, String> importsFromIcu = new HashMap<String, String>(imports.length);
for (IImportDeclaration imp : imports) {
String fqImp = imp.getElementName();
String packageName = Signature.getQualifier(fqImp);
String simpleName = Signature.getSimpleName(fqImp);
importsFromIcu.put(simpleName, packageName);
}
usedImps.putAll(importsFromIcu);
}
}
catch (JavaModelException e) {
SdkUtilActivator.logWarning("could not collect imports of compilation unit '" + icu.getElementName() + "'!", e);
}
}
protected static void collectTypesInPackage(IPackageFragment pck, Map<String, String> usedImps) {
try {
for (ICompilationUnit icu : pck.getCompilationUnits()) {
for (IType t : icu.getTypes()) {
usedImps.put(t.getElementName(), pck.getElementName());
}
}
}
catch (JavaModelException e) {
SdkUtilActivator.logWarning("could not collect all used typenames in package '" + pck.getElementName() + "'!", e);
}
}
@Override
public String getTypeName(String singleTypeSignature) {
// handle primitive and void types
int kind = SignatureUtility.getTypeSignatureKind(singleTypeSignature);
if (kind == Signature.BASE_TYPE_SIGNATURE) {
return Signature.getSignatureSimpleName(singleTypeSignature);
}
// handle unresolved signatures
if (SignatureUtility.isUnresolved(singleTypeSignature)) {
return Signature.toString(singleTypeSignature);
}
StringBuilder result = new StringBuilder(singleTypeSignature.length() + EXT_PREFIX.length());
// handle extends prefix
if (EXT_REGEX.matcher(singleTypeSignature).matches()) {
result.append(EXT_PREFIX);
singleTypeSignature = EXT_REPL_REGEX.matcher(singleTypeSignature).replaceAll("");
}
// handle normal signature
String pckName = Signature.getSignatureQualifier(singleTypeSignature);
String simpleName = Signature.getSignatureSimpleName(singleTypeSignature);
String plainSimpleName = Signature.getSignatureSimpleName(PLAIN_REPL_REGEX.matcher(singleTypeSignature).replaceAll(""));
if (!StringUtility.hasText(pckName)) {
return simpleName;
}
if (isAlreadyUsed(pckName, plainSimpleName)) {
result.append(pckName).append(".");
}
else {
m_newImports.put(plainSimpleName, pckName);
}
return result.append(simpleName).toString();
}
protected String findUsedPackageName(String simpleName) {
if (m_initialImports.containsKey(simpleName)) {
return m_initialImports.get(simpleName);
}
else {
return m_newImports.get(simpleName);
}
}
protected boolean isAlreadyUsed(String packageName, String simpleName) {
String usedPackageName = findUsedPackageName(simpleName);
return usedPackageName != null && !usedPackageName.equals(packageName);
}
@Override
public void addImport(String fqn) {
String packageName = Signature.getQualifier(fqn);
String simpleName = Signature.getSimpleName(fqn);
m_newImports.put(simpleName, packageName);
}
@Override
public Set<String> getImportsToCreate() {
TreeSet<String> importsToCreate = new TreeSet<String>();
for (Entry<String, String> e : m_newImports.entrySet()) {
String pck = e.getValue();
String simpleName = e.getKey();
// don't create imports for java.lang.* classes and classes in the same package.
if (!"java.lang".equals(pck) && !pck.equals(getPackageName())) {
importsToCreate.add(pck + "." + simpleName);
}
}
return importsToCreate;
}
public String getPackageName() {
return m_packageName;
}
}