package org.eclipse.jst.j2ee.application.internal.operations;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jst.j2ee.datamodel.properties.IEarComponentCreationDataModelProperties;
import org.eclipse.jst.j2ee.datamodel.properties.IJ2EEComponentCreationDataModelProperties;
import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;
import org.eclipse.jst.j2ee.internal.archive.operations.JavaComponentCreationDataModelProvider;
import org.eclipse.jst.j2ee.internal.common.J2EEVersionUtil;
import org.eclipse.jst.j2ee.internal.earcreation.EARCreationResourceHandler;
import org.eclipse.jst.j2ee.internal.earcreation.EarComponentCreationDataModelProvider;
import org.eclipse.jst.j2ee.internal.project.J2EECreationResourceHandler;
import org.eclipse.jst.j2ee.internal.servertarget.ServerTargetHelper;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.datamodel.properties.IComponentCreationDataModelProperties;
import org.eclipse.wst.common.componentcore.internal.StructureEdit;
import org.eclipse.wst.common.componentcore.internal.WorkbenchComponent;
import org.eclipse.wst.common.componentcore.internal.util.IModuleConstants;
import org.eclipse.wst.common.componentcore.resources.ComponentHandle;
import org.eclipse.wst.common.componentcore.resources.IFlexibleProject;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;
import org.eclipse.wst.common.frameworks.datamodel.DataModelEvent;
import org.eclipse.wst.common.frameworks.datamodel.DataModelFactory;
import org.eclipse.wst.common.frameworks.datamodel.DataModelPropertyDescriptor;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.common.frameworks.internal.plugin.WTPCommonMessages;
import org.eclipse.wst.common.frameworks.internal.plugin.WTPCommonPlugin;
import org.eclipse.wst.server.core.IModuleType;
import org.eclipse.wst.server.core.IRuntime;
import org.eclipse.wst.server.core.IRuntimeType;

public abstract class J2EEComponentCreationDataModelProvider extends JavaComponentCreationDataModelProvider implements IJ2EEComponentCreationDataModelProperties, IAnnotationsDataModel {

	private IDataModel earCreationDM = null;
	private static String MODULE_NOT_SUPPORTED = "MODULE_NOT_SUPPORTED";
	private static String MODULEVERSION_NOT_SUPPORTED = "VERSION_NOT_SUPPORTED";
	private static String OK = "OK";

	public void init() {
		super.init();
		model.setProperty(COMPONENT_VERSION, getDefaultProperty(COMPONENT_VERSION));

		IDataModel dm = DataModelFactory.createDataModel(createAddComponentToEAR());
		model.setProperty(NESTED_ADD_COMPONENT_TO_EAR_DM, dm);
		propertySet(CLASSPATH_SELECTION, null);
		model.setProperty(NESTED_UPDATE_MANIFEST_DM, DataModelFactory.createDataModel(UpdateManifestDataModelProvider.class));
		model.setProperty(USE_ANNOTATIONS, Boolean.FALSE);
	}

	public AddComponentToEnterpriseApplicationDataModelProvider createAddComponentToEAR() {
		return new AddComponentToEnterpriseApplicationDataModelProvider();
	}

	public Set getPropertyNames() {
		Set propertyNames = super.getPropertyNames();
		propertyNames.add(EAR_COMPONENT_NAME);
		propertyNames.add(EAR_COMPONENT_DEPLOY_NAME);
		propertyNames.add(ADD_TO_EAR);
		propertyNames.add(UI_SHOW_EAR_SECTION);
		propertyNames.add(DD_FOLDER);
		propertyNames.add(COMPONENT_VERSION);
		propertyNames.add(VALID_COMPONENT_VERSIONS_FOR_PROJECT_RUNTIME);
		propertyNames.add(NESTED_ADD_COMPONENT_TO_EAR_DM);
		propertyNames.add(CLASSPATH_SELECTION);
		propertyNames.add(NESTED_EAR_COMPONENT_CREATION_DM);
		propertyNames.add(NESTED_UPDATE_MANIFEST_DM);
		propertyNames.add(EAR_COMPONENT_HANDLE);
		propertyNames.add(USE_ANNOTATIONS);
		propertyNames.add(EXISTING_PROJECT);
		return propertyNames;
	}

	public Object getDefaultProperty(String propertyName) {
		if (propertyName.equals(ADD_TO_EAR)) {
			return Boolean.FALSE;
		} else if (propertyName.equals(UI_SHOW_EAR_SECTION)) {
			return Boolean.TRUE;
		} else if (propertyName.equals(EAR_COMPONENT_NAME)) {
			return getDataModel().getStringProperty(COMPONENT_NAME) + "EAR";
		} else if (propertyName.equals(COMPONENT_VERSION)) {
			return getDefaultComponentVersion();
		} else if (propertyName.equals(NESTED_EAR_COMPONENT_CREATION_DM))
			return getDefaultEarCreationDM();
		return super.getDefaultProperty(propertyName);
	}

	private Object getDefaultEarCreationDM() {
		if (earCreationDM == null) {
			earCreationDM = DataModelFactory.createDataModel(new EarComponentCreationDataModelProvider());
			setProperty(NESTED_EAR_COMPONENT_CREATION_DM, earCreationDM);
		}
		return earCreationDM;
	}

	public boolean isPropertyEnabled(String propertyName) {
		if (EAR_COMPONENT_NAME.equals(propertyName)) {
			return getBooleanProperty(ADD_TO_EAR);
		} else if (EXISTING_PROJECT.equals(propertyName)) {
			return getBooleanProperty(SUPPORT_MULTIPLE_MODULES);
		}
		return super.isPropertyEnabled(propertyName);
	}


	public boolean propertySet(String propertyName, Object propertyValue) {
		boolean status = super.propertySet(propertyName, propertyValue);
		if (propertyName.equals(EAR_COMPONENT_NAME)) {
			model.setProperty(EAR_COMPONENT_DEPLOY_NAME, propertyValue);
			ComponentHandle handle = computeEARHandle();
			IDataModel earDM = (IDataModel) model.getProperty(NESTED_EAR_COMPONENT_CREATION_DM);
			earDM.setProperty(IJ2EEComponentCreationDataModelProperties.EAR_COMPONENT_HANDLE, handle);
			model.setProperty(EAR_COMPONENT_HANDLE, handle);

		} else if (propertyName.equals(COMPONENT_NAME)) {

			if (getBooleanProperty(ADD_TO_EAR)) {
				if (!model.isPropertySet(EAR_COMPONENT_NAME)) {
					model.notifyPropertyChange(EAR_COMPONENT_NAME, IDataModel.VALID_VALUES_CHG);
					model.setProperty(EAR_COMPONENT_DEPLOY_NAME, getProperty(EAR_COMPONENT_NAME));
					IDataModel earDM = (IDataModel) model.getProperty(NESTED_EAR_COMPONENT_CREATION_DM);
					ComponentHandle handle = computeEARHandle();
					model.setProperty(EAR_COMPONENT_HANDLE, handle);
					if (earDM != null && handle != null)
						earDM.setProperty(IJ2EEComponentCreationDataModelProperties.EAR_COMPONENT_HANDLE, handle);
				}
			}
		} else if (propertyName.equals(ADD_TO_EAR)) {
			model.notifyPropertyChange(EAR_COMPONENT_NAME, IDataModel.ENABLE_CHG);
			model.notifyPropertyChange(NESTED_EAR_COMPONENT_CREATION_DM, IDataModel.DEFAULT_CHG);
			ComponentHandle handle = computeEARHandle();
			model.setProperty(EAR_COMPONENT_HANDLE, handle);
			IDataModel earDM = (IDataModel) model.getProperty(NESTED_EAR_COMPONENT_CREATION_DM);
			if (earDM != null && handle != null) {
				earDM.setProperty(IJ2EEComponentCreationDataModelProperties.EAR_COMPONENT_HANDLE, handle);
				earDM.setProperty(COMPONENT_VERSION, new Integer(getJ2EEVersion()));
			}

		} else if (propertyName.equals(COMPONENT_VERSION)) {
			if (getJ2EEVersion() < J2EEVersionConstants.VERSION_1_3)
				setProperty(USE_ANNOTATIONS, Boolean.FALSE);
			model.notifyPropertyChange(USE_ANNOTATIONS, DataModelEvent.ENABLE_CHG);
			model.notifyPropertyChange(EAR_COMPONENT_NAME, DataModelEvent.VALID_VALUES_CHG);
			if (getBooleanProperty(ADD_TO_EAR)) {
				IDataModel earDM = (IDataModel) model.getProperty(NESTED_EAR_COMPONENT_CREATION_DM);
				earDM.setProperty(COMPONENT_VERSION, new Integer(getJ2EEVersion()));
			}
			// this will force to reload all the server types which are valid for this component
			// version
			if (!model.getBooleanProperty(SUPPORT_MULTIPLE_MODULES)) {
				model.notifyPropertyChange(RUNTIME_TARGET_ID, DataModelEvent.VALID_VALUES_CHG);
			}
		} else if (RUNTIME_TARGET_ID.equals(propertyName)) {
			setProperty(ADD_TO_EAR, new Boolean(isEARSupported()));

			IDataModel earDM = (IDataModel) model.getProperty(NESTED_EAR_COMPONENT_CREATION_DM);
			earDM.setProperty(RUNTIME_TARGET_ID, propertyValue);
		} else if (propertyName.equals(SUPPORT_MULTIPLE_MODULES)) {
			model.notifyPropertyChange(EXISTING_PROJECT, IDataModel.ENABLE_CHG);
		}
		return status;
	}

	protected ComponentHandle computeEARHandle() {
		String earProjname = (String) model.getProperty(EAR_COMPONENT_NAME);

		IDataModel earDM = (IDataModel) model.getProperty(NESTED_EAR_COMPONENT_CREATION_DM);
		earDM.setProperty(IEarComponentCreationDataModelProperties.PROJECT_NAME, earProjname);

		ComponentHandle handle = null;

		if (earProjname != null && !earProjname.equals("") && validate(EAR_COMPONENT_NAME).isOK()) {
			handle = ComponentHandle.create(ProjectUtilities.getProject(earProjname), earProjname);
		}
		return handle;
	}


	public DataModelPropertyDescriptor[] getValidPropertyDescriptors(String propertyName) {
		if (propertyName.equals(COMPONENT_VERSION)) {
			return getValidComponentVersionDescriptors();
		}
		if (propertyName.equals(EAR_COMPONENT_NAME)) {
			int j2eeVersion = getJ2EEVersion();
			return getEARPropertyDescriptor(j2eeVersion);
		} else if (propertyName.equals(RUNTIME_TARGET_ID)) {
			return validJ2EEServerPropertyDescriptors();
		} else if (propertyName.equals(EXISTING_PROJECT)) {
			return validExistingProjectsDescriptors();
		}
		return super.getValidPropertyDescriptors(propertyName);
	}

	protected String isvalidJComponentVersionsSupportedByServer() {
		String serverID = model.getStringProperty(RUNTIME_TARGET_ID);
		IRuntime runtime = getServerTargetByID(serverID);

		if (serverID.equals("") || runtime == null) {
			return MODULEVERSION_NOT_SUPPORTED;
		}
		Integer version = (Integer) model.getProperty(COMPONENT_VERSION);
		int nj2eeVer = convertModuleVersionToJ2EEVersion(version.intValue());
		String j2eeVer = J2EEVersionUtil.getJ2EETextVersion(nj2eeVer);
		return isTypeSupported(runtime.getRuntimeType(), getComponentID(), j2eeVer);
	}

	protected DataModelPropertyDescriptor[] validJ2EEServerPropertyDescriptors() {

		Integer version = (Integer) model.getProperty(COMPONENT_VERSION);
		int j2eeversion = convertModuleVersionToJ2EEVersion(version.intValue());
		String j2eeVersionText = J2EEVersionUtil.getJ2EETextVersion(j2eeversion);

		ArrayList validServers = new ArrayList();

		IDataModel projectdm = model.getNestedModel(NESTED_PROJECT_CREATION_DM);
		DataModelPropertyDescriptor[] desc = projectdm.getValidPropertyDescriptors(RUNTIME_TARGET_ID);
		for (int i = 0; i < desc.length; i++) {
			DataModelPropertyDescriptor descriptor = desc[i];
			String name = descriptor.getPropertyDescription();
			String runtimeid = (String) descriptor.getPropertyValue();
			IRuntime runtime = getServerTargetByID(runtimeid);
			String ok = isTypeSupported(runtime.getRuntimeType(), getComponentID(), j2eeVersionText);
			if (ok.equals("OK"))
				validServers.add(descriptor);
		}

		if (!validServers.isEmpty()) {
			int serverTargetListSize = validServers.size();
			DataModelPropertyDescriptor[] result = new DataModelPropertyDescriptor[serverTargetListSize];
			for (int i = 0; i < validServers.size(); i++) {
				result[i] = (DataModelPropertyDescriptor) validServers.get(i);
			}
			return result;
		}
		return new DataModelPropertyDescriptor[0];
	}

	protected IRuntime getServerTargetByID(String id) {
		List targets = getValidServerTargets();
		IRuntime target;
		for (int i = 0; i < targets.size(); i++) {
			target = (IRuntime) targets.get(i);
			if (id.equals(target.getId()))
				return target;
		}
		return null;
	}

	private List getValidServerTargets() {
		List validServerTargets = null;
		validServerTargets = ServerTargetHelper.getServerTargets("", ""); //$NON-NLS-1$  //$NON-NLS-2$
		if (validServerTargets != null && validServerTargets.isEmpty())
			validServerTargets = null;
		if (validServerTargets == null)
			return Collections.EMPTY_LIST;
		return validServerTargets;
	}


	protected String isTypeSupported(IRuntimeType type, String moduleID, String j2eeVersion) {
		IModuleType[] moduleTypes = type.getModuleTypes();

		boolean moduleFound = false;
		boolean moduleVersionFound = false;

		if (moduleTypes != null) {
			int size = moduleTypes.length;

			for (int i = 0; i < size; i++) {
				IModuleType moduleType = moduleTypes[i];

				if (matches(moduleType.getId(), moduleID)) {
					moduleFound = true;
					String version = moduleType.getVersion();
					if (version.equals(j2eeVersion) || version.equals("*")) {
						moduleVersionFound = true;
						return OK;
					} else {
						if (i < size)
							continue;
					}
				}
			}
		}
		if (!moduleFound) {
			return MODULE_NOT_SUPPORTED;
		} else {
			if (!moduleVersionFound)
				return MODULEVERSION_NOT_SUPPORTED;
		}

		return "";
	}


	protected static String[] getServerVersions(IRuntimeType type, String moduleID) {
		List list = new ArrayList();
		if (type == null)
			return null;
		IModuleType[] moduleTypes = type.getModuleTypes();
		if (moduleTypes != null) {
			int size = moduleTypes.length;
			for (int i = 0; i < size; i++) {
				IModuleType moduleType = moduleTypes[i];
				if (matches(moduleType.getId(), moduleID)) {
					list.add(moduleType.getVersion());
				}

			}
		}
		String[] versions = null;
		if (!list.isEmpty()) {
			versions = new String[list.size()];
			list.toArray(versions);
		}
		return versions;
	}

	protected static boolean matches(String serverTypeID, String j2eeModuleID) {

		if (serverTypeID.equals("j2ee")) {
			if (j2eeModuleID.equals(IModuleConstants.JST_WEB_MODULE) || j2eeModuleID.equals(IModuleConstants.JST_EJB_MODULE) || j2eeModuleID.equals(IModuleConstants.JST_EAR_MODULE) || j2eeModuleID.equals(IModuleConstants.JST_APPCLIENT_MODULE) || j2eeModuleID.equals(IModuleConstants.JST_CONNECTOR_MODULE)) {
				return true;
			}
		} else if (serverTypeID.equals("j2ee.*")) {
			if (j2eeModuleID.equals(IModuleConstants.JST_WEB_MODULE) || j2eeModuleID.equals(IModuleConstants.JST_EJB_MODULE) || j2eeModuleID.equals(IModuleConstants.JST_EAR_MODULE) || j2eeModuleID.equals(IModuleConstants.JST_APPCLIENT_MODULE) || j2eeModuleID.equals(IModuleConstants.JST_CONNECTOR_MODULE)) {
				return true;
			}
		} else if (serverTypeID.equals("j2ee.web")) {//$NON-NLS-1$
			if (j2eeModuleID.equals(IModuleConstants.JST_WEB_MODULE)) {
				return true;
			}
		} else if (serverTypeID.equals("j2ee.ejb")) {//$NON-NLS-1$
			if (j2eeModuleID.equals(IModuleConstants.JST_EJB_MODULE)) {
				return true;
			}
		} else if (serverTypeID.equals("j2ee.ear")) {//$NON-NLS-1$
			if (j2eeModuleID.equals(IModuleConstants.JST_EAR_MODULE) || j2eeModuleID.equals(IModuleConstants.JST_APPCLIENT_MODULE) || j2eeModuleID.equals(IModuleConstants.JST_CONNECTOR_MODULE)) {
				return true;
			}
		}
		return false;
	}



	private DataModelPropertyDescriptor[] getEARPropertyDescriptor(int j2eeVersion) {
		StructureEdit mc = null;
		ArrayList earDescriptorList = new ArrayList();

		IProject[] projs = ProjectUtilities.getAllProjects();

		for (int index = 0; index < projs.length; index++) {
			IProject flexProject = projs[index];
			try {
				if (flexProject != null) {
					IFlexibleProject fProject = ComponentCore.createFlexibleProject(flexProject);
					if (fProject.isFlexible()) {
						IVirtualComponent[] comps = fProject.getComponents();
						int earVersion = 0;
						for (int i = 0; i < comps.length; i++) {
							if (comps[i].getComponentTypeId().equals(IModuleConstants.JST_EAR_MODULE)) {
								String sVer = comps[i].getVersion();
								int ver = J2EEVersionUtil.convertVersionStringToInt(sVer);
								if (j2eeVersion <= ver) {
									DataModelPropertyDescriptor desc = new DataModelPropertyDescriptor(comps[i].getComponentHandle(), comps[i].getName());
									earDescriptorList.add(desc);
								}
							}
						}
					}
				}
			} finally {
				if (mc != null)
					mc.dispose();
			}
		}
		DataModelPropertyDescriptor[] descriptors = new DataModelPropertyDescriptor[earDescriptorList.size()];
		for (int i = 0; i < descriptors.length; i++) {
			DataModelPropertyDescriptor desc = (DataModelPropertyDescriptor) earDescriptorList.get(i);
			descriptors[i] = new DataModelPropertyDescriptor(desc.getPropertyDescription(), desc.getPropertyDescription());
		}
		return descriptors;
	}



	public IProject getProject() {
		String projName = getDataModel().getStringProperty(IComponentCreationDataModelProperties.PROJECT_NAME);
		if (projName != null && projName.length() > 0)
			return ProjectUtilities.getProject(projName);
		return null;
	}

	public WorkbenchComponent getTargetWorkbenchComponent() {
		StructureEdit core = null;
		try {
			IProject flexProject = getProject();
			if (flexProject != null) {
				core = StructureEdit.getStructureEditForRead(getProject());
				if (core != null) {
					String componentName = getProperty(COMPONENT_NAME) != null ? getProperty(COMPONENT_NAME).toString() : null;
					if (componentName != null)
						return core.findComponentByName(componentName);
				}
			}
		} finally {
			if (core != null)
				core.dispose();
		}
		return null;
	}

	protected boolean isEARSupported() {
		if (this instanceof EarComponentCreationDataModelProvider)
			return false;
		String serverID = model.getStringProperty(RUNTIME_TARGET_ID);
		IRuntime runtime = getServerTargetByID(serverID);
		Integer version = (Integer) model.getProperty(COMPONENT_VERSION);
		int nj2eeVer = convertModuleVersionToJ2EEVersion(version.intValue());
		String j2eeVer = J2EEVersionUtil.getJ2EETextVersion(nj2eeVer);

		if (runtime != null) {
			String msg = isTypeSupported(runtime.getRuntimeType(), IModuleConstants.JST_EAR_MODULE, j2eeVer);
			if (msg.equals(OK)) {
				return true;
			}
		}
		return false;
	}

	protected boolean validateComponentAlreadyInEar() {
		IVirtualComponent component = ComponentCore.createComponent(getProject(), getModuleName());

		ComponentHandle earHandle = (ComponentHandle) model.getProperty(EAR_COMPONENT_HANDLE);
		if (earHandle != null && earHandle.getProject() != null && earHandle.getProject().exists()) {
			IVirtualComponent earComp = ComponentCore.createComponent(earHandle.getProject(), earHandle.getName());
			if (earComp != null && earComp.exists()) {
				IVirtualReference[] refs = earComp.getReferences();
				for (int i = 0; i < refs.length; i++) {
					IVirtualReference ref = refs[i];
					IVirtualComponent referencedComp = ref.getReferencedComponent();
					if (referencedComp.getName().equalsIgnoreCase(component.getName()))
						return true;
				}
			}
		}
		return false;
	}

	public IStatus validate(String propertyName) {
		if (EAR_COMPONENT_NAME.equals(propertyName) && getBooleanProperty(ADD_TO_EAR)) {
			return validateEARModuleNameProperty();
		} else if (COMPONENT_VERSION.equals(propertyName)) {
			return validateComponentVersionProperty();
		} else if (propertyName.equals(VALID_COMPONENT_VERSIONS_FOR_PROJECT_RUNTIME)) {
			return OK_STATUS;
		} else if (propertyName.equals(ADD_TO_EAR)) {
			boolean val = getBooleanProperty(ADD_TO_EAR);
			if (val) {
				String serverID = model.getStringProperty(RUNTIME_TARGET_ID);
				IRuntime runtime = getServerTargetByID(serverID);
				if (serverID.equals("") || runtime == null) {
					String msg = EARCreationResourceHandler.getString(EARCreationResourceHandler.SERVER_TARGET_NOT_SUPPORT_EAR);
					return WTPCommonPlugin.createErrorStatus(msg);
				}
				Integer version = (Integer) model.getProperty(COMPONENT_VERSION);
				int nj2eeVer = convertModuleVersionToJ2EEVersion(version.intValue());
				String j2eeVer = J2EEVersionUtil.getJ2EETextVersion(nj2eeVer);
				String msg = isTypeSupported(runtime.getRuntimeType(), IModuleConstants.JST_EAR_MODULE, j2eeVer);
				if (!msg.equals(OK)) {
					msg = EARCreationResourceHandler.getString(EARCreationResourceHandler.SERVER_TARGET_NOT_SUPPORT_EAR);
					return WTPCommonPlugin.createErrorStatus(msg);
				} else {
					if (validateComponentAlreadyInEar()) {
						msg = J2EECreationResourceHandler.getString("COMPONENT_ALREADYINEAR"); //$NON-NLS-1$
						return WTPCommonPlugin.createErrorStatus(msg);
					}
				}
			}
		} else if (propertyName.equals(PROJECT_NAME)) {
			if (!isCreatingEarComponent()) {
				String projName = getDataModel().getStringProperty(IComponentCreationDataModelProperties.PROJECT_NAME);
				IDataModel earDM = (IDataModel) model.getProperty(NESTED_EAR_COMPONENT_CREATION_DM);
				ComponentHandle earHandle = (ComponentHandle) earDM.getProperty(EAR_COMPONENT_HANDLE);
				if (earHandle != null && earHandle.getProject() != null) {
					String earProjName = earHandle.getProject().getName();
					if (earProjName.equalsIgnoreCase(projName)) {
						String msg = msg = EARCreationResourceHandler.getString(EARCreationResourceHandler.EAR_PROJECTNAME_SAMEAS_MODULE);
						return WTPCommonPlugin.createErrorStatus(msg);
					}
				}
			}
		}
		return super.validate(propertyName);
	}

	protected boolean isCreatingEarComponent() {
		return false;
	}

	private IStatus validateComponentVersionProperty() {
		int componentVersion = model.getIntProperty(COMPONENT_VERSION);
		String result = isvalidJComponentVersionsSupportedByServer();
		if (result.equals(MODULEVERSION_NOT_SUPPORTED)) {
			return WTPCommonPlugin.createErrorStatus(WTPCommonPlugin.getResourceString(WTPCommonMessages.SPEC_LEVEL_NOT_FOUND));
		} else if (result.equals(MODULE_NOT_SUPPORTED)) {
			return WTPCommonPlugin.createErrorStatus(WTPCommonPlugin.getResourceString(WTPCommonMessages.MODULE_NOT_SUPPORTED));
		}
		if (componentVersion == -1)
			return WTPCommonPlugin.createErrorStatus(WTPCommonPlugin.getResourceString(WTPCommonMessages.SPEC_LEVEL_NOT_FOUND));
		return OK_STATUS;
	}

	private IStatus validateEARModuleNameProperty() {
		IStatus status = OK_STATUS;
		String earName = getStringProperty(EAR_COMPONENT_NAME);
		if (status.isOK()) {
			if (earName.indexOf("#") != -1 || earName.indexOf("/") != -1) { //$NON-NLS-1$
				String errorMessage = WTPCommonPlugin.getResourceString(WTPCommonMessages.ERR_INVALID_CHARS); //$NON-NLS-1$
				return WTPCommonPlugin.createErrorStatus(errorMessage);
			} else if (earName == null || earName.equals("")) { //$NON-NLS-1$
				String errorMessage = WTPCommonPlugin.getResourceString(WTPCommonMessages.ERR_EMPTY_MODULE_NAME);
				return WTPCommonPlugin.createErrorStatus(errorMessage);
			}
		} else
			return status;
		// IProject earProject =
		// applicationCreationDataModel.getTargetProject();
		// if (null != earProject && earProject.exists()) {
		// if (earProject.isOpen()) {
		// try {
		// EARNatureRuntime earNature = (EARNatureRuntime)
		// earProject.getNature(IEARNatureConstants.NATURE_ID);
		// if (earNature == null) {
		// return
		// WTPCommonPlugin.createErrorStatus(WTPCommonPlugin.getResourceString(WTPCommonMessages.PROJECT_NOT_EAR,
		// new Object[]{earProject.getName()}));
		// } else if (earNature.getJ2EEVersion() < getJ2EEVersion()) {
		// String earVersion =
		// EnterpriseApplicationCreationDataModel.getVersionString(earNature.getJ2EEVersion());
		// return
		// WTPCommonPlugin.createErrorStatus(WTPCommonPlugin.getResourceString(WTPCommonMessages.INCOMPATABLE_J2EE_VERSIONS,
		// new Object[]{earProject.getName(), earVersion}));
		// }
		// return OK_STATUS;
		// } catch (CoreException e) {
		// return new Status(IStatus.ERROR, J2EEPlugin.PLUGIN_ID, -1, null, e);
		// }
		// }
		// return
		// WTPCommonPlugin.createErrorStatus(WTPCommonPlugin.getResourceString(WTPCommonMessages.PROJECT_ClOSED,
		// new Object[]{earProject.getName()}));
		// } else if (null != earProject && null != getTargetProject()) {
		// if (earProject.getName().equals(getTargetProject().getName())) {
		// return
		// WTPCommonPlugin.createErrorStatus(WTPCommonPlugin.getResourceString(WTPCommonMessages.SAME_MODULE_AND_EAR_NAME,
		// new Object[]{earProject.getName()}));
		// } else if (!CoreFileSystemLibrary.isCaseSensitive()) {
		// if
		// (earProject.getName().toLowerCase().equals(getTargetProject().getName().toLowerCase()))
		// {
		// return
		// WTPCommonPlugin.createErrorStatus(WTPCommonPlugin.getResourceString(WTPCommonMessages.SAME_MODULE_AND_EAR_NAME,
		// new Object[]{earProject.getName()}));
		// }
		// }
		// }
		// IStatus status =
		// applicationCreationDataModel.validateProperty(EnterpriseApplicationCreationDataModel.PROJECT_NAME);
		// if (status.isOK()) {
		// status =
		// applicationCreationDataModel.validateProperty(EnterpriseApplicationCreationDataModel.PROJECT_LOCATION);
		// }
		// return status;

		return WTPCommonPlugin.OK_STATUS;
	}

	public final ClassPathSelection getClassPathSelection() {
		// boolean createNew = false;
		// if (null == cachedSelection ||
		// !getApplicationCreationDataModel().getTargetProject().getName().equals(cachedSelection.getEARFile().getURI()))
		// {
		// createNew = true;
		// }
		// // close an existing cachedSelection
		// if (createNew && cachedSelection != null) {
		// EARFile earFile = cachedSelection.getEARFile();
		// if (earFile != null)
		// earFile.close();
		// }
		//
		// if (createNew && getTargetProject() != null) {
		// cachedSelection =
		// ClasspathSelectionHelper.createClasspathSelection(getTargetProject(),
		// getModuleExtension(),
		// getApplicationCreationDataModel().getTargetProject(),
		// getModuleType());
		// }
		// return cachedSelection;
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.wst.common.frameworks.internal.operation.WTPOperationDataModel#dispose()
	 */
	public void dispose() {
		super.dispose();
	}

	// public void propertyChanged(WTPOperationDataModelEvent event) {
	// super.propertyChanged(event);
	// if (event.getDataModel() == addComponentToEARDataModel && event.getFlag()
	// == WTPOperationDataModelEvent.PROPERTY_CHG &&
	// event.getPropertyName().equals(ArtifactEditOperationDataModel.PROJECT_NAME))
	// {
	// earComponentCreationDataModel.setProperty(EARComponentCreationDataModel.COMPONENT_NAME,
	// event.getProperty());
	// }
	// }
	protected final IDataModel getAddComponentToEARDataModel() {
		// return (AddComponentToEnterpriseApplicationDataModel)
		// model.getProperty(NESTED_ADD_COMPONENT_TO_EAR_DM);
		return (IDataModel) model.getProperty(NESTED_ADD_COMPONENT_TO_EAR_DM);
	}

	protected final IDataModel getUpdateManifestDataModel() {
		return (IDataModel) model.getProperty(NESTED_UPDATE_MANIFEST_DM);
	}

	public String getModuleName() {
		return getDataModel().getStringProperty(COMPONENT_NAME);
	}

	public final int getJ2EEVersion() {
		return convertModuleVersionToJ2EEVersion(getIntProperty(COMPONENT_VERSION));
	}

	/**
	 * Subclasses should override to convert the j2eeVersion to a module version id. By default we
	 * return the j2eeVersion which is fine if no conversion is necessary.
	 * 
	 * @param integer
	 * @return
	 */
	protected Integer convertJ2EEVersionToModuleVersion(Integer j2eeVersion) {
		return j2eeVersion;
	}

	protected abstract int convertModuleVersionToJ2EEVersion(int moduleVersion);

	protected abstract DataModelPropertyDescriptor[] getValidComponentVersionDescriptors();


	private DataModelPropertyDescriptor[] validExistingProjectsDescriptors() {

		IProject[] workspaceProjects = ProjectUtilities.getAllProjects();
		List items = new ArrayList();
		for (int i = 0; i < workspaceProjects.length; i++) {
			IProject project = workspaceProjects[i];
			try {
				if (project.hasNature(IModuleConstants.MODULE_NATURE_ID)) {
					items.add(project.getName());
				}
			} catch (CoreException ce) {
				// Ignore
			}
		}

		DataModelPropertyDescriptor[] descriptors = new DataModelPropertyDescriptor[items.size()];
		for (int i = 0; i < descriptors.length; i++) {
			descriptors[i] = new DataModelPropertyDescriptor(items.get(i));
		}
		return descriptors;


		// StructureEdit mc = null;
		// ArrayList earDescriptorList = new ArrayList();
		//
		// IProject[] projs = ProjectUtilities.getAllProjects();
		//
		// for (int index = 0; index < projs.length; index++) {
		// IProject flexProject = projs[index];
		// try {
		// if (flexProject != null) {
		// IFlexibleProject fProject = ComponentCore.createFlexibleProject(flexProject);
		// if ( fProject.isFlexible()){
		// IVirtualComponent[] comps = fProject.getComponents();
		// int earVersion = 0;
		// for( int i=0; i< comps.length; i++ ){
		// if( comps[i].getComponentTypeId().equals(IModuleConstants.JST_EAR_MODULE)){
		// String sVer = comps[i].getVersion();
		// int ver = J2EEVersionUtil.convertVersionStringToInt(sVer);
		// if (j2eeVersion <= ver) {
		// DataModelPropertyDescriptor desc = new
		// DataModelPropertyDescriptor(comps[i].getComponentHandle(), comps[i].getName());
		// earDescriptorList.add(desc);
		// }
		// }
		// }
		// }
		// }
		// } finally {
		// if (mc != null)
		// mc.dispose();
		// }
		// }
		// DataModelPropertyDescriptor[] descriptors = new
		// DataModelPropertyDescriptor[earDescriptorList.size()];
		// for (int i = 0; i < descriptors.length; i++) {
		// DataModelPropertyDescriptor desc = (DataModelPropertyDescriptor)earDescriptorList.get(i);
		// descriptors[i] = new DataModelPropertyDescriptor(desc.getPropertyDescription(),
		// desc.getPropertyDescription());
		// }
		// return descriptors;


	}
}