/**********************************************************************
 * This file is part of "Object Teams Development Tooling"-Software
 * 
 * Copyright 2009, 2019 Technical University Berlin, Germany.
 * 
 * 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
 * 
 * Please visit http://www.eclipse.org/objectteams for updates and contact.
 * 
 * Contributors:
 * Technical University Berlin - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.otdt.internal.pde.validation;

import static org.eclipse.objectteams.otequinox.Constants.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.IMethodMappingBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.objectteams.otdt.core.IMethodMapping;
import org.eclipse.objectteams.otdt.core.IRoleType;
import org.eclipse.objectteams.otdt.core.OTModelManager;
import org.eclipse.objectteams.otdt.internal.pde.ui.OTPDEUIMessages;
import org.eclipse.objectteams.otequinox.ActivationKind;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.State;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.internal.core.builders.CompilerFlags;
import org.eclipse.pde.internal.core.builders.IHeader;
import org.eclipse.pde.internal.core.builders.IncrementalErrorReporter.VirtualMarker;
import org.eclipse.pde.internal.core.builders.PDEMarkerFactory;
import org.eclipse.pde.internal.core.ibundle.IManifestHeader;
import org.eclipse.pde.internal.core.text.bundle.BundleActivationPolicyHeader;
import org.eclipse.pde.internal.core.text.bundle.BundleModel;
import org.eclipse.pde.internal.core.text.plugin.PluginAttribute;
import org.eclipse.pde.internal.ui.correction.AbstractManifestMarkerResolution;
import org.eclipse.pde.internal.ui.correction.AbstractPDEMarkerResolution;
import org.eclipse.pde.internal.ui.correction.AbstractXMLMarkerResolution;
import org.eclipse.pde.internal.ui.correction.AddExportPackageMarkerResolution;
import org.eclipse.ui.IMarkerResolution;
import org.osgi.framework.Constants;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.resource.Capability;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import base org.eclipse.pde.internal.core.builders.BundleErrorReporter;
import base org.eclipse.pde.internal.core.builders.ExtensionsErrorReporter;
import base org.eclipse.pde.internal.core.builders.ManifestConsistencyChecker;
import base org.eclipse.pde.internal.core.builders.XMLErrorReporter;
import base org.eclipse.pde.internal.ui.correction.ResolutionGenerator;

/**
 * Enhanced validation of bundle manifests.
 * <ul>
 * <li>Check whether all bundles with aspectBindings have a proper activation policy set,<br>
 *    Provide suitable quick assist if activation policy is wrong/missing.</li>
 * </ul>
 * 
 * @author stephan
 * @since 1.2.7
 */
@SuppressWarnings("restriction")
public team class BundleValidation 
{
	/** Constant for a problem that can be resolved by adding an activation policy to the manifest. */
	static final int ADD_ACTIVATION_POLICY = 0x1801; // must not overlap with any constant in org.eclipse.pde.internal.core.builders.PDEMarkerFactory. 
	/** Constant for a problem that can be resolved by adding an activation policy to the manifest. */
	static final int ADD_PACKAGE_EXPORT = 0x1802; // must not overlap with any constant in org.eclipse.pde.internal.core.builders.PDEMarkerFactory. 
	static final int CHANGE_DOT_TO_DOLLAR = 0x1803; // must not overlap with any constant in org.eclipse.pde.internal.core.builders.PDEMarkerFactory.

	ThreadLocal<BundleCheckingContext> bundleContext = new ThreadLocal<BundleCheckingContext>();
	
	/** 
	 * Defines the context of validating one bundle. 
	 * One instance of this role exists per control flow (= per thread) 
	 * for retrieval in downstream callin bindings. 
	 */
	protected class BundleCheckingContext playedBy ManifestConsistencyChecker 
	{
		// flags set during validation of one bundle:
		protected boolean isAspectBundle = false;
		protected boolean hasTeamActivation = false;
		protected Set<String> aspectPackages = new HashSet<String>();

		/** packages containing bound base classes, which require the team to be bound to the corresponding base bundle. */
		public Map<String,List<String>> requiredBasePackagesPerTeam = new HashMap<String, List<String>>();
		
		IProject getProject() -> IProject getProject();  

		@SuppressWarnings("decapsulation")
		spanContext <- replace validateFiles;
		
		callin void spanContext() {
			BundleValidation.this.bundleContext.set(this);
			try {
				base.spanContext();
			} finally {
				// withdraw role, is for one-time use only:
				BundleValidation.this.bundleContext.set(null);
				BundleValidation.this.unregisterRole(this, BundleCheckingContext.class);
			}
		}
		protected void addRequiredBasePackage(String teamName, String baseName) {
			List<String> bases = requiredBasePackagesPerTeam.get(teamName);
			if (bases == null)
				requiredBasePackagesPerTeam.put(teamName, bases = new ArrayList<>());
			bases.add(baseName);
		}
	}
	
	/** Super-role for access to internal members. */
	protected class XMLAnalyzer playedBy XMLErrorReporter {
		@SuppressWarnings("decapsulation")
		protected String generateLocationPath(Node node, String attrName) -> String generateLocationPath(Node node, String attrName);

		@SuppressWarnings("decapsulation")
		protected IProject getFProject() -> get IProject fProject;
	}

	/**
	 * Detects aspectBindings declared in plugin.xml and records information in the current {@link BundleCheckingContext}.
	 * Directly reports erroneous use of '.' for nested team names.
	 */
	protected class ExtensionAnalyzer extends XMLAnalyzer playedBy ExtensionsErrorReporter 
			base when (BundleValidation.this.bundleContext.get() != null)
	{	
		
		@SuppressWarnings("decapsulation")
		State getState() -> get IPluginModelBase fModel
			with { result <- fModel.getBundleDescription().getContainingState() }
		
		VirtualMarker report(String message, int line, int severity, int fixId, String category)
		-> VirtualMarker report(String message, int line, int severity, int fixId, String category);

		@SuppressWarnings("decapsulation")
		int getLine(Element element) -> int getLine(Element element);
		
		@SuppressWarnings("decapsulation")
		int getLine(Element element, String attrName) -> int getLine(Element element, String attrName);

		VirtualMarker report(String message, int line, int severity, int fixId, Element element, String attrName, String category)
		<- replace VirtualMarker report(String message, int line, int severity, int fixId, Element element, String attrName, String category);

		void checkAspectBinding(Element element) <- after void validateExtension(Element element);

		protected void checkAspectBinding(Element element) 
		{
			Object pointID = element.getAttribute("point"); //$NON-NLS-1$
			if (ASPECT_BINDING_FQEXTPOINT_ID.equals(pointID)) 
			{
				BundleCheckingContext context = BundleValidation.this.bundleContext.get();
				// it's an aspect bundle
				context.isAspectBundle = true;
				
				IJavaProject jProject = JavaCore.create(context.getProject());

				boolean hasSelfAdaptation = false;
				NodeList baseNodes = element.getElementsByTagName(BASE_PLUGIN);
				for (int b=0; b<baseNodes.getLength(); b++) {
					if (SELF.equalsIgnoreCase(((Element)baseNodes.item(b)).getAttribute(ID))) {
						hasSelfAdaptation = true;
						break;
					}
				}

				Map<String,Map<String,Set<String>>> superBasePackagesByTeam;
				{
					List<IMethodMapping> mappings = new ArrayList<>();
	
					// collect binding requirements by nested teams of all bound teams:
					NodeList teamNodes = element.getElementsByTagName(TEAM);
					for (int t=0; t<teamNodes.getLength(); t++) {
						// record aspect packages:
						Object teamClass = ((Element)teamNodes.item(t)).getAttribute(CLASS);
						if (teamClass instanceof String)
							checkNestedTeams((String) teamClass, context, hasSelfAdaptation, mappings);
					}
					// collect packages with overridden base methods:
					superBasePackagesByTeam = collectOverridden(mappings);
				}
				NodeList aspectBindings = element.getChildNodes();
				int aspectCount = aspectBindings.getLength();
				for (int i = 0; i < aspectCount; i++) {
					Node aspectBinding = aspectBindings.item(i);
					// does it have elements with relevant activation?
					boolean isSelfAdaptation = false;
					boolean hasActivation = true;
					BundleDescription baseBundle = null;
					List<String> teamNames = new ArrayList<String>();

					NodeList children = aspectBinding.getChildNodes();
					int childrenCount = children.getLength();
					for (int j = 0; j < childrenCount; j++) {
						Node child = children.item(j);
						if (child instanceof Element) {
							Element childElement = (Element)child;
							String tagName = childElement.getTagName();
							if (BASE_PLUGIN.equals(tagName)) {
								String baseId = childElement.getAttribute(ID);
								if (baseId != null) {
									if (baseId.toUpperCase().equals(SELF))
										isSelfAdaptation = true; // missing bundle activation is not fatal in this case
									else
										baseBundle = checkBasePlugIn(baseId, getLine(childElement));
								}

							} else if (TEAM.equals(tagName)) {
								// analyze aspect packages:
								Element teamNode = childElement;
								Object teamClass = teamNode.getAttribute(CLASS);
								if (!(teamClass instanceof String))
									continue;
							
								String teamName = (String) teamClass;
								String actualPackage = checkActualPackage(context, teamNode, teamName);
								if (actualPackage == null)
									report(OTPDEUIMessages.Validation_MissingPackage_error, getLine(teamNode),
											CompilerFlags.ERROR, PDEMarkerFactory.NO_RESOLUTION, PDEMarkerFactory.CAT_FATAL);
								else
									context.aspectPackages.add(actualPackage);
								teamNames.add(teamName);

								// team activation?
								Object activation = teamNode.getAttribute(ACTIVATION);
								if (ActivationKind.ALL_THREADS.toString().equals(activation)) {
									hasActivation = true;
								} else if (ActivationKind.THREAD.toString().equals(activation)) {
									hasActivation = true;
								}
								NodeList superBases = teamNode.getElementsByTagName(SUPER_BASE);
								for (int k=0; k<superBases.getLength(); k++) {
									// report bad declarations & remove superBase requirements matching this declaration 
									Node grandChild = superBases.item(k);
									if (grandChild instanceof Element) {
										checkSuperBaseClass((Element) grandChild, superBasePackagesByTeam.get(teamName), jProject, baseBundle);
									}
								}
							}
						}
					}
					if (hasActivation && !isSelfAdaptation)
						context.hasTeamActivation = true;
					if (baseBundle != null) {
						// remove packages provided by this baseBundle from the list of required packages
						Set<String> providedPackages = new HashSet<String>();
						// for SELF-adaptation we don't need a package export, that's why we include those 
						// requirements from this check (see checkNestedTeams(..hasSelfAdaptation)).
						for (Capability cap : baseBundle.getCapabilities(PackageNamespace.PACKAGE_NAMESPACE))
							providedPackages.add((String) cap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE));
						for (String teamName: teamNames) {
							List<String> basePackagesList = context.requiredBasePackagesPerTeam.get(teamName);
							if (basePackagesList != null) {
								Iterator<String> basePackages = basePackagesList.iterator();
								while (basePackages.hasNext()) {
									String basePackage = basePackages.next();
									if (providedPackages.contains(basePackage))
										basePackages.remove();
								}
							}
						}
					}
				}
				// complain about remaining requiredBasePackages (i.e., those for which no binding was provided)
				reportUnmatchedRequirements(element, context.requiredBasePackagesPerTeam, e->e,
											OTPDEUIMessages.Validation_MissingBindingForBasePackage_error);
				// complain about remaining undeclared super bases:
				reportUnmatchedRequirements(element, superBasePackagesByTeam,
											e->e.values().stream().flatMap(Set::stream).collect(Collectors.toSet()),
											OTPDEUIMessages.Validation_MissingSuperBasePackageDecl_error);
			}
		}

		private <T> void reportUnmatchedRequirements(Element element,
				Map<String, T> requirementsPerTeam,
				Function<T,? extends Collection<String>> extractor,
				String errorMessageTemplate)
		{
			for (Entry<String, T> entry : requirementsPerTeam.entrySet()) {
				Collection<String> requireds = extractor.apply(entry.getValue());
				if (requireds != null && !requireds.isEmpty()) {
					for (String required : requireds) {
						report(NLS.bind(errorMessageTemplate, entry.getKey(), required),
								getLine(element),
								CompilerFlags.ERROR,
								PDEMarkerFactory.NO_RESOLUTION,
								PDEMarkerFactory.CAT_FATAL);
					}
				}
			}
		}

		private Map<String, Map<String,Set<String>>> collectOverridden(List<IMethodMapping> mappings) {
			Map<String,Map<String,Set<String>>> superBasePackagesByTeam = new HashMap<>(); // inner map is package name -> class names
			try {
				// collect role types from mappings (IType, then ITypeBinding):
				Set<IType> roleTypes = new HashSet<IType>(); 
				for (IMethodMapping mapping : mappings) {
					IType type = mapping.getDeclaringType();
					if (!"java.lang.Object".equals(type.getSuperclassName())) //$NON-NLS-1$
						roleTypes.add(type);
				}
				if (roleTypes.isEmpty())
					return Collections.emptyMap();
				ASTParser parser = ASTParser.newParser(AST.JLS12);
				parser.setProject(JavaCore.create(getFProject()));
				IBinding[] bindings = parser.createBindings(roleTypes.toArray(new IType[roleTypes.size()]), null);

				// from ITypeBinding descend into IMethodMappingBinding, then IMethodBinding (base):
				for (IBinding binding : bindings) {
					if (binding instanceof ITypeBinding) {
						String teamName = ((ITypeBinding) binding).getDeclaringClass().getQualifiedName();
						Map<String,Set<String>> perTeamResult = superBasePackagesByTeam.get(teamName);
						for (IMethodMappingBinding mappingBinding : ((ITypeBinding) binding).getResolvedMethodMappings()) {
							if (mappingBinding == null) continue;
							for (IMethodBinding basemethod : mappingBinding.getBaseMethods()) {
								if (!mappingBinding.isCallin() && Flags.isPublic(basemethod.getModifiers()))
									continue; // no weaving required for callout to public
								// find overridden
								for (IMethodBinding overriddenMethod : Bindings.findOverriddenMethods(basemethod, true, false)) {									
									if (Flags.isAbstract(overriddenMethod.getModifiers()))
										continue; // no code to weave
									// remember package of declaring class
									ITypeBinding declaringClass = overriddenMethod.getDeclaringClass();
									String packageName = declaringClass.getPackage().getName();
									if (perTeamResult == null) {
										superBasePackagesByTeam.put(teamName, perTeamResult = new HashMap<>());
									}
									Set<String> classSet = perTeamResult.get(packageName);
									if (classSet == null) {
										perTeamResult.put(packageName, classSet = new HashSet<>());
									}
									classSet.add(declaringClass.getQualifiedName());
								}
							}
						}
					}
				}
			} catch (JavaModelException e) {
				// cannot analyse
			}
			return superBasePackagesByTeam;
		}

		private void checkSuperBaseClass(Element elem, Map<String,Set<String>> collectedPackages, IJavaProject jProject, BundleDescription baseBundle) {
			try {
				String packageName = null;
				String superBaseClass = elem.getAttribute(SUPER_BASE_CLASS);
				if (superBaseClass != null) {
					IType clazz = jProject.findType(superBaseClass);
					if (clazz != null) { // otherwise assume standard validation already complained
						packageName = clazz.getPackageFragment().getElementName();
						if (collectedPackages == null || collectedPackages.remove(packageName) == null) {
							report(NLS.bind(OTPDEUIMessages.Validation_UnnecessarySuperBase_warning, superBaseClass),
									getLine(elem), 
									CompilerFlags.WARNING,
									PDEMarkerFactory.NO_RESOLUTION,
									PDEMarkerFactory.CAT_OTHER);
						}
					}
				}
				if (packageName != null) {
					String bundleName = elem.getAttribute(SUPER_BASE_PLUGIN);
					BundleDescription basePlugIn = !bundleName.isEmpty() ? checkBasePlugIn(bundleName, getLine(elem))
													: baseBundle; // fall back if no explicit plugin
					if (basePlugIn != null) {
						for (Capability cap : basePlugIn.getCapabilities(PackageNamespace.PACKAGE_NAMESPACE)) {
							if (packageName.equals(cap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE)))
								return;
						}
						report(NLS.bind(OTPDEUIMessages.Validation_PackageNotInSuperBase_error, bundleName, packageName),
								getLine(elem), 
								CompilerFlags.ERROR,
								PDEMarkerFactory.NO_RESOLUTION,
								PDEMarkerFactory.CAT_FATAL);						
					}
				}
			} catch (JavaModelException e) {
				// cannot analyse
			}
		}

		String checkActualPackage(BundleCheckingContext context, Element teamNode, String teamName) {
			int lastDot = teamName.lastIndexOf('.');
			if (lastDot == -1)
				return null;
			String packageName = teamName.substring(0, lastDot);
			String actualPackage = getContainingPackage(context, packageName);
			if (packageName != actualPackage) {
				VirtualMarker marker = report(NLS.bind(OTPDEUIMessages.Validation_NotAPackage_error, packageName),
						   getLine(teamNode, CLASS), 
						   CompilerFlags.ERROR,
						   CHANGE_DOT_TO_DOLLAR,
						   PDEMarkerFactory.CAT_FATAL);
				if (marker != null) {
					marker.setAttribute("package", actualPackage); //$NON-NLS-1$
					marker.setAttribute("team", teamName); //$NON-NLS-1$
					marker.setAttribute(PDEMarkerFactory.MPK_LOCATION_PATH, generateLocationPath(teamNode, CLASS));
				}
			}
			return actualPackage;
		}
		String getContainingPackage(BundleCheckingContext context, String packageNameCandidate) {
			IProject project = context.getProject();
			if (project != null) {
				IJavaProject jProject = JavaCore.create(project);
				if (jProject != null) {
					try {
						IJavaElement jElement = jProject.findElement(new Path(packageNameCandidate));
						if (jElement != null && jElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT)
							return packageNameCandidate;
						jElement = jProject.findType(packageNameCandidate);
						if (jElement != null) {
							IJavaElement ancestor = jElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
							if (ancestor != null)
								return ancestor.getElementName();
						}
					} catch (JavaModelException e) {
						// cannot analyse
					}
				}
			}
			return packageNameCandidate; // be shy about reporting errors in error contexts
		}

		BundleDescription checkBasePlugIn(String symbolicName, int lineNo) {
			BundleDescription[] bundles = getState().getBundles(symbolicName);
			if (bundles.length == 0) {
				report(NLS.bind(OTPDEUIMessages.Validation_UnresolveBasePlugin_error, symbolicName),
						   lineNo, 
						   CompilerFlags.ERROR,
						   PDEMarkerFactory.NO_RESOLUTION,
						   PDEMarkerFactory.CAT_OTHER);
				return null;
			}
			return bundles[0];
		}
		
		void checkNestedTeams(String teamName, BundleCheckingContext context, boolean hasSelfAdaptation, List<IMethodMapping> mappings) {
			teamName = teamName.replace('$', '.');
			IJavaProject jPrj = JavaCore.create(getFProject());
			if (jPrj.exists()) {
				try {
					IType teamType = jPrj.findType(teamName);
					if (teamType != null) {
						for (IType member : teamType.getTypes()) {
							if (OTModelManager.isTeam(member)) {
								String nestedTeamName = member.getFullyQualifiedName('$'); // name as used in aspectBinding.basePlugin
								for (IType role : OTModelManager.getOTElement(member).getRoleTypes()) {
									IType aBase = ((IRoleType) OTModelManager.getOTElement(role)).getBaseClass();
									if (aBase != null
											&& !(hasSelfAdaptation && aBase.getJavaProject().equals(jPrj)))
										context.addRequiredBasePackage(nestedTeamName, aBase.getPackageFragment().getElementName());
								}
								checkNestedTeams(nestedTeamName, context, hasSelfAdaptation, mappings);
							} else {
								IRoleType role = (IRoleType) OTModelManager.getOTElement(member);
								for (IMethodMapping mapping : role.getMethodMappings())
									mappings.add(mapping);
							}
						}
					}
				} catch (JavaModelException e) {
					// cannot analyse
				}
			}
		}

		@SuppressWarnings("basecall")
		callin VirtualMarker report(String message, int line, int severity, int fixId, Element element, String attrName, String category) {
			if (fixId == PDEMarkerFactory.M_DISCOURAGED_CLASS) {
				if (matchElementPath(element, new String[] {ASPECT_BINDING, TEAM, SUPER_BASE}, 2))
					return null; // don't report restriction inside aspectBinding/superBase
			}
			return base.report(message, line, severity, fixId, element, attrName, category);
		}

		private boolean matchElementPath(Element cur, String[] containerTags, int idx) {
			if (idx < 0)
				return true;
			if (!containerTags[idx].equals(cur.getTagName()))
				return false;
			Node parentNode = cur.getParentNode();
			if (parentNode instanceof Element)
				return matchElementPath((Element) parentNode, containerTags, idx-1);
			return false;
		}
	}
	
	/**
	 * Validates whether activation policy is set if needed.
     * This role is only active for bundles with one or more aspect bindings.
	 */
	protected class BundleErrorReporter playedBy BundleErrorReporter 
			base when (BundleValidation.this.bundleContext.get().isAspectBundle)
	{			
		@SuppressWarnings("decapsulation")
		void addMarkerAttribute(VirtualMarker marker, String attr, String val)
			-> void addMarkerAttribute(VirtualMarker marker, String attr, String val);
		@SuppressWarnings("decapsulation")
		IHeader getHeader(String key) -> IHeader getHeader(String key);
		VirtualMarker report(String message, int line, int severity, int resolution, String category) 
			-> VirtualMarker report(String message, int line, int severity, int resolution, String category);
		
		void validateBundleActivatorPolicy() <- after void validateBundleActivatorPolicy();
		
		void validateBundleActivatorPolicy() 
		{
			IHeader header = getHeader(Constants.BUNDLE_ACTIVATIONPOLICY);
			int lineNo = 1;
			if (header != null) {
				if (Constants.ACTIVATION_LAZY.equals(header.getValue()))
					return; // OK!
				lineNo = header.getLineNumber()+1;
			}
			boolean hasTeamActivation = BundleValidation.this.bundleContext.get().hasTeamActivation;
			report(OTPDEUIMessages.Validation_MissingActivationPolicy_error, 
				   lineNo, 
				   hasTeamActivation ? CompilerFlags.ERROR : CompilerFlags.WARNING, 	// only severe if relevant team activation is requested. 
				   ADD_ACTIVATION_POLICY, 
				   PDEMarkerFactory.CAT_FATAL);
		}

		void validateExportPackages() <- after void validateExportPackages();

		void validateExportPackages() {
			Set<String> needingExport = bundleContext.get().aspectPackages;
			if (needingExport.isEmpty()) return;
			IHeader header = getHeader(Constants.EXPORT_PACKAGE);
			if (header != null) {
				ManifestElement[] elements = header.getElements();
				for (int i = 0; i < elements.length; i++)
					needingExport.remove(elements[i].getValue());
			}
			for (String unmatched : needingExport) {
				VirtualMarker marker = report(NLS.bind(OTPDEUIMessages.Validation_MissingAspectPackageExport_error, unmatched), 
						   1, 
						   CompilerFlags.ERROR, 	// can reduce severity when we have the option to add the export at runtime 
						   ADD_PACKAGE_EXPORT, 
						   PDEMarkerFactory.CAT_FATAL);
				addMarkerAttribute(marker, "package", unmatched); //$NON-NLS-1$

				IHeader aspectBundleName = getHeader(Constants.BUNDLE_SYMBOLICNAME);
				if (aspectBundleName != null && aspectBundleName.getValue() != null) {
					String bundleSymbolicName = aspectBundleName.getValue();
					int semi = bundleSymbolicName.indexOf(';');
					if (semi != -1)
						bundleSymbolicName = bundleSymbolicName.substring(0, semi); // strip of attributes/directives like ;singleton:=true
					addMarkerAttribute(marker, "packages", unmatched+";ot-aspect-host=\""+bundleSymbolicName+"\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				}
				else {
					addMarkerAttribute(marker, "packages", unmatched); //$NON-NLS-1$
				}
			}
		}
	}

	/** Unbound role: simple rewriting of the manifest to add or correct an activation policy header. */
	protected class SetActivationPolicyResolution extends AbstractManifestMarkerResolution 
	{	
		public SetActivationPolicyResolution(int type) {
			super(type);
		}
	
		protected void createChange(BundleModel model) {
	
			IManifestHeader header = model.getBundle().getManifestHeader(Constants.BUNDLE_ACTIVATIONPOLICY);
	
			if (header != null && header instanceof BundleActivationPolicyHeader)
				((BundleActivationPolicyHeader) header).setLazyStart(true);
			else
				model.getBundle().setHeader(Constants.BUNDLE_ACTIVATIONPOLICY, Constants.ACTIVATION_LAZY);
		}
	
		public String getLabel() {
			return OTPDEUIMessages.Resolution_AddBundleActivationPolicy_label;
		}
	}
	
	/** Unbound role: simple rewriting of the manifest to add an Export-Package header. */
	protected class ExportAspectPackageResolution extends AddExportPackageMarkerResolution {
		String packageName;
		String export; // extended version with ot-aspect-host attribute
		public ExportAspectPackageResolution(IMarker marker) {
			super(marker, AbstractPDEMarkerResolution.CREATE_TYPE, marker.getAttribute("packages", null)); //$NON-NLS-1$
			this.packageName = marker.getAttribute("package", null); //$NON-NLS-1$
			this.export = marker.getAttribute("packages", null); //$NON-NLS-1$
		}
		@Override
		public String getLabel() {
			return NLS.bind(OTPDEUIMessages.Resolution_AddAspectPackageExport_label, packageName);
		}
		@Override
		public String getDescription() {
			return NLS.bind(OTPDEUIMessages.Resolution_AddAspectPackageExport_description, packageName, export);
		}
	}

	/** Unbound role: rewrite the team@class attribute for proper usage of '$' as inner class separator. */
	protected class ChangeDotToDollarResolution extends AbstractXMLMarkerResolution {
		String packageName;
		String teamName;
		String newName;

		public ChangeDotToDollarResolution(IMarker marker) {
			super(CHANGE_DOT_TO_DOLLAR, marker);
			this.packageName = marker.getAttribute("package", null); //$NON-NLS-1$
			this.teamName = marker.getAttribute("team", null); //$NON-NLS-1$
			this.newName = packageName + '.' +teamName.substring(this.packageName.length()+1).replace('.', '$');
		}
		@Override
		public String getLabel() {
			return NLS.bind(OTPDEUIMessages.Resolution_ChangeDotToDollar_label, this.teamName);
		}
		@Override
		public String getDescription() {
			return NLS.bind(OTPDEUIMessages.Resolution_ChangeDotToDollar_description, this.teamName, this.newName);
		}

		@Override
		protected void createChange(IPluginModelBase model) {
			Object node = findNode(model);
			if (!(node instanceof PluginAttribute))
				return;
			
			PluginAttribute attr = (PluginAttribute) node;
			attr.getEnclosingElement().setXMLAttribute(attr.getName(), this.newName);
		}
	}
	
	/**
	 * Advise the base class for handling missing/incorrect activation policy 
	 * (code {@link BundleValidation#ADD_ACTIVATION_POLICY}).
	 */
	protected class ResolutionGenerator playedBy ResolutionGenerator {

		IMarkerResolution[] getResolutions(IMarker marker) <- replace IMarkerResolution[] getResolutions(IMarker marker);
		
		callin IMarkerResolution[] getResolutions(IMarker marker) {
			IMarkerResolution[] result = base.getResolutions(marker);
			if (result.length == 0) {
				int problemID = marker.getAttribute(PDEMarkerFactory.PROBLEM_ID, PDEMarkerFactory.NO_RESOLUTION);
				switch (problemID) {
					case BundleValidation.ADD_ACTIVATION_POLICY :
						return new IMarkerResolution[] {new SetActivationPolicyResolution(AbstractPDEMarkerResolution.CREATE_TYPE)};
					case BundleValidation.ADD_PACKAGE_EXPORT :
						return new IMarkerResolution[] {new ExportAspectPackageResolution(marker) };
					case BundleValidation.CHANGE_DOT_TO_DOLLAR :
						return new IMarkerResolution[] {new ChangeDotToDollarResolution(marker) };
				}
			}
			return result;
		}
	}
}
