/*******************************************************************************
* Copyright © 2011, 2013 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.edt.compiler.binding;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.edt.compiler.core.ast.AnnotationExpression;
import org.eclipse.edt.compiler.core.ast.DefaultASTVisitor;
import org.eclipse.edt.compiler.core.ast.Class;
import org.eclipse.edt.compiler.core.ast.ExternalType;
import org.eclipse.edt.compiler.core.ast.Handler;
import org.eclipse.edt.compiler.core.ast.Interface;
import org.eclipse.edt.compiler.core.ast.Library;
import org.eclipse.edt.compiler.core.ast.Name;
import org.eclipse.edt.compiler.core.ast.Program;
import org.eclipse.edt.compiler.core.ast.Record;
import org.eclipse.edt.compiler.core.ast.Service;
import org.eclipse.edt.compiler.core.ast.SetValuesExpression;
import org.eclipse.edt.compiler.core.ast.SettingsBlock;
import org.eclipse.edt.compiler.internal.core.builder.IProblemRequestor;
import org.eclipse.edt.compiler.internal.core.lookup.AbstractBinder;
import org.eclipse.edt.compiler.internal.core.lookup.ResolutionException;
import org.eclipse.edt.compiler.internal.util.BindingUtil;
import org.eclipse.edt.mof.egl.AnnotationType;
import org.eclipse.edt.mof.egl.Part;
import org.eclipse.edt.mof.egl.Stereotype;
import org.eclipse.edt.mof.egl.StereotypeType;
import org.eclipse.edt.mof.egl.Type;
public class PartSubTypeAndAnnotationCollector extends DefaultASTVisitor {
private IProblemRequestor problemRequestor;
private List<SettingsBlock> settingsBlocks = new ArrayList<SettingsBlock>();
private Stereotype stereotype;
private Part partBinding;
private boolean foundSubTypeInSettingsBlock = false;
private AbstractBinder abstractBinder;
public PartSubTypeAndAnnotationCollector(Part partBinding, AbstractBinder binder, IProblemRequestor problemRequestor) {
super();
this.partBinding = partBinding;
this.abstractBinder = binder;
this.problemRequestor = problemRequestor;
}
public boolean visit(SettingsBlock settingsBlock) {
settingsBlocks.add(settingsBlock);
settingsBlock.accept(new DefaultASTVisitor() {
//Search the settings block for a parttype annotation
public boolean visit(SetValuesExpression setValuesExpression) {
return true;
}
public boolean visit(AnnotationExpression annotationExpression) {
Type resolvedType = null;
try {
resolvedType = abstractBinder.bindTypeName(annotationExpression.getName());
}
catch(ResolutionException e) {
resolvedType = null;
}
annotationExpression.getName().setElement(null); //reset the binding info so that resolution will work later
annotationExpression.getName().setType(null);
annotationExpression.getName().setBindAttempted(false);
StereotypeType stereotypeType = null;
if(resolvedType != null) {
AnnotationType annType = BindingUtil.getAnnotationType(resolvedType);
if (annType instanceof StereotypeType) {
stereotypeType = (StereotypeType)annType;
}
}
if (stereotypeType != null) {
if (BindingUtil.isApplicableFor(stereotypeType, partBinding)) {
if (stereotype == null) {
stereotype = (Stereotype)stereotypeType.newInstance();
foundSubTypeInSettingsBlock = true;
annotationExpression.getName().setElement(stereotype);
annotationExpression.getName().setType(stereotypeType);
annotationExpression.setType(stereotypeType);
} else {
problemRequestor.acceptProblem(annotationExpression.getName(), IProblemRequestor.DUPLICATE_PART_SUBTYPE);
}
}
else {
problemRequestor.acceptProblem(
annotationExpression.getName(),
IProblemRequestor.INVALID_PART_SUBTYPE,
new String[] {annotationExpression.getName().getCanonicalName(), partBinding.getCaseSensitiveName()});
}
}
return false;
}
public boolean visit(SettingsBlock settingsBlock) {
return true;
}
});
return false;
}
public boolean visit(Record record) {
if (record.hasSubType()) {
checkSubType(record.getSubType());
}
return true;
}
public boolean visit(Program program) {
if (program.hasSubType()) {
checkSubType(program.getSubType());
}
return true;
}
public boolean visit(Library library) {
if (library.hasSubType()) {
checkSubType(library.getSubType());
}
return true;
}
public boolean visit(Service service) {
if (service.hasSubType()) {
checkSubType(service.getSubType());
}
return true;
}
public boolean visit(Interface intrface) {
if (intrface.hasSubType()) {
checkSubType(intrface.getSubType());
}
return true;
}
public boolean visit(ExternalType externalType) {
if (externalType.hasSubType()) {
checkSubType(externalType.getSubType());
}
return true;
}
public boolean visit(Handler handler) {
if (handler.hasSubType()) {
checkSubType(handler.getSubType());
}
return true;
}
public boolean visit(Class eglClass) {
if (eglClass.hasSubType()) {
checkSubType(eglClass.getSubType());
}
return true;
}
private void checkSubType(Name name) {
StereotypeType stereotypeType = null;
Type resolvedType = null;
boolean typeResolved = false;
try {
resolvedType = abstractBinder.bindTypeName(name);
typeResolved = true;
}
catch(ResolutionException e) {
resolvedType = null;
}
if(resolvedType != null) {
AnnotationType annType = BindingUtil.getAnnotationType(resolvedType);
if (annType instanceof StereotypeType) {
stereotypeType = (StereotypeType)annType;
}
}
if (stereotypeType == null || !BindingUtil.isApplicableFor(stereotypeType, partBinding)) {
if(typeResolved) {
problemRequestor.acceptProblem(
name,
IProblemRequestor.INVALID_PART_SUBTYPE,
new String[] {name.getCanonicalName(), partBinding.getCaseSensitiveName()});
}
else {
problemRequestor.acceptProblem(
name,
IProblemRequestor.TYPE_CANNOT_BE_RESOLVED,
new String[] {name.getCanonicalName()});
}
name.setBindAttempted(true);
}
else {
stereotype = (Stereotype)stereotypeType.newInstance();
partBinding.addAnnotation(stereotype);
name.setType(stereotypeType);
name.setElement(stereotype);
}
}
public Stereotype getStereotype() {
return stereotype;
}
/**
* @return Returns the foundSubTypeInSettingsBlock.
*/
public boolean isFoundSubTypeInSettingsBlock() {
return foundSubTypeInSettingsBlock;
}
/**
* @return Returns the settingsBlocks.
*/
public List<SettingsBlock> getSettingsBlocks() {
return settingsBlocks;
}
}