/*******************************************************************************
* Copyright (c) 2006-2014
* Software Technology Group, Dresden University of Technology
* DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026
*
* 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:
* Software Technology Group - TU Dresden, Germany;
* DevBoost GmbH - Berlin, Germany
* - initial API and implementation
******************************************************************************/
package org.emftext.language.java.extensions.classifiers;
import java.util.List;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.emftext.language.java.JavaUniquePathConstructor;
import org.emftext.language.java.classifiers.Classifier;
import org.emftext.language.java.classifiers.ConcreteClassifier;
import org.emftext.language.java.classifiers.Interface;
import org.emftext.language.java.commons.Commentable;
import org.emftext.language.java.containers.CompilationUnit;
import org.emftext.language.java.members.Member;
import org.emftext.language.java.modifiers.AnnotableAndModifiable;
import org.emftext.language.java.types.ClassifierReference;
import org.emftext.language.java.types.TypeReference;
import org.emftext.language.java.util.UniqueEList;
public class ConcreteClassifierExtension {
public static EList<ConcreteClassifier> getAllInnerClassifiers(ConcreteClassifier me) {
EList<ConcreteClassifier> innerClassifierList = new UniqueEList<ConcreteClassifier>();
innerClassifierList.addAll(me.getInnerClassifiers());
for (ConcreteClassifier superClassifier : me.getAllSuperClassifiers()) {
List<ConcreteClassifier> superInnerList = superClassifier
.getInnerClassifiers();
for (ConcreteClassifier superInner : superInnerList) {
if (superInner.eIsProxy()) {
EObject resolved = EcoreUtil.resolve(superInner, me);
superInner = (ConcreteClassifier) resolved;
}
boolean isVisible = !superInner.isHidden(me);
if (isVisible) {
innerClassifierList.add(superInner);
}
}
}
return innerClassifierList;
}
public static EList<ConcreteClassifier> getInnerClassifiers(ConcreteClassifier me) {
if (me.eIsProxy()) {
String uriString = ((InternalEObject) me).eProxyURI().trimFragment().toString();
String fullName = uriString.substring(JavaUniquePathConstructor.JAVA_CLASSIFIER_PATHMAP.length(),
uriString.length() - ".java".length()) + "$";
return me.getConcreteClassifierProxies(fullName, "*");
} else {
String suffix = "";
ConcreteClassifier containingClass = me;
while (containingClass.eContainer() instanceof ConcreteClassifier) {
containingClass = (ConcreteClassifier) containingClass.eContainer();
suffix = containingClass.getName() + JavaUniquePathConstructor.CLASSIFIER_SEPARATOR + suffix;
}
if (containingClass.eContainer() instanceof CompilationUnit) {
CompilationUnit compilationUnit = (CompilationUnit) containingClass.eContainer();
String fullName = compilationUnit.getNamespacesAsString() + suffix +
me.getName() + JavaUniquePathConstructor.CLASSIFIER_SEPARATOR;
return me.getConcreteClassifierProxies(fullName, "*");
}
}
// For classes declared locally inside methods that are not registered
// in the class path
EList<ConcreteClassifier> result = new UniqueEList<ConcreteClassifier>();
// Can not call ClassifierUtil.getAllMembers, because it will try to
// call this method!
for (Member member : me.getMembers()) {
if (member instanceof ConcreteClassifier) {
result.add((ConcreteClassifier) member);
}
}
for (ConcreteClassifier superClassifier : me.getAllSuperClassifiers()) {
for (Member member : superClassifier.getMembers()) {
if (member instanceof ConcreteClassifier) {
result.add((ConcreteClassifier) member);
}
}
}
return result;
}
public static EList<ClassifierReference> getSuperTypeReferences(ConcreteClassifier me) {
EList<ClassifierReference> typeReferenceList = new UniqueEList<ClassifierReference>();
if (me instanceof org.emftext.language.java.classifiers.Class) {
org.emftext.language.java.classifiers.Class javaClass = (org.emftext.language.java.classifiers.Class) me;
// Add super type of class to super type list
TypeReference superClass = javaClass.getExtends();
if (superClass != null) {
ClassifierReference classifierReference = superClass.getPureClassifierReference();
typeReferenceList.add(classifierReference);
Classifier target = classifierReference.getTarget();
ConcreteClassifier concreteTarget = (ConcreteClassifier) target;
if (!me.isJavaLangObject(concreteTarget)) {
typeReferenceList.addAll(concreteTarget.getSuperTypeReferences());
}
}
// Add all implemented interfaces to super type list
addSuperTypes(javaClass.getImplements(), typeReferenceList);
} else if (me instanceof Interface) {
Interface javaInterface = (Interface) me;
// Add all super interfaces to super type list
addSuperTypes(javaInterface.getExtends(), typeReferenceList);
}
return typeReferenceList;
}
private static void addSuperTypes(List<TypeReference> typeReferences,
List<ClassifierReference> superTypeReferences) {
for (TypeReference interfaceReference : typeReferences) {
addSuperType(interfaceReference, superTypeReferences);
}
}
private static void addSuperType(TypeReference typeReference,
List<ClassifierReference> superTypeReferences) {
ClassifierReference classifierReference = typeReference.getPureClassifierReference();
superTypeReferences.add(classifierReference);
Classifier target = classifierReference.getTarget();
ConcreteClassifier concreteTarget = (ConcreteClassifier) target;
superTypeReferences.addAll(concreteTarget.getSuperTypeReferences());
}
/**
* Returns all members of the given classifier including inner classes and
* all members of super types (extended classes and implemented interfaces).
*
* @param context to check protected visibility
* @return member list
*/
public static EList<Member> getAllMembers(ConcreteClassifier me, Commentable context) {
EList<Member> memberList = new UniqueEList<Member>();
ConcreteClassifier concreteClassifier = (ConcreteClassifier) me;
memberList.addAll(concreteClassifier.getMembers());
memberList.addAll(concreteClassifier.getDefaultMembers());
// Because inner classes are found in separate class files
memberList.addAll(concreteClassifier.getAllInnerClassifiers());
for (ConcreteClassifier superClassifier : me.getAllSuperClassifiers()) {
for (Member member : superClassifier.getMembers()) {
if (member instanceof AnnotableAndModifiable) {
AnnotableAndModifiable modifiable = (AnnotableAndModifiable) member;
boolean isVisible = !modifiable.isHidden(context);
if (isVisible) {
memberList.add(member);
}
} else {
memberList.add(member);
}
}
memberList.addAll(superClassifier.getDefaultMembers());
}
return memberList;
}
/**
* Returns the qualified name of this concrete classifier.
*/
public static String getQualifiedName(ConcreteClassifier me) {
StringBuilder qualifiedName = new StringBuilder();
List<String> packageParts = me.getContainingPackageName();
for (String packagePart : packageParts) {
qualifiedName.append(packagePart);
qualifiedName.append(".");
}
qualifiedName.append(me.getName());
return qualifiedName.toString();
}
/**
* Returns <code>true</code> if the given {@link ConcreteClassifier} is
* <code>java.lang.Object</code>. Attention: This method does not take the
* {@link ConcreteClassifier} on which the method is called (<code>me</code>
* ) as argument as this is not used in the methods implementation.
*
* @param clazz
* the class to check
* @return <code>true</code> if <code>clazz</code> represents
* <code>java.lang.Object</code>, otherwise <code>false</code>
*/
public static boolean isJavaLangObject(ConcreteClassifier clazz) {
String name = clazz.getName();
if (!"Object".equals(name)) {
return false;
}
List<String> packageName = clazz.getContainingPackageName();
if (packageName.size() != 2) {
return false;
}
if (!("java".equals(packageName.get(0)))) {
return false;
}
if (!("lang".equals(packageName.get(1)))) {
return false;
}
return true;
}
}