/*
 * Copyright (c) 2005, 2006 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 - initial API and implementation
 *
 * $Id: NamespaceOperations.java,v 1.14 2006/12/14 15:49:26 khussey Exp $
 */
package org.eclipse.uml2.uml.internal.operations;

import java.util.Map;

import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.emf.common.util.ECollections;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.UniqueEList;

import org.eclipse.emf.ecore.InternalEObject;

import org.eclipse.uml2.common.util.UnionEObjectEList;

import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Namespace;
import org.eclipse.uml2.uml.PackageImport;
import org.eclipse.uml2.uml.PackageableElement;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.UMLPlugin;
import org.eclipse.uml2.uml.VisibilityKind;

import org.eclipse.uml2.uml.util.UMLValidator;

/**
 * <!-- begin-user-doc -->
 * A static utility class that provides operations related to '<em><b>Namespace</b></em>' model objects.
 * <!-- end-user-doc -->
 *
 * <p>
 * The following operations are supported:
 * <ul>
 *   <li>{@link org.eclipse.uml2.uml.Namespace#validateMembersDistinguishable(org.eclipse.emf.common.util.DiagnosticChain, java.util.Map) <em>Validate Members Distinguishable</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Namespace#createElementImport(org.eclipse.uml2.uml.PackageableElement, org.eclipse.uml2.uml.VisibilityKind) <em>Create Element Import</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Namespace#createPackageImport(org.eclipse.uml2.uml.Package, org.eclipse.uml2.uml.VisibilityKind) <em>Create Package Import</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Namespace#getImportedElements() <em>Get Imported Elements</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Namespace#getImportedPackages() <em>Get Imported Packages</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Namespace#getImportedMembers() <em>Get Imported Members</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Namespace#getNamesOfMember(org.eclipse.uml2.uml.NamedElement) <em>Get Names Of Member</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Namespace#membersAreDistinguishable() <em>Members Are Distinguishable</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Namespace#importMembers(org.eclipse.emf.common.util.EList) <em>Import Members</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Namespace#excludeCollisions(org.eclipse.emf.common.util.EList) <em>Exclude Collisions</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class NamespaceOperations
		extends NamedElementOperations {

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected NamespaceOperations() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * All the members of a Namespace are distinguishable within it.
	 * membersAreDistinguishable()
	 * <!-- end-model-doc -->
	 * @generated NOT
	 */
	public static boolean validateMembersDistinguishable(Namespace namespace,
			DiagnosticChain diagnostics, Map<Object, Object> context) {
		boolean result = true;

		if (!namespace.membersAreDistinguishable()) {
			result = false;

			if (diagnostics != null) {
				diagnostics.add(new BasicDiagnostic(Diagnostic.WARNING,
					UMLValidator.DIAGNOSTIC_SOURCE,
					UMLValidator.NAMESPACE__MEMBERS_DISTINGUISHABLE,
					UMLPlugin.INSTANCE.getString(
						"_UI_Namespace_MembersDistinguishable_diagnostic", //$NON-NLS-1$
						getMessageSubstitutions(context, namespace)),
					new Object[]{namespace}));
			}
		}

		return result;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static ElementImport createElementImport(Namespace namespace,
			PackageableElement element, VisibilityKind visibility) {

		if (element == null
			|| namespace.getImportedElements().contains(element)) {

			throw new IllegalArgumentException(String.valueOf(element));
		}

		if (visibility == null) {
			throw new IllegalArgumentException(String.valueOf(visibility));
		}

		ElementImport elementImport = namespace.createElementImport(element);
		elementImport.setVisibility(visibility);

		return elementImport;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static PackageImport createPackageImport(Namespace namespace,
			org.eclipse.uml2.uml.Package package_, VisibilityKind visibility) {

		if (package_ == null
			|| namespace.getImportedPackages().contains(package_)) {

			throw new IllegalArgumentException(String.valueOf(package_));
		}

		if (visibility == null) {
			throw new IllegalArgumentException(String.valueOf(visibility));
		}

		PackageImport packageImport = namespace.createPackageImport(package_);
		packageImport.setVisibility(visibility);

		return packageImport;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static EList<PackageableElement> getImportedElements(
			Namespace namespace) {
		EList<PackageableElement> importedElements = new UniqueEList.FastCompare<PackageableElement>();

		for (ElementImport elementImport : namespace.getElementImports()) {
			PackageableElement importedElement = elementImport
				.getImportedElement();

			if (importedElement != null) {
				importedElements.add(importedElement);
			}
		}

		return ECollections.unmodifiableEList(importedElements);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static EList<org.eclipse.uml2.uml.Package> getImportedPackages(
			Namespace namespace) {
		EList<org.eclipse.uml2.uml.Package> importedPackages = new UniqueEList.FastCompare<org.eclipse.uml2.uml.Package>();

		for (PackageImport packageImport : namespace.getPackageImports()) {
			org.eclipse.uml2.uml.Package importedPackage = packageImport
				.getImportedPackage();

			if (importedPackage != null) {
				importedPackages.add(importedPackage);
			}
		}

		return ECollections.unmodifiableEList(importedPackages);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * The importedMember property is derived from the ElementImports and the PackageImports. References the PackageableElements that are members of this Namespace as a result of either PackageImports or ElementImports.
	 * The importedMember property is derived from the ElementImports and the PackageImports.
	 * result = self.importMembers(self.elementImport.importedElement.asSet()-
	 * >union(self.packageImport.importedPackage->collect(p | p.visibleMembers())))
	 * <!-- end-model-doc -->
	 * @generated NOT
	 */
	public static EList<PackageableElement> getImportedMembers(
			Namespace namespace) {
		EList<PackageableElement> importedMembers = new UniqueEList.FastCompare<PackageableElement>();

		for (ElementImport elementImport : namespace.getElementImports()) {
			PackageableElement importedElement = elementImport
				.getImportedElement();

			if (importedElement != null) {
				importedMembers.add(importedElement);
			}
		}

		for (PackageImport packageImport : namespace.getPackageImports()) {
			org.eclipse.uml2.uml.Package importedPackage = packageImport
				.getImportedPackage();

			if (importedPackage != null) {
				importedMembers.addAll(importedPackage.visibleMembers());
			}
		}

		return new UnionEObjectEList<PackageableElement>(
			(InternalEObject) namespace,
			UMLPackage.Literals.NAMESPACE__IMPORTED_MEMBER, importedMembers
				.size(), importedMembers.toArray());
	}

	protected static EList<String> getNamesOfMember(Namespace namespace,
			NamedElement element, EList<Namespace> namespaces,
			EList<String> namesOfMember) {

		if (!namespaces.contains(namespace)) {
			namespaces.add(namespace);

			if (namespace.getOwnedMembers().contains(element)) {
				String name = element.getName();

				if (!isEmpty(name)) {
					namesOfMember.add(name);
				}
			} else {
				EList<String> elementImportNames = new UniqueEList<String>();

				for (ElementImport elementImport : namespace
					.getElementImports()) {

					if (elementImport.getImportedElement() == element) {
						String name = elementImport.getName();

						if (!isEmpty(name)) {
							elementImportNames.add(name);
						}
					}
				}

				if (elementImportNames.isEmpty()) {

					for (PackageImport packageImport : namespace
						.getPackageImports()) {

						org.eclipse.uml2.uml.Package importedPackage = packageImport
							.getImportedPackage();

						if (importedPackage != null
							&& importedPackage.visibleMembers().contains(
								element)) {

							getNamesOfMember(importedPackage, element,
								namespaces, namesOfMember);
						}
					}
				} else {
					namesOfMember.addAll(elementImportNames);
				}
			}
		}

		return namesOfMember;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * The query getNamesOfMember() is overridden to take account of importing. It gives back the set of names that an element would have in an importing namespace, either because it is owned, or if not owned then imported individually, or if not individually then from a package.
	 * The query getNamesOfMember() gives a set of all of the names that a member would have in a Namespace. In general a member can have multiple names in a Namespace if it is imported more than once with different aliases. The query takes account of importing. It gives back the set of names that an element would have in an importing namespace, either because it is owned, or if not owned then imported individually, or if not individually then from a package.
	 * result = if self.ownedMember ->includes(element)
	 * then Set{}->include(element.name)
	 * else let elementImports: ElementImport = self.elementImport->select(ei | ei.importedElement = element) in
	 *   if elementImports->notEmpty()
	 *   then elementImports->collect(el | el.getName())
	 *   else self.packageImport->select(pi | pi.importedPackage.visibleMembers()->includes(element))-> collect(pi | pi.importedPackage.getNamesOfMember(element))
	 *   endif
	 * endif
	 * <!-- end-model-doc -->
	 * @generated NOT
	 */
	public static EList<String> getNamesOfMember(Namespace namespace,
			NamedElement element) {
		return ECollections.unmodifiableEList(getNamesOfMember(namespace,
			element, new UniqueEList.FastCompare<Namespace>(),
			new UniqueEList<String>()));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * The Boolean query membersAreDistinguishable() determines whether all of the namespace's members are distinguishable within it.
	 * result = self.member->forAll( memb |
	 * self.member->excluding(memb)->forAll(other |
	 * memb.isDistinguishableFrom(other, self)))
	 * <!-- end-model-doc -->
	 * @generated NOT
	 */
	public static boolean membersAreDistinguishable(Namespace namespace) {
		EList<NamedElement> namespaceMembers = namespace.getMembers();

		for (NamedElement member : namespaceMembers) {

			for (NamedElement otherMember : namespaceMembers) {

				if (member != otherMember
					&& !member.isDistinguishableFrom(otherMember, namespace)) {

					return false;
				}
			}
		}

		return true;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * The query importMembers() defines which of a set of PackageableElements are actually imported into the namespace. This excludes hidden ones, i.e., those which have names that conflict with names of owned members, and also excludes elements which would have the same name when imported.
	 * result = self.excludeCollisions(imps)->select(imp | self.ownedMember->forAll(mem |
	 * mem.imp.isDistinguishableFrom(mem, self)))
	 * <!-- end-model-doc -->
	 * @generated NOT
	 */
	public static EList<PackageableElement> importMembers(Namespace namespace,
			EList<PackageableElement> imps) {
		EList<PackageableElement> importMembers = new UniqueEList.FastCompare<PackageableElement>();
		EList<NamedElement> ownedMembers = namespace.getOwnedMembers();

		excludeCollisionsLoop : for (PackageableElement excludeCollision : namespace
			.excludeCollisions(imps)) {

			for (NamedElement ownedMember : ownedMembers) {

				if (!excludeCollision.isDistinguishableFrom(ownedMember,
					namespace)) {

					continue excludeCollisionsLoop;
				}
			}

			importMembers.add(excludeCollision);
		}

		return ECollections.unmodifiableEList(importMembers);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * The query excludeCollisions() excludes from a set of PackageableElements any that would not be distinguishable from each other in this namespace.
	 * result = imps->reject(imp1 | imps.exists(imp2 | not imp1.isDistinguishableFrom(imp2, self)))
	 * <!-- end-model-doc -->
	 * @generated NOT
	 */
	public static EList<PackageableElement> excludeCollisions(
			Namespace namespace, EList<PackageableElement> imps) {
		EList<PackageableElement> excludeCollisions = new UniqueEList.FastCompare<PackageableElement>();

		imps1Loop : for (PackageableElement imp1 : imps) {

			for (PackageableElement imp2 : imps) {

				if (imp1 != imp2
					&& !imp1.isDistinguishableFrom(imp2, namespace)) {

					continue imps1Loop;
				}
			}

			excludeCollisions.add(imp1);
		}

		return ECollections.unmodifiableEList(excludeCollisions);
	}

} // NamespaceOperations