blob: 26bd6ada119853f0563c65b5ce1c7a22577b730d [file] [log] [blame]
/**
********************************************************************************
* Copyright (c) 2015-2021 Robert Bosch GmbH and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Robert Bosch GmbH - initial API and implementation
********************************************************************************
*/
package org.eclipse.app4mc.amalthea.model.emf;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipFile;
import org.eclipse.app4mc.amalthea.model.AmaltheaIndex;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.xmi.XMLHelper;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.XMIHelperImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
public class AmaltheaResource extends XMIResourceImpl {
public AmaltheaResource() {
super();
addDefaults();
}
public AmaltheaResource(final URI uri) {
super(uri);
addDefaults();
}
private void addDefaults() {
getDefaultSaveOptions().put(XMLResource.OPTION_ENCODING, "UTF-8");
// Add some performance tweaks to improve loading of big models
// http://sdqweb.ipd.kit.edu/wiki/EMF_Model_Loading_Performance_Tweaks
getDefaultLoadOptions().put(XMLResource.OPTION_DEFER_ATTACHMENT, Boolean.TRUE);
getDefaultLoadOptions().put(XMLResource.OPTION_DEFER_IDREF_RESOLUTION, Boolean.TRUE);
getDefaultLoadOptions().put(XMLResource.OPTION_USE_XML_NAME_TO_FEATURE_MAP, new HashMap<>());
// Also store defaults (this option has no effect on enums)
getDefaultLoadOptions().put(XMLResource.OPTION_KEEP_DEFAULT_CONTENT, Boolean.TRUE);
getDefaultSaveOptions().put(XMLResource.OPTION_KEEP_DEFAULT_CONTENT, Boolean.TRUE);
// Use AmaltheaResourceHandler
getDefaultLoadOptions().put(XMLResource.OPTION_RESOURCE_HANDLER, new AmaltheaResourceHandler());
getDefaultSaveOptions().put(XMLResource.OPTION_RESOURCE_HANDLER, new AmaltheaResourceHandler());
}
// Zip option
// - can be set explicitly to avoid computation (with problematic URI to file conversion)
// - will be computed otherwise
private boolean computeZipOption = true;
@Override
public boolean useZip() {
// if not already set then compute and cache value
if (computeZipOption) {
setUseZip(isZipFile(getURI()));
}
return super.useZip();
}
@Override
public void setUseZip(boolean useZip) {
super.setUseZip(useZip);
// if explicitly set then do not compute value
computeZipOption = false;
}
private boolean isZipFile(final URI uri) {
boolean result = false;
URI fileURI = convertToAbsoluteFileURI(uri);
if (fileURI != null) {
String fileString = fileURI.toFileString();
if (fileString != null) {
try (ZipFile f = new ZipFile(fileString)) {
// zipped file detected
result = true;
} catch (IOException e) {
// IOException includes ZipException -> not a zip file
}
}
}
return result;
}
private URI convertToAbsoluteFileURI(final URI uri) {
URI result;
// Try to convert to absolute file URI
result = CommonPlugin.asLocalURI(uri);
// Resulting URI still relative?
if (result.isRelative()) {
// Try with normalize URI
result = getURIConverter().normalize(uri);
result = CommonPlugin.asLocalURI(result);
}
return result;
}
/**
* @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#useUUIDs()
*/
@Override
protected boolean useUUIDs() {
return false;
}
@Override
protected boolean useIDs() {
return true;
}
protected void resetIDMaps() {
synchronized(this) {
idToEObjectMap = null;
eObjectToIDMap = null;
}
}
@Override
protected EObject getEObjectByID(String id) {
if (id == null)
return null;
// first: check extrinsic IDs map (only available while saving model)
if (idToEObjectMap != null) {
EObject eObject = idToEObjectMap.get(id);
if (eObject != null) {
return eObject;
}
}
// second: check intrinsic IDs map (only available while loading model)
Map<String, EObject> map = getIntrinsicIDToEObjectMap();
if (map != null) {
EObject eObject = map.get(id);
if (eObject != null) {
return eObject;
}
}
// third: check Amalthea index
return AmaltheaIndex.getEObjectByID(this, id);
// -----------------------------------------------------------------------------------
// Load option is OPTION_DEFER_IDREF_RESOLUTION = true
//
// -> no fallback solution if ID is not stored in cache(s)
//
// This prevents time consuming iterations (especially in case of very large models)
// -----------------------------------------------------------------------------------
}
/*
* @see org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl#createXMLHelper()
*/
@Override
protected XMLHelper createXMLHelper() {
// Overwrite creation of HREFs (required for serialized references)
// - internal reference -> prefix #
// - cross-document reference -> prefix amlt:/#
return new XMIHelperImpl(this) {
@Override
protected URI getHREF(Resource otherResource, EObject obj) {
String prefix = (resource == otherResource) ? "#" : "amlt:/#";
return URI.createURI(prefix + getIDREF(obj), true);
}
};
}
}