/******************************************************************************* * Copyright (c) 2007 Oracle Corporation. * 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.jst.jsf.common.metadata.internal; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IStatus; import org.eclipse.jst.jsf.common.JSFCommonPlugin; /** * Default class used for loading metadata. * Loads the source types from extensions defined against the domain. * * see org.eclipse.jst.jsf.common.domainLoadingStrategies ext-pt */ public class DomainLoadingStrategy implements IDomainLoadingStrategy, IMetaDataObserver { /** * Domain id */ protected String domain; private MetaDataModel _model; private List <IDomainSourceModelType> _sourceTypes; private List <IMetaDataSourceModelProvider> _sources; /** * Constructor * @param domain */ public DomainLoadingStrategy(String domain){ this.domain = domain; } /* (non-Javadoc) * @see org.eclipse.jst.jsf.common.metadata.internal.IDomainLoadingStrategy#load(org.eclipse.jst.jsf.common.metadata.internal.MetaDataModel) */ public void load(MetaDataModel model) { this._model = model; _sourceTypes = loadDomainSourceModelTypes(); sortSourceTypes(_sourceTypes); _sources = locateMetaDataSourceInstances(_sourceTypes, model); mergeModel(model, _sources); } /* (non-Javadoc) * @see org.eclipse.jst.jsf.common.metadata.internal.IDomainLoadingStrategy#reload() */ public void reload() throws ModelNotSetException { //System.out.println("reload");//debug //$NON-NLS-1$ if (_model == null) throw new ModelNotSetException(); removeOldLocatorObservers(); _sources = locateMetaDataSourceInstances(_sourceTypes, _model); mergeModel(_model, _sources); } /** * Responsible for iterating through the sorted list of <code>IMetaDataSourceModelProvider</code> * and merging the models after first translating the source model as required, into a single mreged model of * standard metadata Entities and Traits. * @param model * @param sources */ protected void mergeModel(final MetaDataModel model, final List <IMetaDataSourceModelProvider> sources) { StandardModelFactory.debug(">> Begin Merge: "+model.getModelContext()+"("+sources.size()+ " sources)", StandardModelFactory.DEBUG_MD_LOAD); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ final IMetaDataModelMergeAssistant assistant = createModelMergeAssistant(model); for (final IMetaDataSourceModelProvider mds : sources){ final Iterator translators = mds.getLocator().getDomainSourceModelType().getTranslators().iterator(); while (translators.hasNext()){ final IMetaDataTranslator translator = (IMetaDataTranslator)translators.next(); if (translator.canTranslate(mds)){ StandardModelFactory.debug(">>> Merging: "+model.getModelContext()+"::"+mds, StandardModelFactory.DEBUG_MD_LOAD); //$NON-NLS-1$//$NON-NLS-2$ assistant.setSourceModelProvider(mds); try { translator.translate(assistant); } catch (Exception e) { StandardModelFactory.debug(">>>> Error during translate/merge of: "+model.getModelContext()+": "+mds, StandardModelFactory.DEBUG_MD_LOAD); //$NON-NLS-1$ //$NON-NLS-2$ JSFCommonPlugin.log(IStatus.ERROR, "Error during load of: "+mds, e); //$NON-NLS-1$ } } } } assistant.setMergeComplete(); StandardModelFactory.debug(">> End Merge: "+model.getModelContext(),StandardModelFactory.DEBUG_MD_LOAD); //$NON-NLS-1$ } /** * @param model * @return an instance of a IMetaDataModelMergeAssistant to be used while merging source models */ protected IMetaDataModelMergeAssistant createModelMergeAssistant(MetaDataModel model){ return new MetaDataModelMergeAssistantImpl(model); } /** * Allows for subclasses to override the default mechanism for sorting the source types. * @param sourceTypes */ protected void sortSourceTypes(List <IDomainSourceModelType> sourceTypes) { //allows override } /** * @return list of <code>IDomainSourceModelType</code>s located in the <code>DomainSourceTypesRegistry</code> * for the specified uri */ protected List <IDomainSourceModelType> loadDomainSourceModelTypes() { return DomainSourceTypesRegistry.getInstance().getDomainSourceTypes(domain); } /** * @param sourceTypes * @param model * @return list of <code>IMetaDataSourceModelProvider</code> instances from the domain source types applicable for * this domain for this particular uri specified in the model */ protected List <IMetaDataSourceModelProvider> locateMetaDataSourceInstances(final List <IDomainSourceModelType> sourceTypes, MetaDataModel model) { final List<IMetaDataSourceModelProvider> sources = new ArrayList<IMetaDataSourceModelProvider>(); final IProject project = getProject(model); for (final IDomainSourceModelType sourceType : sourceTypes){ final IMetaDataLocator locator = sourceType.getLocator(project); if (locator != null) { //We MUST set the sourceType here to associate the handler with locator to use for the source models locator.setDomainSourceModelType(sourceType); final List <IMetaDataSourceModelProvider> providers = locator.locateMetaDataModelProviders(model.getModelContext().getModelIdentifier()); if (providers != null && !providers.isEmpty()){ for (final IMetaDataSourceModelProvider provider : providers){ //We MUST set the sourceType here to associate the translators to use for the source models provider.setLocator(locator); sources.add(provider); } } //listen for changes locator.addObserver(this); } } return sources; } private IProject getProject(final MetaDataModel model) { return (IProject)model.getModelContext().getAdapter(IProject.class); } /* (non-Javadoc) * @see org.eclipse.jst.jsf.common.metadata.internal.IMetaDataObserver#notifyMetadataChanged(org.eclipse.jst.jsf.common.metadata.internal.IMetaDataChangeNotificationEvent) */ public void notifyMetadataChanged(final IMetaDataChangeNotificationEvent event) { //for now, if any event occurs, we need to flush the _model so that it will rebuild _model.setNeedsRefresh(); } /* (non-Javadoc) * @see org.eclipse.jst.jsf.common.metadata.internal.IDomainLoadingStrategy#cleanup() */ public void cleanup(){ removeOldLocatorObservers(); _sources = null; _sourceTypes = null; _model = null; } private void removeOldLocatorObservers(){ if (_sources != null){ for (final IMetaDataSourceModelProvider provider : _sources){ if (provider != null) { final IMetaDataLocator locator = provider.getLocator(); if (locator != null){ locator.removeObserver(this); locator.setDomainSourceModelType(null); provider.setLocator(null); } } } } } }