package com.sap.ip.mmr.mof14;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.jmi.model.AggregationKindEnum;
import javax.jmi.model.AssociationEnd;
import javax.jmi.model.ModelElement;
import javax.jmi.model.ModelPackage;

import com.sap.ip.mmr.IMMRInstance;
import com.sap.ip.mmr.IRepository;
import com.sap.ip.mmr.StateEnum;
import com.sap.ip.mmr.foundation.Association;
import com.sap.ip.mmr.foundation.AssociationsOfObject;
import com.sap.ip.mmr.foundation.IAssociationsOfObject;
import com.sap.ip.mmr.foundation.Utilities;
import com.sap.ip.mmr.foundation.AssociationsContainer.MultiplicityOfAssoc;
import com.sap.ip.mmr.mof14.generic.RefBaseObjectImpl;
import com.sap.ip.mmr.mof14.model.ModelPackageImpl;

public class RepositoryMof14Gen implements IRepositoryMof14 {

	public static final String ASSOC_ID_CONTAINS = "4F217B07-80F7-2472-F8F4-F2435917";
	public static final String MOFID_MODEL = "A63D9D81-7796-FD9B-B446-1E0002F3";

	private IRepository repository;

	private Map instances = new HashMap();
	private Map associations = new HashMap();
	private Map qualifiedNameToMofId = new HashMap();

	private ModelPackageImpl modelPackage;

	public RepositoryMof14Gen() {
	}

	/**
	 * @see com.sap.ip.mmr.mof14.IRepositoryMof14#resolveQualifiedName(java.lang.String[])
	 */
	public IMMRInstance resolveQualifiedName(String[] qualifiedName) {
		IMMRInstance mmri = null;
		// get MOF ID by qualified Name
		String qn = Utilities.getUtilities().encodeMmrQualifiedName(qualifiedName);
		String mofId = (String) qualifiedNameToMofId.get(qn);
		if (mofId != null) {
			// get the instances
			mmri = select(mofId);
		}
		/* just for debugging of bootstrap phase
		if (mmri == null) {
			System.err.println("resolveQualifiedName failed for " + qn);
		}
		*/
		return mmri;
	}

	/**
	 * @see com.sap.ip.mmr.mof14.IRepositoryMof14#select(java.lang.String)
	 */
	public IMMRInstance select(String mofId) {
		IMMRInstance mmri = (IMMRInstance) instances.get(mofId);
		/* just for debugging of bootstrap phase
		if (mmri == null) {
			System.err.println("select failed for " + mofId);
		}
		*/
		return mmri;
	}

	/**
	 * @see com.sap.ip.mmr.mof14.IRepositoryMof14#selectAssoc(java.lang.String, java.lang.String)
	 */
	public IAssociationsOfObject selectAssoc(String associationMofId, String mofId) {
		IAssociationsOfObject aoo = (IAssociationsOfObject) associations.get(mofId);
		/* just for debugging of bootstrap phase
		if (aoo == null) {
			System.err.println("selectAssoc failed for " + mofId);
		}
		*/
		return aoo;
	}

	/**
	 * @see com.sap.ip.mmr.mof14.IRepositoryMof14#getMultiplicity(java.lang.String)
	 */
	public MultiplicityOfAssoc getMultiplicity(String mofIdOfAssociation) {
		MultiplicityOfAssoc moa = null;
		// read the associations
		IAssociationsOfObject aoo = selectAssoc(ASSOC_ID_CONTAINS, mofIdOfAssociation); // read contains
		if (aoo != null) {
			// read the association ends
			AssociationEnd ae1 = null;
			AssociationEnd ae2 = null;
			Iterator iter = aoo.getMofIdsForward().iterator();
			while (iter.hasNext()) {
				Association a = (Association) iter.next();
				if (a.getAssociationId().compareTo(ASSOC_ID_CONTAINS) == 0) {
					ModelElement me = (ModelElement) select(a.getMofId2());
					if (me instanceof AssociationEnd) {
						if (ae1 == null) {
							ae1 = (AssociationEnd) me;
						} else if (ae2 == null) {
							ae2 = (AssociationEnd) me;
						}
					}
				}
			}
			// read the instances
			if (ae1 != null && ae2 != null) {
				moa = new MultiplicityOfAssoc();
				moa.associationMofId = mofIdOfAssociation;
				moa.multEnd1 = ae1.getMultiplicity();
				moa.multEnd2 = ae2.getMultiplicity();
				moa.composite1 = AggregationKindEnum.COMPOSITE.equals(ae1.getAggregation());
				moa.composite2 = AggregationKindEnum.COMPOSITE.equals(ae2.getAggregation());
			}
		}
		return moa;
	}

	private void addInstance(IMMRInstance mmri, String qualifiedName) {
		// add the instance
		instances.put(mmri.getMmrId(), mmri);
		// add the pair (qualified naem, MOF ID)
		qualifiedNameToMofId.put(qualifiedName, mmri.getMmrId());
		// set some properties
		mmri.set___Repository(repository);
		mmri.set___State(StateEnum.STATE_READ_ONLY);
	}

	private void addAssociation(IAssociationsOfObject aoo, String mofId) {
		associations.put(mofId, aoo);
	}

	public ModelPackage getModelPackage() {
		return modelPackage;
	}

	/**
	 * @see com.sap.ip.mmr.mof14.IRepositoryMof14#initialize(IRepository repository)
	 */
	public void initialize(IRepository repository) {
		this.repository = repository;
		initInstances();
		initAssociations();
		// initialize model package AFTER this, because the model package
		// will call resolveQualifiedname to determine the MOF ID of the metaobjects
		// of the associations in model package
		modelPackage = new ModelPackageImpl(repository);
		modelPackage.setMmrId(MOFID_MODEL);
		// set the immediate package now
		Iterator iter = instances.values().iterator();
		while (iter.hasNext()) {
		    RefBaseObjectImpl me = (RefBaseObjectImpl) iter.next();
			me.set___ImmediatePackage(modelPackage);
		}
	}

