/*
 * 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: StereotypeOperations.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.UniqueEList;

import org.eclipse.emf.common.util.EList;

import org.eclipse.emf.ecore.EClass;

import org.eclipse.uml2.uml.AggregationKind;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Extension;
import org.eclipse.uml2.uml.Image;
import org.eclipse.uml2.uml.ExtensionEnd;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.UMLPackage;

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

/**
 * <!-- begin-user-doc -->
 * A static utility class that provides operations related to '<em><b>Stereotype</b></em>' model objects.
 * <!-- end-user-doc -->
 *
 * <p>
 * The following operations are supported:
 * <ul>
 *   <li>{@link org.eclipse.uml2.uml.Stereotype#validateNameNotClash(org.eclipse.emf.common.util.DiagnosticChain, java.util.Map) <em>Validate Name Not Clash</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Stereotype#validateGeneralize(org.eclipse.emf.common.util.DiagnosticChain, java.util.Map) <em>Validate Generalize</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Stereotype#createExtension(org.eclipse.uml2.uml.Class, boolean) <em>Create Extension</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Stereotype#getProfile() <em>Get Profile</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Stereotype#getKeyword() <em>Get Keyword</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Stereotype#getKeyword(boolean) <em>Get Keyword</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Stereotype#getExtendedMetaclasses() <em>Get Extended Metaclasses</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Stereotype#getAllExtendedMetaclasses() <em>Get All Extended Metaclasses</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Stereotype#getDefinition() <em>Get Definition</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Stereotype#createIcon(java.lang.String) <em>Create Icon</em>}</li>
 *   <li>{@link org.eclipse.uml2.uml.Stereotype#createIcon(java.lang.String, java.lang.String) <em>Create Icon</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class StereotypeOperations
		extends ClassOperations {

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

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * Stereotype names should not clash with keyword names for the extended model element.
	 * true
	 * <!-- end-model-doc -->
	 * @generated
	 */
	public static boolean validateNameNotClash(Stereotype stereotype,
			DiagnosticChain diagnostics, Map<Object, Object> context) {
		// TODO: implement this method
		// -> specify the condition that violates the invariant
		// -> verify the details of the diagnostic, including severity and message
		// Ensure that you remove @generated or mark it @generated NOT
		if (false) {
			if (diagnostics != null) {
				diagnostics
					.add(new BasicDiagnostic(
						Diagnostic.ERROR,
						UMLValidator.DIAGNOSTIC_SOURCE,
						UMLValidator.STEREOTYPE__NAME_NOT_CLASH,
						org.eclipse.emf.ecore.plugin.EcorePlugin.INSTANCE
							.getString(
								"_UI_GenericInvariant_diagnostic", new Object[]{"validateNameNotClash", org.eclipse.emf.ecore.util.EObjectValidator.getObjectLabel(stereotype, context)}), //$NON-NLS-1$ //$NON-NLS-2$
						new Object[]{stereotype}));
			}
			return false;
		}
		return true;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * A Stereotype may only generalize or specialize another Stereotype.
	 * generalization.general->forAll(e |e.oclIsKindOf(Stereotype)) and generalization.specific->forAll(e | e.oclIsKindOf(Stereotype)) 
	 * <!-- end-model-doc -->
	 * @generated
	 */
	public static boolean validateGeneralize(Stereotype stereotype,
			DiagnosticChain diagnostics, Map<Object, Object> context) {
		// TODO: implement this method
		// -> specify the condition that violates the invariant
		// -> verify the details of the diagnostic, including severity and message
		// Ensure that you remove @generated or mark it @generated NOT
		if (false) {
			if (diagnostics != null) {
				diagnostics
					.add(new BasicDiagnostic(
						Diagnostic.ERROR,
						UMLValidator.DIAGNOSTIC_SOURCE,
						UMLValidator.STEREOTYPE__GENERALIZE,
						org.eclipse.emf.ecore.plugin.EcorePlugin.INSTANCE
							.getString(
								"_UI_GenericInvariant_diagnostic", new Object[]{"validateGeneralize", org.eclipse.emf.ecore.util.EObjectValidator.getObjectLabel(stereotype, context)}), //$NON-NLS-1$ //$NON-NLS-2$
						new Object[]{stereotype}));
			}
			return false;
		}
		return true;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static Extension createExtension(Stereotype stereotype,
			org.eclipse.uml2.uml.Class metaclass, boolean isRequired) {
		String name = stereotype.getName();

		if (isEmpty(name)) {
			throw new IllegalStateException();
		}

		Profile profile = stereotype.getProfile();

		if (profile == null) {
			throw new IllegalStateException();
		}

		if (metaclass == null || !metaclass.isMetaclass()
			|| stereotype.getExtendedMetaclasses().contains(metaclass)) {

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

		if (!profile.getReferencedMetaclasses().contains(metaclass)
			&& !profile.getReferencedMetamodels()
				.contains(metaclass.getModel())) {

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

		String metaclassName = metaclass.getName();
		Extension extension = (Extension) profile.createOwnedType(metaclassName
			+ '_' + name, UMLPackage.Literals.EXTENSION);

		ExtensionEnd extensionEnd = (ExtensionEnd) extension.createOwnedEnd(
			Extension.STEREOTYPE_ROLE_PREFIX + name, stereotype,
			UMLPackage.Literals.EXTENSION_END);
		extensionEnd.setAggregation(AggregationKind.COMPOSITE_LITERAL);

		if (isRequired) {
			extensionEnd.setLower(1);
		}

		Property property = stereotype.createOwnedAttribute(
			Extension.METACLASS_ROLE_PREFIX + metaclassName, metaclass);
		property.setAssociation(extension);

		return extension;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static Profile getProfile(Stereotype stereotype) {
		org.eclipse.uml2.uml.Package package_ = stereotype.getPackage();
		return package_ instanceof Profile
			? (Profile) package_
			: null;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static String getKeyword(Stereotype stereotype) {
		return stereotype.getKeyword(true);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static String getKeyword(Stereotype stereotype, boolean localize) {
		String keyword = getString(stereotype,
			getValidJavaIdentifier(stereotype.getQualifiedName().replace(':',
				'_')), EMPTY_STRING, localize);

		if (isEmpty(keyword)) {
			String identifier = getValidJavaIdentifier(stereotype.getName());

			keyword = identifier.length() > 0
				? Character.toLowerCase(identifier.charAt(0))
					+ identifier.substring(1)
				: identifier;
		}

		return keyword;
	}

	protected static EList<org.eclipse.uml2.uml.Class> getExtendedMetaclasses(
			Stereotype stereotype,
			EList<org.eclipse.uml2.uml.Class> extendedMetaclasses) {

		for (Property ownedAttribute : stereotype.getOwnedAttributes()) {

			if (ownedAttribute.getAssociation() instanceof Extension) {
				Type type = ownedAttribute.getType();

				if (type instanceof org.eclipse.uml2.uml.Class) {
					extendedMetaclasses.add((org.eclipse.uml2.uml.Class) type);
				}
			}
		}

		return extendedMetaclasses;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static EList<org.eclipse.uml2.uml.Class> getExtendedMetaclasses(
			Stereotype stereotype) {
		return ECollections.unmodifiableEList(getExtendedMetaclasses(
			stereotype,
			new UniqueEList.FastCompare<org.eclipse.uml2.uml.Class>()));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static EList<org.eclipse.uml2.uml.Class> getAllExtendedMetaclasses(
			Stereotype stereotype) {
		EList<org.eclipse.uml2.uml.Class> allExtendedMetaclasses = getExtendedMetaclasses(
			stereotype,
			new UniqueEList.FastCompare<org.eclipse.uml2.uml.Class>());

		for (Classifier parent : stereotype.allParents()) {

			if (parent instanceof Stereotype) {
				getExtendedMetaclasses((Stereotype) parent,
					allExtendedMetaclasses);
			}
		}

		return ECollections.unmodifiableEList(allExtendedMetaclasses);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static EClass getDefinition(Stereotype stereotype) {
		Profile profile = stereotype.getProfile();
		return profile == null
			? null
			: (EClass) profile.getDefinition(stereotype);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static Image createIcon(Stereotype stereotype, String location) {
		Image icon = stereotype.createIcon();
		icon.setLocation(location);
		return icon;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public static Image createIcon(Stereotype stereotype, String format,
			String content) {
		Image icon = stereotype.createIcon();
		icon.setFormat(format);
		icon.setContent(content);
		return icon;
	}

} // StereotypeOperations