/*******************************************************************************
 * Copyright (c) 2006, 2009 Oracle. 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:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.core.internal.facet;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jpt.core.JptCorePlugin;
import org.eclipse.jpt.core.internal.JptCoreMessages;
import org.eclipse.jpt.core.internal.platform.JpaPlatformRegistry;
import org.eclipse.jpt.db.Catalog;
import org.eclipse.jpt.db.ConnectionProfile;
import org.eclipse.jpt.db.ConnectionProfileFactory;
import org.eclipse.jpt.db.Database;
import org.eclipse.jpt.db.DatabaseFinder;
import org.eclipse.jpt.db.JptDbPlugin;
import org.eclipse.jpt.db.Schema;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.iterators.CompositeIterator;
import org.eclipse.jpt.utility.internal.iterators.EmptyIterator;
import org.eclipse.jpt.utility.internal.iterators.TransformationIterator;
import org.eclipse.jst.common.project.facet.core.libprov.IPropertyChangeListener;
import org.eclipse.jst.common.project.facet.core.libprov.LibraryInstallDelegate;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.componentcore.datamodel.FacetInstallDataModelProvider;
import org.eclipse.wst.common.componentcore.internal.util.IModuleConstants;
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.common.project.facet.core.IFacetedProjectWorkingCopy;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntime;

public class JpaFacetDataModelProvider extends FacetInstallDataModelProvider
	implements JpaFacetDataModelProperties
{
	private static final String EJB_FACET_ID = IModuleConstants.JST_EJB_MODULE;

	private static final String RUNTIME_NONE = 
			WTPCommonPlugin.getResourceString(WTPCommonMessages.RUNTIME_NONE, null);
	
	private static final IStatus PLATFORM_NOT_SPECIFIED_STATUS = 
			buildErrorStatus(JptCoreMessages.VALIDATE_PLATFORM_NOT_SPECIFIED);
	
	private static final IStatus CONNECTION_NOT_CONNECTED_STATUS = 
			buildInfoStatus(JptCoreMessages.VALIDATE_CONNECTION_NOT_CONNECTED);
	
	private static final IStatus USER_OVERRIDE_DEFAULT_CATALOG_NOT_SPECIFIED_STATUS = 
		buildErrorStatus(JptCoreMessages.VALIDATE_DEFAULT_CATALOG_NOT_SPECIFIED);
	
	private static final IStatus USER_OVERRIDE_DEFAULT_SCHEMA_NOT_SPECIFIED_STATUS = 
			buildErrorStatus(JptCoreMessages.VALIDATE_DEFAULT_SCHEMA_NOT_SPECIFIED);
	
	private static final IStatus RUNTIME_NOT_SPECIFIED_STATUS = 
			buildWarningStatus(JptCoreMessages.VALIDATE_RUNTIME_NOT_SPECIFIED);
	
	private static final IStatus RUNTIME_DOES_NOT_SUPPORT_EJB_30_STATUS = 
			buildWarningStatus(JptCoreMessages.VALIDATE_RUNTIME_DOES_NOT_SUPPORT_EJB_30);
	
	
	private LibraryInstallDelegate defaultLibraryProvider;
	
	
	/**
	 * required default constructor
	 */
	public JpaFacetDataModelProvider() {
		super();
	}
	
	
	@Override
	public Set<String> getPropertyNames() {
		@SuppressWarnings("unchecked") Set<String> propertyNames = super.getPropertyNames();
		propertyNames.add(RUNTIME);
		propertyNames.add(PLATFORM_ID);
		propertyNames.add(LIBRARY_PROVIDER_DELEGATE);
		propertyNames.add(CONNECTION);
		propertyNames.add(CONNECTION_ACTIVE);
		propertyNames.add(USER_WANTS_TO_ADD_DB_DRIVER_JARS_TO_CLASSPATH);
		propertyNames.add(DB_DRIVER_NAME);
		propertyNames.add(USER_WANTS_TO_OVERRIDE_DEFAULT_CATALOG);
		propertyNames.add(USER_OVERRIDE_DEFAULT_CATALOG);
		propertyNames.add(USER_WANTS_TO_OVERRIDE_DEFAULT_SCHEMA);
		propertyNames.add(USER_OVERRIDE_DEFAULT_SCHEMA);
		propertyNames.add(DISCOVER_ANNOTATED_CLASSES);
		propertyNames.add(LIST_ANNOTATED_CLASSES);
		propertyNames.add(CREATE_ORM_XML);
		return propertyNames;
	}
	
	@Override
	public boolean isPropertyEnabled(String propertyName) {
		if (propertyName.equals(USER_OVERRIDE_DEFAULT_CATALOG)) {
			return getBooleanProperty(USER_WANTS_TO_OVERRIDE_DEFAULT_CATALOG);
		}
		if (propertyName.equals(USER_OVERRIDE_DEFAULT_SCHEMA)) {
			return getBooleanProperty(USER_WANTS_TO_OVERRIDE_DEFAULT_SCHEMA);
		}
		if (propertyName.equals(USER_WANTS_TO_ADD_DB_DRIVER_JARS_TO_CLASSPATH)) {
			return getConnectionProfile() != null;
		}
		if (propertyName.equals(DB_DRIVER_NAME)) {
			return getBooleanProperty(USER_WANTS_TO_ADD_DB_DRIVER_JARS_TO_CLASSPATH);
		}
		return super.isPropertyEnabled(propertyName);
	}
	
	@Override
	public Object getDefaultProperty(String propertyName) {
		if (propertyName.equals(RUNTIME)) {
			return null;
		}
		if (propertyName.equals(FACET_ID)) {
			return JptCorePlugin.FACET_ID;
		}
		if (propertyName.equals(PLATFORM_ID)) {
			return JptCorePlugin.getDefaultJpaPlatformId();
		}
		if (propertyName.equals(LIBRARY_PROVIDER_DELEGATE)) {
			return getDefaultLibraryProvider();
		}
		if (propertyName.equals(CONNECTION)) {
			return null;
		}
		if (propertyName.equals(CONNECTION_ACTIVE)) {
			return Boolean.valueOf(connectionIsActive());
		}
		if (propertyName.equals(USER_WANTS_TO_ADD_DB_DRIVER_JARS_TO_CLASSPATH)) {
			return Boolean.FALSE;
		}
		if (propertyName.equals(DB_DRIVER_NAME)) {
			return getDefaultDriverName();
		}
		if (propertyName.equals(USER_WANTS_TO_OVERRIDE_DEFAULT_CATALOG)) {
			return Boolean.FALSE;
		}
		if (propertyName.equals(USER_OVERRIDE_DEFAULT_CATALOG)) {
			return getDefaultCatalogName();
		}
		if (propertyName.equals(USER_WANTS_TO_OVERRIDE_DEFAULT_SCHEMA)) {
			return Boolean.FALSE;
		}
		if (propertyName.equals(USER_OVERRIDE_DEFAULT_SCHEMA)) {
			return getDefaultSchemaName();
		}
		if (propertyName.equals(DISCOVER_ANNOTATED_CLASSES)) {
			return Boolean.valueOf(this.runtimeSupportsEjb30(this.runtime()));
		}
		if (propertyName.equals(LIST_ANNOTATED_CLASSES)) {
			return Boolean.valueOf( ! getBooleanProperty(DISCOVER_ANNOTATED_CLASSES));
		}
		if (propertyName.equals(CREATE_ORM_XML)) {
			return Boolean.TRUE;
		}
		
		return super.getDefaultProperty(propertyName);
	}
	
	private String getDefaultDriverName() {
		ConnectionProfile cp = this.getConnectionProfile();
		if (cp == null) {
			return null;
		}
		return cp.getDriverName();
	}

	private String getDefaultCatalogName() {
		ConnectionProfile cp = this.getConnectionProfile();
		if (cp == null) {
			return null;
		}
		Database db = cp.getDatabase();
		if (db == null) {
			return null;
		}
		Catalog catalog = db.getDefaultCatalog();
		return (catalog == null) ? null : catalog.getIdentifier();
	}

	private String getDefaultSchemaName() {
		ConnectionProfile cp = this.getConnectionProfile();
		if (cp == null) {
			return null;
		}
		Database db = cp.getDatabase();
		if (db == null) {
			return null;
		}
		Schema schema = db.getDefaultSchema();
		return (schema == null) ? null : schema.getIdentifier();
	}
	
	private LibraryInstallDelegate getDefaultLibraryProvider() {
		// delegate itself changes, not the instance of delegate
		if (defaultLibraryProvider == null) {
			IFacetedProjectWorkingCopy fpjwc = (IFacetedProjectWorkingCopy) getProperty(FACETED_PROJECT_WORKING_COPY);
			IProjectFacetVersion fv = (IProjectFacetVersion) getProperty(FACET_VERSION);
			if (fpjwc != null && fv != null ) {
				Map<String, Object> enablementVariables = new HashMap<String, Object>();
				enablementVariables.put(
					JpaLibraryProviderConstants.EXPR_VAR_JPA_PLATFORM, 
					getPlatformId());	
				defaultLibraryProvider = new LibraryInstallDelegate(fpjwc, fv, enablementVariables);
				defaultLibraryProvider.addListener( 
					new IPropertyChangeListener() {
						public void propertyChanged(final String property, final Object oldValue, final Object newValue ) {
							JpaFacetDataModelProvider.this.model.notifyPropertyChange(LIBRARY_PROVIDER_DELEGATE, IDataModel.VALUE_CHG);
						}
					});
			}
		}
		return defaultLibraryProvider;
	}
	
	@Override
	public boolean propertySet(String propertyName, Object propertyValue) {
		boolean ok = super.propertySet(propertyName, propertyValue);
		
		if (propertyName.equals(FACETED_PROJECT_WORKING_COPY)) {
			//no-op
		}
		if( propertyName.equals(FACET_VERSION)){
			this.model.notifyPropertyChange(LIBRARY_PROVIDER_DELEGATE, IDataModel.DEFAULT_CHG);
		}
		if (propertyName.equals(RUNTIME)) {
			LibraryInstallDelegate lid = getLibraryInstallDelegate();
			if (lid != null) {
				// may be null while model is being built up
				// ... or in tests
				lid.refresh();
			}
			this.model.notifyPropertyChange(DISCOVER_ANNOTATED_CLASSES, IDataModel.DEFAULT_CHG);
			this.model.notifyPropertyChange(LIST_ANNOTATED_CLASSES, IDataModel.DEFAULT_CHG);
		}
		if (propertyName.equals(PLATFORM_ID)) {
			LibraryInstallDelegate lid = getLibraryInstallDelegate();
			if (lid != null) {
				// may be null while model is being built up
				// ... or in tests
				lid.setEnablementContextVariable(
					JpaLibraryProviderConstants.EXPR_VAR_JPA_PLATFORM,
					(String) propertyValue);
			}
		}
		if (propertyName.equals(CONNECTION)) {
			this.model.notifyPropertyChange(CONNECTION, IDataModel.VALID_VALUES_CHG);
			this.model.setBooleanProperty(CONNECTION_ACTIVE, connectionIsActive());
			this.model.notifyPropertyChange(DB_DRIVER_NAME, IDataModel.DEFAULT_CHG);
			this.model.notifyPropertyChange(DB_DRIVER_NAME, IDataModel.VALID_VALUES_CHG);
			this.model.notifyPropertyChange(USER_OVERRIDE_DEFAULT_CATALOG, IDataModel.DEFAULT_CHG);
			this.model.notifyPropertyChange(USER_OVERRIDE_DEFAULT_CATALOG, IDataModel.VALID_VALUES_CHG);
			this.model.notifyPropertyChange(USER_OVERRIDE_DEFAULT_SCHEMA, IDataModel.DEFAULT_CHG);
			this.model.notifyPropertyChange(USER_OVERRIDE_DEFAULT_SCHEMA, IDataModel.VALID_VALUES_CHG);
		}
		if (propertyName.equals(CONNECTION_ACTIVE)) {
			this.model.notifyPropertyChange(USER_OVERRIDE_DEFAULT_CATALOG, IDataModel.DEFAULT_CHG);
			this.model.notifyPropertyChange(USER_OVERRIDE_DEFAULT_CATALOG, IDataModel.VALID_VALUES_CHG);
			this.model.notifyPropertyChange(USER_OVERRIDE_DEFAULT_SCHEMA, IDataModel.DEFAULT_CHG);
			this.model.notifyPropertyChange(USER_OVERRIDE_DEFAULT_SCHEMA, IDataModel.VALID_VALUES_CHG);
			this.model.notifyPropertyChange(USER_WANTS_TO_ADD_DB_DRIVER_JARS_TO_CLASSPATH, IDataModel.ENABLE_CHG);
			this.model.notifyPropertyChange(DB_DRIVER_NAME, IDataModel.ENABLE_CHG);
		}
		if (propertyName.equals(USER_WANTS_TO_ADD_DB_DRIVER_JARS_TO_CLASSPATH)) {
			this.model.notifyPropertyChange(DB_DRIVER_NAME, IDataModel.ENABLE_CHG);
			if (! ((Boolean) propertyValue).booleanValue()) {
				this.model.setProperty(DB_DRIVER_NAME, null);
			}
		}
		if (propertyName.equals(USER_WANTS_TO_OVERRIDE_DEFAULT_CATALOG)) {
			this.model.notifyPropertyChange(USER_OVERRIDE_DEFAULT_CATALOG, IDataModel.ENABLE_CHG);
			if (! ((Boolean) propertyValue).booleanValue()) {
				this.model.setProperty(USER_OVERRIDE_DEFAULT_CATALOG, null);
			}
		}
		if (propertyName.equals(USER_WANTS_TO_OVERRIDE_DEFAULT_SCHEMA)) {
			this.model.notifyPropertyChange(USER_OVERRIDE_DEFAULT_SCHEMA, IDataModel.ENABLE_CHG);
			if (! ((Boolean) propertyValue).booleanValue()) {
				this.model.setProperty(USER_OVERRIDE_DEFAULT_SCHEMA, null);
			}
		}
//		if (propertyName.equals(USE_SERVER_JPA_IMPLEMENTATION)) {
//			this.model.setBooleanProperty(USE_USER_JPA_LIBRARY, ! ((Boolean) propertyValue).booleanValue());
//		}
//		if (propertyName.equals(USE_USER_JPA_LIBRARY)) {
//			this.model.setBooleanProperty(USE_SERVER_JPA_IMPLEMENTATION, ! ((Boolean) propertyValue).booleanValue());
//			this.model.notifyPropertyChange(JPA_LIBRARY, IDataModel.ENABLE_CHG);
//		}
		if (propertyName.equals(DISCOVER_ANNOTATED_CLASSES)) {
			this.model.setBooleanProperty(LIST_ANNOTATED_CLASSES, ! ((Boolean) propertyValue).booleanValue());
		}
		if (propertyName.equals(LIST_ANNOTATED_CLASSES)) {
			this.model.setBooleanProperty(DISCOVER_ANNOTATED_CLASSES, ! ((Boolean) propertyValue).booleanValue());
		}
		return ok;
	}

	private static final DataModelPropertyDescriptor[] EMPTY_DMPD_ARRAY = new DataModelPropertyDescriptor[0];

	@Override
	public DataModelPropertyDescriptor[] getValidPropertyDescriptors(String propertyName) {
		if (propertyName.equals(PLATFORM_ID)) {
			return CollectionTools.sort(
				CollectionTools.array(
					new TransformationIterator<String, DataModelPropertyDescriptor>(
						JpaPlatformRegistry.instance().jpaPlatformIds()) {
							@Override
							protected DataModelPropertyDescriptor transform(String platformId) {
								return platformIdPropertyDescriptor(platformId);
							}
						},
						EMPTY_DMPD_ARRAY),
				new Comparator<DataModelPropertyDescriptor>() {
					public int compare(DataModelPropertyDescriptor o1, DataModelPropertyDescriptor o2) {
						return (o1.getPropertyDescription().compareTo(o2.getPropertyDescription()));
					};
				});
		}
		if (propertyName.equals(CONNECTION)) {
			return CollectionTools.array(
				new TransformationIterator<String, DataModelPropertyDescriptor>(
						new CompositeIterator<String>(null, connectionNames())) {
					@Override
					protected DataModelPropertyDescriptor transform(String next) {
						return connectionPropertyDescriptor(next);
					}
				},
				EMPTY_DMPD_ARRAY);
		}
		if (propertyName.equals(DB_DRIVER_NAME)) {
			return CollectionTools.array(
				new TransformationIterator<String, DataModelPropertyDescriptor>(driverNames()) {
					@Override
					protected DataModelPropertyDescriptor transform(String next) {
						return new DataModelPropertyDescriptor(next);
					}
				},
				EMPTY_DMPD_ARRAY);
		}
		if (propertyName.equals(USER_OVERRIDE_DEFAULT_CATALOG)) {
			return CollectionTools.array(
				new TransformationIterator<String, DataModelPropertyDescriptor>(catalogNames()) {
					@Override
					protected DataModelPropertyDescriptor transform(String next) {
						return new DataModelPropertyDescriptor(next);
					}
				},
				EMPTY_DMPD_ARRAY);
		}
		if (propertyName.equals(USER_OVERRIDE_DEFAULT_SCHEMA)) {
			return CollectionTools.array(
				new TransformationIterator<String, DataModelPropertyDescriptor>(schemaNames()) {
					@Override
					protected DataModelPropertyDescriptor transform(String next) {
						return new DataModelPropertyDescriptor(next);
					}
				},
				EMPTY_DMPD_ARRAY);
		}

		return super.getValidPropertyDescriptors(propertyName);
	}
	
	@Override
	public DataModelPropertyDescriptor getPropertyDescriptor(String propertyName) {
		if (propertyName.equals(PLATFORM_ID)) {
			return platformIdPropertyDescriptor(getStringProperty(PLATFORM_ID));
		}
		if (propertyName.equals(CONNECTION)) {
			return connectionPropertyDescriptor(getStringProperty(CONNECTION));
		}
		return super.getPropertyDescriptor(propertyName);
	}
	
	DataModelPropertyDescriptor platformIdPropertyDescriptor(String platformId) {
		return new DataModelPropertyDescriptor(
			platformId, JpaPlatformRegistry.instance().getJpaPlatformLabel(platformId));
	}
	
	DataModelPropertyDescriptor connectionPropertyDescriptor(String connection) {
		return StringTools.stringIsEmpty(connection) ?
					new DataModelPropertyDescriptor(null, JptCoreMessages.NONE)
				:
					new DataModelPropertyDescriptor(connection);
	}

	@Override
	public IStatus validate(String name) {
		if (name.equals(PLATFORM_ID)) {
			return this.validatePlatformId(this.getStringProperty(name));
		}
		if (name.equals(LIBRARY_PROVIDER_DELEGATE)) {
			LibraryInstallDelegate delegate = (LibraryInstallDelegate) getProperty(LIBRARY_PROVIDER_DELEGATE);
		    return delegate.validate();
		}
		if (name.equals(CONNECTION)) {
			return this.validateConnectionName(this.getStringProperty(name));
		}
		if (name.equals(USER_WANTS_TO_ADD_DB_DRIVER_JARS_TO_CLASSPATH)
				|| name.equals(DB_DRIVER_NAME)) {
			return this.validateDbDriverName();
		}
		if (name.equals(USER_WANTS_TO_OVERRIDE_DEFAULT_CATALOG)
			|| name.equals(USER_OVERRIDE_DEFAULT_CATALOG)) {
			return this.validateUserOverrideDefaultCatalog();
		}
		if (name.equals(USER_WANTS_TO_OVERRIDE_DEFAULT_SCHEMA)
				|| name.equals(USER_OVERRIDE_DEFAULT_SCHEMA)) {
			return this.validateUserOverrideDefaultSchema();
		}
		if (name.equals(DISCOVER_ANNOTATED_CLASSES)) {
			return this.validatePersistentClassManagement(this.getBooleanProperty(name));
		}
		
		return super.validate(name);
	}

	private IRuntime runtime() {
		return (IRuntime) this.getProperty(RUNTIME);
	}

	private boolean runtimeSupportsEjb30(IRuntime runtime) {
		IProjectFacetVersion ejb30 = ProjectFacetsManager.getProjectFacet(EJB_FACET_ID).getVersion("3.0"); //$NON-NLS-1$
		return (runtime == null) ? false : runtime.supports(ejb30);
	}
	
	private String getPlatformId() {
		return this.getStringProperty(PLATFORM_ID);
	}
	
	private LibraryInstallDelegate getLibraryInstallDelegate() {
		return (LibraryInstallDelegate) getProperty(LIBRARY_PROVIDER_DELEGATE);
	}

	private String getConnectionName() {
		return this.getStringProperty(CONNECTION);
	}
	
	private ConnectionProfile getConnectionProfile() {
		return this.buildConnectionProfile(this.getConnectionName());
	}

	private ConnectionProfileFactory getConnectionProfileFactory() {
		// we don't have a JPA project yet, so go to the db plug-in directly to get the factory
		return JptDbPlugin.instance().getConnectionProfileFactory();
	}

	private ConnectionProfile buildConnectionProfile(String name) {
		return this.getConnectionProfileFactory().buildConnectionProfile(name, DatabaseFinder.Default.instance());
	}

	private boolean connectionIsActive() {
		return this.connectionIsActive(this.getConnectionName());
	}

	private boolean connectionIsActive(String connectionName) {
		ConnectionProfile cp = this.buildConnectionProfile(connectionName);
		return (cp != null) && cp.isActive();
	}
	
	private Iterator<String> connectionNames() {
		String setValue = getStringProperty(CONNECTION);
		
		List<String> connectionNames = CollectionTools.sort(CollectionTools.list(
			this.getConnectionProfileFactory().connectionProfileNames()));
		
		if (! StringTools.stringIsEmpty(setValue) && ! connectionNames.contains(setValue)) {
			return new CompositeIterator<String>(setValue, connectionNames.iterator());
		}
		return connectionNames.iterator();
	}
	
	private List<String> buildSortedCatalogNames() {
		ConnectionProfile cp = this.getConnectionProfile();
		if (cp == null) {
			return Collections.emptyList();
		}
		Database db = cp.getDatabase();
		if (db == null) {
			return Collections.emptyList();
		}
		return CollectionTools.list(db.sortedCatalogIdentifiers());
	}
	
	private Iterator<String> catalogNames() {
		String setValue = getStringProperty(USER_OVERRIDE_DEFAULT_CATALOG);
		List<String> catalogNames = this.buildSortedCatalogNames();
		
		if (StringTools.stringIsEmpty(setValue) || catalogNames.contains(setValue)) {
			return catalogNames.iterator();
		}
		return new CompositeIterator<String>(setValue, catalogNames.iterator());
	}
	
	private List<String> buildSortedSchemaNames() {
		ConnectionProfile cp = this.getConnectionProfile();
		if (cp == null) {
			return Collections.emptyList();
		}
		Database db = cp.getDatabase();
		if (db == null) {
			return Collections.emptyList();
		}
		return CollectionTools.list(db.sortedSchemaIdentifiers());  // use identifiers? names seem OK since combo-box is read-only?
	}

	private Iterator<String> schemaNames() {
		String setValue = getStringProperty(USER_OVERRIDE_DEFAULT_SCHEMA);
		List<String> schemaNames = this.buildSortedSchemaNames();
		
		if (StringTools.stringIsEmpty(setValue) || schemaNames.contains(setValue)) {
			return schemaNames.iterator();
		}
		return new CompositeIterator<String>(setValue, schemaNames.iterator());
	}
	
	private Iterator<String> driverNames() {
		String setValue = getStringProperty(DB_DRIVER_NAME);
		
		return new CompositeIterator<String>(setValue, EmptyIterator.<String> instance());
	}


	// ********** validation **********

	private IStatus validatePlatformId(String platformId) {
		return StringTools.stringIsEmpty(platformId) ?
				PLATFORM_NOT_SPECIFIED_STATUS
			:
				OK_STATUS;
	}

	private IStatus validateConnectionName(String connectionName) {
		if (StringTools.stringIsEmpty(connectionName)) {
			return OK_STATUS;
		}
		ConnectionProfile connectionProfile = getConnectionProfile();
		if (connectionProfile == null) {
			return buildErrorStatus(NLS.bind(JptCoreMessages.VALIDATE_CONNECTION_INVALID, connectionName));
	
		}
		if (! connectionProfile.isActive()) {
			return CONNECTION_NOT_CONNECTED_STATUS;
		}
		return OK_STATUS;
	}
	
	private IStatus validateUserOverrideDefaultCatalog() {
		if (getBooleanProperty(USER_WANTS_TO_OVERRIDE_DEFAULT_CATALOG)) {
			if (StringTools.stringIsEmpty(getStringProperty(USER_OVERRIDE_DEFAULT_CATALOG))) {
				return USER_OVERRIDE_DEFAULT_CATALOG_NOT_SPECIFIED_STATUS;
			}
		}
		return OK_STATUS;
	}
	
	private IStatus validateUserOverrideDefaultSchema() {
		if (getBooleanProperty(USER_WANTS_TO_OVERRIDE_DEFAULT_SCHEMA)) {
			if (StringTools.stringIsEmpty(getStringProperty(USER_OVERRIDE_DEFAULT_SCHEMA))) {
				return USER_OVERRIDE_DEFAULT_SCHEMA_NOT_SPECIFIED_STATUS;
			}
		}
		return OK_STATUS;
	}

	private IStatus validatePersistentClassManagement(boolean discoverAnnotatedClasses) {
		// TODO warning if "discovery" is used, but no runtime specified ??
		return OK_STATUS;
	}

	private IStatus validateDbDriverName() {
		return OK_STATUS;
	}


	// ********** static methods **********

	private static IStatus buildInfoStatus(String message) {
		return buildStatus(IStatus.INFO, message);
	}

	private static IStatus buildWarningStatus(String message) {
		return buildStatus(IStatus.WARNING, message);
	}

	private static IStatus buildErrorStatus(String message) {
		return buildStatus(IStatus.ERROR, message);
	}

	private static IStatus buildStatus(int severity, String message) {
		return new Status(severity, JptCorePlugin.PLUGIN_ID, message);
	}
}
