/*******************************************************************************
* 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.modifiers;
import java.util.ArrayList;
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.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.emftext.language.java.annotations.AnnotationInstance;
import org.emftext.language.java.classifiers.AnonymousClass;
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.literals.Self;
import org.emftext.language.java.modifiers.AnnotableAndModifiable;
import org.emftext.language.java.modifiers.AnnotationInstanceOrModifier;
import org.emftext.language.java.modifiers.Modifier;
import org.emftext.language.java.modifiers.ModifiersFactory;
import org.emftext.language.java.modifiers.Private;
import org.emftext.language.java.modifiers.Protected;
import org.emftext.language.java.modifiers.Public;
import org.emftext.language.java.modifiers.Static;
import org.emftext.language.java.references.Reference;
import org.emftext.language.java.references.SelfReference;
import org.emftext.language.java.types.Type;
public class AnnotableAndModifiableExtension {
/**
* Sets the visibility of this element to <code>private</code>.
*/
public static void makePrivate(AnnotableAndModifiable me) {
if (me.isPrivate()) {
return;
}
me.removeModifier(Public.class);
me.removeModifier(Protected.class);
me.getAnnotationsAndModifiers().add(ModifiersFactory.eINSTANCE.createPrivate());
}
/**
* Sets the visibility of this element to <code>public</code>.
*/
public static void makePublic(AnnotableAndModifiable me) {
if (me.isPublic()) {
return;
}
me.removeModifier(Private.class);
me.removeModifier(Protected.class);
me.getAnnotationsAndModifiers().add(ModifiersFactory.eINSTANCE.createPublic());
}
/**
* Sets the visibility of this element to <code>protected</code>.
*/
public static void makeProtected(AnnotableAndModifiable me) {
if (me.isProtected()) {
return;
}
me.removeModifier(Private.class);
me.removeModifier(Public.class);
me.getAnnotationsAndModifiers().add(ModifiersFactory.eINSTANCE.createProtected());
}
/**
* Removes all modifiers from this element.
*/
public static void removeAllModifiers(AnnotableAndModifiable me) {
List<Modifier> modifiers = me.getModifiers();
EList<AnnotationInstanceOrModifier> elements = me.getAnnotationsAndModifiers();
elements.removeAll(modifiers);
}
/**
* Returns an unmodifiable list of the modifiers that apply to this element.
*/
public static EList<Modifier> getModifiers(AnnotableAndModifiable me) {
EList<AnnotationInstanceOrModifier> elements = me.getAnnotationsAndModifiers();
EList<Modifier> modifiers = new BasicEList<Modifier>();
for (AnnotationInstanceOrModifier next : elements) {
if (next instanceof Modifier) {
modifiers.add((Modifier) next);
}
}
return ECollections.unmodifiableEList(modifiers);
}
/**
* Returns an unmodifiable list of the annotations that apply to this element.
*/
public static EList<AnnotationInstance> getAnnotationInstances(AnnotableAndModifiable me) {
EList<AnnotationInstanceOrModifier> elements = me.getAnnotationsAndModifiers();
EList<AnnotationInstance> annotations = new BasicEList<AnnotationInstance>();
for (AnnotationInstanceOrModifier next : elements) {
if (next instanceof AnnotationInstance) {
annotations.add((AnnotationInstance) next);
}
}
return ECollections.unmodifiableEList(annotations);
}
/**
* Adds the given type of modifier to this element. This method does not
* check for duplicate modifiers!
*
* @param newModifier the modifier to add
*/
public static void addModifier(AnnotableAndModifiable me, Modifier newModifier) {
me.getAnnotationsAndModifiers().add(newModifier);
}
/**
* Removes the given type of modifier from this element.
*
* @param modifierType
*/
public static void removeModifier(AnnotableAndModifiable me, Class<?> modifierType) {
List<AnnotationInstanceOrModifier> modifiers = me.getAnnotationsAndModifiers();
List<AnnotationInstanceOrModifier> modifiersToRemove = new ArrayList<AnnotationInstanceOrModifier>();
for (AnnotationInstanceOrModifier modifier : modifiers) {
if (modifierType.isInstance(modifier)) {
modifiersToRemove.add(modifier);
}
}
modifiers.removeAll(modifiersToRemove);
}
public static boolean isPublic(AnnotableAndModifiable me) {
return me.hasModifier(Public.class);
}
public static boolean isPrivate(AnnotableAndModifiable me) {
return me.hasModifier(Private.class);
}
public static boolean isProtected(AnnotableAndModifiable me) {
return me.hasModifier(Protected.class);
}
/**
* Checks whether this element has an modifier of the given type.
* @param type
*/
public static boolean hasModifier(AnnotableAndModifiable me, Class<?> type) {
List<AnnotationInstanceOrModifier> modifiers = me.getAnnotationsAndModifiers();
for (AnnotationInstanceOrModifier modifier : modifiers) {
if (type.isInstance(modifier)) {
return true;
}
}
return false;
}
/**
* Returns <code>true</code> if this element is static (either by an
* explicit modifier <code>static</code> or because this element is part of
* an interface).
*/
public static boolean isStatic(AnnotableAndModifiable me) {
//all members of an interface are static by default
if (me.eContainer() instanceof Interface) {
return true;
}
for (AnnotationInstanceOrModifier modifier : me.getAnnotationsAndModifiers()) {
if (modifier instanceof Static) {
return true;
}
}
return false;
}
public static boolean isHidden(AnnotableAndModifiable me, Commentable context) {
Commentable lContext = context;
if (me.eIsProxy()) {
return false;
}
//all members of an interface are public by default
if (me.eContainer() instanceof Interface) {
return false;
}
if (lContext.eIsProxy()) {
lContext = (Commentable) EcoreUtil.resolve(lContext, me);
}
ConcreteClassifier lContextClassifier = lContext.getContainingConcreteClassifier();
if (!(me.eContainer() instanceof Commentable)) {
return true;
}
ConcreteClassifier myClassifier = ((Commentable) me.eContainer()).getParentConcreteClassifier();
//special case: self reference to outer instance
if (lContext instanceof Reference) {
if (((Reference)lContext).getPrevious() instanceof SelfReference) {
SelfReference selfReference = (SelfReference) ((Reference)lContext).getPrevious();
if (selfReference.getSelf() instanceof Self) {
if (selfReference.getPrevious() != null) {
Type type = selfReference.getPrevious().getReferencedType();
if (type instanceof ConcreteClassifier) {
lContextClassifier = (ConcreteClassifier) type;
}
}
}
}
}
for (AnnotationInstanceOrModifier modifier : me.getAnnotationsAndModifiers()) {
if (modifier instanceof Private) {
if (myClassifier.equalsType(0, lContextClassifier, 0)) {
return false;
}
return true;
}
if(modifier instanceof Public) {
return false;
}
if(modifier instanceof Protected) {
//package visibility
if (me.getContainingPackageName() != null &&
me.getContainingPackageName().equals(lContext.getContainingPackageName())) {
return false;
}
//try outer classifiers as well
while(lContextClassifier instanceof Classifier) {
if (lContextClassifier.isSuperType(0, myClassifier, null)) {
return false;
}
EObject container = lContextClassifier.eContainer();
if (container instanceof Commentable) {
lContextClassifier = ((Commentable) container).getParentConcreteClassifier();
} else {
lContextClassifier = null;
}
if (lContextClassifier != null && !lContextClassifier.eIsProxy() &&
lContextClassifier.isSuperType(0, myClassifier, null)) {
return false;
}
}
//visibility through anonymous subclass
AnonymousClass anonymousClass = lContext.getContainingAnonymousClass();
while (anonymousClass != null) {
lContextClassifier = anonymousClass.getSuperClassifier();
if (lContextClassifier == null) {
return true;
}
if (lContextClassifier.isSuperType(0, myClassifier, null)) {
return false;
}
EObject container = anonymousClass.eContainer();
if (container instanceof Commentable) {
anonymousClass = ((Commentable) container).getContainingAnonymousClass();
} else {
anonymousClass = null;
}
}
return true;
}
}
//package visibility?
if (me.getContainingPackageName() != null &&
me.getContainingPackageName().equals(lContext.getContainingPackageName())) {
return false;
}
return true;
}
}