/**
* 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
*/
package org.eclipse.emf.converter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.emf.converter.util.ConverterUtil;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.plugin.EcorePlugin;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
/**
* @since 2.2.0
*/
public abstract class ModelConverter
{
public static class EPackageConvertInfo
{
protected boolean convert = false;
protected String convertData;
public boolean isConvert()
{
return convert;
}
public void setConvert(boolean convert)
{
this.convert = convert;
}
public String getConvertData()
{
return convertData;
}
public void setConvertData(String convertData)
{
this.convertData = convertData;
}
}
public static class ReferencedGenPackageConvertInfo
{
protected boolean validReference = true;
public boolean isValidReference()
{
return validReference;
}
public void setValidReference(boolean validReference)
{
this.validReference = validReference;
}
}
protected class ReferencedEPackageFilter
{
public List<GenPackage> computeValidReferencedGenPackages()
{
List<GenPackage> genPackages = new ConverterUtil.GenPackageList();
for (GenPackage genPackage : getReferencedGenPackages())
{
EPackage ePackage = getReferredEPackage(genPackage);
if (ePackage != null)
{
genPackages.add(genPackage);
}
}
return genPackages;
}
public List<EPackage> filterReferencedEPackages(Collection<EPackage> ePackages, List<GenPackage> referencedGenPackages)
{
if (referencedGenPackages == null)
{
referencedGenPackages = getReferencedGenPackages();
}
if (ePackages.isEmpty())
{
return Collections.emptyList();
}
else if (referencedGenPackages.isEmpty())
{
return new ArrayList<EPackage>(ePackages);
}
else
{
List<EPackage> filteredEPackages = new ConverterUtil.EPackageList(ePackages);
for (GenPackage genPackage : referencedGenPackages)
{
EPackage ePackage = getReferredEPackage(genPackage);
if (ePackage != null)
{
filteredEPackages.remove(ePackage);
}
}
return filteredEPackages;
}
}
protected EPackage getReferredEPackage(GenPackage genPackage)
{
return isValidReference(genPackage) ?
ModelConverter.this.getReferredEPackage(genPackage) :
null;
}
protected boolean isValidReference(GenPackage genPackage)
{
return getReferenceGenPackageConvertInfo(genPackage).isValidReference();
}
}
protected GenModel genModel;
protected List<EPackage> ePackages;
protected Map<EPackage, EPackageConvertInfo> ePackageToInfoMap;
protected List<GenPackage> referencedGenPackages;
protected Map<GenPackage, ReferencedGenPackageConvertInfo> referencedGenPackageToInfoMap;
protected ResourceSet externalGenModelResourceSet;
protected List<GenModel> externalGenModelList;
protected ReferencedEPackageFilter referencedEPackageFilter;
protected ReferencedEPackageFilter referencedEPackageFilterToConvert;
public void dispose()
{
clearEPackagesCollections();
if (referencedGenPackages != null)
{
referencedGenPackages.clear();
referencedGenPackages = null;
}
if (referencedGenPackageToInfoMap != null)
{
referencedGenPackageToInfoMap.clear();
referencedGenPackageToInfoMap = null;
}
genModel = null;
referencedEPackageFilter = null;
referencedEPackageFilterToConvert = null;
}
public abstract String getID();
protected String getConverterGenAnnotationSource()
{
return GenModelPackage.eNS_URI + getID();
}
public GenModel getGenModel()
{
return genModel;
}
public List<EPackage> getEPackages()
{
if (ePackages == null)
{
ePackages = createEPackagesList();
}
return ePackages;
}
protected List<EPackage> createEPackagesList()
{
return new ConverterUtil.EPackageList();
}
public List<GenPackage> getReferencedGenPackages()
{
if (referencedGenPackages == null)
{
referencedGenPackages = createReferencedGenPackagesList();
}
return referencedGenPackages;
}
protected List<GenPackage> createReferencedGenPackagesList()
{
return new ConverterUtil.GenPackageList();
}
public void clearEPackagesCollections()
{
if (ePackages != null)
{
ePackages.clear();
ePackages = null;
}
if (ePackageToInfoMap != null)
{
ePackageToInfoMap.clear();
ePackageToInfoMap = null;
}
if (externalGenModelList != null)
{
externalGenModelList.clear();
externalGenModelList = null;
}
}
public ResourceSet createResourceSet()
{
return ConverterUtil.createResourceSet();
}
protected Map<EPackage, EPackageConvertInfo> getEPackageToInfoMap()
{
if (ePackageToInfoMap == null)
{
ePackageToInfoMap = new HashMap<EPackage, EPackageConvertInfo>();
}
return ePackageToInfoMap;
}
public EPackageConvertInfo getEPackageConvertInfo(EPackage ePackage)
{
EPackageConvertInfo ePackageInfo = getEPackageToInfoMap().get(ePackage);
if (ePackageInfo == null)
{
ePackageInfo = createEPackageInfo(ePackage);
getEPackageToInfoMap().put(ePackage, ePackageInfo);
}
return ePackageInfo;
}
public void clearEPackageConvertInfoCache()
{
getEPackageToInfoMap().clear();
}
protected EPackageConvertInfo createEPackageInfo(EPackage ePackage)
{
return new EPackageConvertInfo();
}
protected Map<GenPackage, ReferencedGenPackageConvertInfo> getReferencedGenPackageToInfoMap()
{
if (referencedGenPackageToInfoMap == null)
{
referencedGenPackageToInfoMap = new HashMap<GenPackage, ReferencedGenPackageConvertInfo>();
}
return referencedGenPackageToInfoMap;
}
public ReferencedGenPackageConvertInfo getReferenceGenPackageConvertInfo(GenPackage genPackage)
{
ReferencedGenPackageConvertInfo genPackageConvertInfo = getReferencedGenPackageToInfoMap().get(genPackage);
if (genPackageConvertInfo == null)
{
genPackageConvertInfo = createGenPackageConvertInfo(genPackage);
getReferencedGenPackageToInfoMap().put(genPackage, genPackageConvertInfo);
}
return genPackageConvertInfo;
}
public void clearReferenceGenPackageConvertInfoCache()
{
getReferencedGenPackageToInfoMap().clear();
}
protected ReferencedGenPackageConvertInfo createGenPackageConvertInfo(GenPackage genPackage)
{
return new ReferencedGenPackageConvertInfo();
}
public List<EPackage> filterReferencedEPackages(Collection<EPackage> ePackages, List<GenPackage> referencedGenPackages)
{
if (referencedEPackageFilter == null)
{
referencedEPackageFilter = createReferencedEPackageFilter();
}
return referencedEPackageFilter.filterReferencedEPackages(ePackages, referencedGenPackages);
}
protected ReferencedEPackageFilter createReferencedEPackageFilter()
{
return new ReferencedEPackageFilter();
}
protected List<EPackage> computeEPackagesToConvert()
{
List<EPackage> ePackages = new ConverterUtil.EPackageList();
for (EPackage ePackage : getEPackages())
{
if (canConvert(ePackage))
{
ePackages.add(ePackage);
}
}
return filterReferencedEPackagesToConvert(ePackages, null);
}
protected List<EPackage> filterReferencedEPackagesToConvert(Collection<EPackage> ePackages, List<GenPackage> referencedGenPackages)
{
if (referencedEPackageFilterToConvert == null)
{
referencedEPackageFilterToConvert = createReferencedEPackageFilterToConvert();
}
return referencedEPackageFilterToConvert.filterReferencedEPackages(ePackages, referencedGenPackages);
}
protected List<GenPackage> computeValidReferencedGenPackages()
{
if (referencedEPackageFilterToConvert == null)
{
referencedEPackageFilterToConvert = createReferencedEPackageFilterToConvert();
}
return referencedEPackageFilterToConvert.computeValidReferencedGenPackages();
}
protected ReferencedEPackageFilter createReferencedEPackageFilterToConvert()
{
return new ReferencedEPackageFilter();
}
/**
* Returns true if the EPackage can be converted. This
* method doesn't check for dependencies or anything, being focused
* in testing whether all the required information to generate an
* EPackage was gathered.
*/
protected boolean canConvert(EPackage ePackage)
{
return getEPackageConvertInfo(ePackage).isConvert();
}
public EPackage getReferredEPackage(GenPackage genPackage)
{
String nsURI = genPackage.getEcorePackage().getNsURI();
if (nsURI != null)
{
for (EPackage ePackage : getEPackages())
{
if (nsURI.equals(ePackage.getNsURI()))
{
return ePackage;
}
}
}
return null;
}
public List<GenModel> getExternalGenModels()
{
if (externalGenModelList == null)
{
externalGenModelList = new UniqueEList.FastCompare<GenModel>();
if (externalGenModelResourceSet == null)
{
externalGenModelResourceSet = createExternalGenModelResourceSet();
}
Map<String, URI> ePackageToGenModelMap = EcorePlugin.getEPackageNsURIToGenModelLocationMap();
for (TreeIterator<EPackage> i =
new EcoreUtil.ContentTreeIterator<EPackage>(getEPackages())
{
private static final long serialVersionUID = 1L;
@Override
protected Iterator<? extends EObject> getEObjectChildren(EObject eObject)
{
return ((EPackage)eObject).getESubpackages().iterator();
}
};
i.hasNext(); )
{
EPackage ePackage = i.next();
URI genModelURI = ePackageToGenModelMap.get(ePackage.getNsURI());
if (genModelURI != null)
{
try
{
Resource genModelResource = externalGenModelResourceSet.getResource(genModelURI, false);
if (genModelResource == null)
{
genModelResource = externalGenModelResourceSet.getResource(genModelURI, true);
// If we're loading an Xcore file, we need to be sure there is a resource to identify the project to initialize the Xcore's project provider.
//
Resource dummyResource = null;
if ("xcore".equals(genModelURI.fileExtension()) && genModelURI.isPlatformPlugin())
{
dummyResource = externalGenModelResourceSet.createResource(getEPackages().get(0).eResource().getURI());
}
externalGenModelList.add((GenModel)EcoreUtil.getObjectByType(genModelResource.getContents(), GenModelPackage.Literals.GEN_MODEL));
if (dummyResource != null)
{
externalGenModelResourceSet.getResources().remove(dummyResource);
}
}
}
catch (Exception exception)
{
ConverterPlugin.INSTANCE.log(exception);
}
i.prune();
}
}
}
return externalGenModelList;
}
protected ResourceSet createExternalGenModelResourceSet()
{
return createResourceSet();
}
/**
* This method was misnamed and will be removed in the next release.
* @see #getGenModelSaveOptions()
*/
@Deprecated
protected Map<?, ?> getGenmodelSaveOptions()
{
Map<Object, Object> result = new HashMap<Object, Object>();
result.put(Resource.OPTION_SAVE_ONLY_IF_CHANGED, Resource.OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER);
result.put(Resource.OPTION_LINE_DELIMITER, Resource.OPTION_LINE_DELIMITER_UNSPECIFIED);
return result;
}
protected Map<?, ?> getGenModelSaveOptions()
{
return getGenmodelSaveOptions();
}
/**
* Changes the existing EPackage Infos so that no duplicated convert data
* is used.
*/
public void makeEPackageConvertDataUnique()
{
if (!getEPackageToInfoMap().isEmpty())
{
Map<String, Integer> dataToCounter = new HashMap<String, Integer>();
List<EPackage> ePackages = filterReferencedEPackages(getEPackageToInfoMap().keySet(), null);
if (!ePackages.isEmpty())
{
List<EPackageConvertInfo> packageInfos = new ArrayList<EPackageConvertInfo>(ePackages.size());
for (EPackage ePackage : ePackages)
{
if (ePackage.getESuperPackage() == null || !ePackages.contains(ePackage.getESuperPackage()))
{
EPackageConvertInfo packageInfo = getEPackageToInfoMap().get(ePackage);
if (packageInfo.isConvert())
{
packageInfos.add(0, packageInfo);
}
else
{
packageInfos.add(packageInfo);
}
String data = packageInfo.getConvertData();
if (data != null)
{
dataToCounter.put(data, null);
}
}
}
for (EPackageConvertInfo packageInfo : packageInfos)
{
String data = packageInfo.getConvertData();
if (data != null)
{
Integer counterObject = dataToCounter.get(data);
if (counterObject != null)
{
int counter = counterObject;
int index = data.lastIndexOf(".");
StringBuffer newValue = null;
do
{
newValue = new StringBuffer(data).insert(index, counter++);
}
while (dataToCounter.containsKey(newValue.toString()));
packageInfo.setConvertData(newValue.toString());
counterObject = counter;
dataToCounter.put(newValue.toString(), 1);
}
else
{
counterObject = 1;
}
dataToCounter.put(data, counterObject);
}
}
}
}
}
}