/*******************************************************************************
* 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.commons;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.ECollections;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.emftext.commons.layout.LayoutInformation;
import org.emftext.language.java.JavaClasspath;
import org.emftext.language.java.annotations.AnnotationInstance;
import org.emftext.language.java.classifiers.AnonymousClass;
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.modifiers.AnnotableAndModifiable;
import org.emftext.language.java.modifiers.AnnotationInstanceOrModifier;
import org.emftext.language.java.statements.Statement;
import org.emftext.language.java.statements.StatementListContainer;
import org.emftext.language.java.util.UniqueEList;
public class CommentableExtension {
/**
* Adds the given statement before the statement that contains this element.
*/
public static void addBeforeContainingStatement(Commentable me, Statement statementToAdd) {
EObject container = me.eContainer();
EObject statement = me;
while (container != null) {
if (container instanceof StatementListContainer) {
break;
}
container = container.eContainer();
statement = statement.eContainer();
}
if (container == null) {
throw new IllegalArgumentException("Element " + me + " is not contained in a StatementListContainer.");
}
StatementListContainer statementListContainer = (StatementListContainer) container;
EList<Statement> statements = statementListContainer.getStatements();
int index = statements.indexOf(statement);
statements.add(index, statementToAdd);
}
/**
* Adds the given statement after the statement that contains this element.
*/
public static void addAfterContainingStatement(Commentable me, Statement statementToAdd) {
EObject container = me.eContainer();
EObject statement = me;
while (container != null) {
if (container instanceof StatementListContainer) {
break;
}
container = container.eContainer();
statement = statement.eContainer();
}
if (container == null) {
throw new IllegalArgumentException("Element " + me + " is not contained in a StatementListContainer.");
}
StatementListContainer statementListContainer = (StatementListContainer) container;
EList<Statement> statements = statementListContainer.getStatements();
int index = statements.indexOf(statement);
if (index == statements.size() - 1) {
// statement is the last one
statements.add(statementToAdd);
} else {
statements.add(index + 1, statementToAdd);
}
}
/**
* Walks up the containment hierarchy and returns the first parent with the
* given type. If no such parent is found, null is returned.
*/
public static EObject getParentByEType(Commentable me, EClass type) {
EObject container = me.eContainer();
while (container != null) {
if (type.isInstance(container)) {
return container;
}
container = container.eContainer();
}
return null;
}
/**
* Walks up the containment hierarchy and returns the first parent with the
* given type. If no such parent is found, null is returned.
*/
public static <T> T getParentByType(Commentable me, Class<T> type) {
EObject container = me.eContainer();
while (container != null) {
if (type.isInstance(container)) {
return type.cast(container);
}
container = container.eContainer();
}
return null;
}
/**
* Searches for the first child with the given type. If no such child is
* found, <code>null</code> is returned.
*/
public static EObject getFirstChildByEType(Commentable me, EClass type) {
Iterator<EObject> it = me.eAllContents();
while (it.hasNext()) {
EObject next = it.next();
if (type.isInstance(next)) {
return next;
}
}
return null;
}
/**
* Searches for the first child with the given type. If no such child is
* found, <code>null</code> is returned.
*/
public static <T> T getFirstChildByType(Commentable me, Class<T> type) {
Iterator<EObject> it = me.eAllContents();
while (it.hasNext()) {
EObject next = it.next();
if (type.isInstance(next)) {
return type.cast(next);
}
}
return null;
}
/**
* Returns all children of the given type.
*/
public static EList<EObject> getChildrenByEType(Commentable me, EClass type) {
EList<EObject> children = new BasicEList<EObject>();
Iterator<EObject> it = me.eAllContents();
while (it.hasNext()) {
EObject next = it.next();
if (type.isInstance(next)) {
children.add(next);
}
}
return children;
}
/**
* Returns all children of the given type.
*/
public static <T> EList<T> getChildrenByType(Commentable me, Class<T> type) {
EList<T> children = new BasicEList<T>();
Iterator<EObject> it = me.eAllContents();
while (it.hasNext()) {
EObject next = it.next();
if (type.isInstance(next)) {
children.add(type.cast(next));
}
}
return children;
}
/**
* Finds the {@link ConcreteClassifier} representing the class with the
* given classified name.
*
* @param name
* classified name of the ConcreteClassifier
*/
public static ConcreteClassifier getConcreteClassifier(Commentable me, String name) {
return (ConcreteClassifier) EcoreUtil.resolve(
JavaClasspath.get(me).getClassifier(name), me);
}
/**
* Finds all {@link ConcreteClassifier} representing the classes in the
* given package or a single class from that package.
*
* @param packageName
* name of the package
* @param classifierQuery
* * for all classifiers or name of a single classifier
*/
public static EList<ConcreteClassifier> getConcreteClassifiers(
Commentable me, String packageName, String classifierQuery) {
EList<ConcreteClassifier> result = new UniqueEList<ConcreteClassifier>();
JavaClasspath javaClasspath = JavaClasspath.get(me);
EList<EObject> classifiers = javaClasspath.getClassifiers(packageName, classifierQuery);
for (EObject classifier : classifiers) {
result.add((ConcreteClassifier) EcoreUtil.resolve(classifier, me));
}
return result;
}
public static ConcreteClassifier getConcreteClassifierProxy(Commentable me,
String name) {
JavaClasspath javaClasspath = JavaClasspath.get(me);
return (ConcreteClassifier) javaClasspath.getClassifier(name);
}
public static EList<ConcreteClassifier> getConcreteClassifierProxies(
Commentable me, String packageName, String classifierQuery) {
EList<ConcreteClassifier> result = new UniqueEList<ConcreteClassifier>();
JavaClasspath javaClasspath = JavaClasspath.get(me);
EList<EObject> classifiers = javaClasspath.getClassifiers(packageName, classifierQuery);
for (EObject classifier : classifiers) {
result.add((ConcreteClassifier) classifier);
}
return result;
}
/**
* Finds the {@link org.emftext.language.java.classifiers.Class}
* representing the class with the given name located in
* <code>java.lang</code>.
*
* @param name
* name of the Class
* @return the Class
*/
public static org.emftext.language.java.classifiers.Class getLibClass(
Commentable me, String name) {
JavaClasspath javaClasspath = JavaClasspath.get(me);
return javaClasspath.getJavaLangClass(me, name);
}
/**
* Finds the {@link org.emftext.language.java.classifiers.Interface}
* representing the interface with the given name located in
* <code>java.lang</code>.
*
* @param name
* name of the Interface
* @return the interface
*/
public static Interface getLibInterface(Commentable me, String name) {
ConcreteClassifier interfaceClass = me.getConcreteClassifierProxy(
"java.lang." + name);
EObject resolved = EcoreUtil.resolve(interfaceClass, me);
if (resolved instanceof Interface) {
return (Interface) resolved;
}
return null;
}
/**
* Finds the {@link org.emftext.language.java.classifiers.Class}
* representing <code>java.lang.Class</code>.
*
* @return the Class
*/
public static org.emftext.language.java.classifiers.Class getClassClass(Commentable me) {
return me.getLibClass("Class");
}
/**
* Finds the {@link org.emftext.language.java.classifiers.Class}
* representing <code>java.lang.Object</code>.
*
* @return the Class
*/
public static org.emftext.language.java.classifiers.Class getObjectClass(Commentable me) {
return me.getLibClass("Object");
}
/**
* Finds the {@link org.emftext.language.java.classifiers.Class}
* representing <code>java.lang.String</code>.
*
* @return the Class
*/
public static org.emftext.language.java.classifiers.Class getStringClass(Commentable me) {
return me.getLibClass("String");
}
/**
* Finds the {@link org.emftext.language.java.classifiers.Interface}
* representing <code>java.lang.annotation.Annotation</code>.
*
* @return the Class
*/
public static Interface getAnnotationInterface(Commentable me) {
ConcreteClassifier proxy = me.getConcreteClassifierProxy("java.lang.annotation.Annotation");
Interface annotationClass = (Interface) EcoreUtil.resolve(proxy, me);
EObject resolved = EcoreUtil.resolve(annotationClass, me);
if (resolved instanceof Interface) {
return (Interface) resolved;
}
return null;
}
//===== Container look up =====
/**
* Finds the containing classifier for the given element.
*
* @param value
* @return containing classifier
*/
public static ConcreteClassifier getContainingConcreteClassifier(Commentable me) {
EObject value = me;
while (!(value instanceof ConcreteClassifier) && value != null) {
value = value.eContainer();
}
return (ConcreteClassifier) value;
}
/**
* Finds the classifier that is the parent of this element. If this element
* is an inner classifier the parent classifier does not necessarily contain
* this element, since it can reside in a different compilation unit when
* stored in byte code.
*
* @return containing classifier
*/
public static ConcreteClassifier getParentConcreteClassifier(Commentable me) {
ConcreteClassifier classifier = me.getContainingConcreteClassifier();
if (classifier == null) {
CompilationUnit cu = me.getContainingCompilationUnit();
// Maybe the outer classifier is in an extra compilation unit
if (cu != null && cu.getName() != null && cu.getName().contains("$")) {
ConcreteClassifier proxy = me.getConcreteClassifierProxy(cu.getNamespacesAsString());
classifier = (ConcreteClassifier) EcoreUtil.resolve(proxy, me);
if (classifier.eIsProxy()) {
classifier = null;
}
}
}
return classifier;
}
/**
* Finds the containing anonymous class for the given element.
*
* @return containing anonymous class
*/
public static AnonymousClass getContainingAnonymousClass(Commentable me) {
EObject value = me;
while (!(value instanceof AnonymousClass)
&& !(value instanceof ConcreteClassifier) // Do not jump over other classifiers
&& value != null) {
value = value.eContainer();
}
if (!(value instanceof AnonymousClass)) {
return null;
}
return (AnonymousClass) value;
}
/**
* Finds the containing compilation unit for the given element.
*
* @return containing compilation unit
*/
public static CompilationUnit getContainingCompilationUnit(Commentable me) {
EObject value = me;
while (!(value instanceof CompilationUnit) && value != null) {
value = value.eContainer();
}
return (CompilationUnit) value;
}
/**
* Finds the containing annotation instance for the given element.
*
* @return containing annotation instance
*/
public static AnnotationInstance getContainingAnnotationInstance(Commentable me) {
EObject value = me;
while (!(value instanceof AnnotationInstance) && value != null) {
value = value.eContainer();
}
return (AnnotationInstance) value;
}
public static EList<String> getContainingPackageName(Commentable me) {
CompilationUnit cu = me.getContainingCompilationUnit();
if (cu == null) {
return null;
}
int idx = cu.getNamespaces().size();
if (cu.getName() != null) {
char[] fullName = cu.getName().toCharArray();
for (int i = 0; i < fullName.length; i++) {
if (fullName[i] == '$') {
idx--;
}
}
}
List<String> packageNameParts = cu.getNamespaces().subList(0, idx);
BasicEList<String> packageNameList = new BasicEList<String>(
packageNameParts);
return ECollections.unmodifiableEList(packageNameList);
}
public static EList<String> getContainingContainerName(Commentable me) {
CompilationUnit cu = me.getContainingCompilationUnit();
if (cu == null) {
return null;
}
return ECollections.unmodifiableEList(cu.getNamespaces());
}
public static EList<String> getComments(Commentable me) {
EList<String> comments = new BasicEList<String>();
if (me instanceof AnnotableAndModifiable) {
for (AnnotationInstanceOrModifier aom : ((AnnotableAndModifiable) me).getAnnotationsAndModifiers()) {
comments.addAll(aom.getComments());
}
}
for (LayoutInformation layoutInformation : me.getLayoutInformations()) {
String text = layoutInformation.getHiddenTokenText();
if (text.contains("/*") || text.contains("//")) {
comments.add(layoutInformation.getHiddenTokenText().trim());
}
}
return ECollections.unmodifiableEList(comments);
}
}