blob: 1f2f068b7a537cb00b461b38969d50b96af0efe8 [file] [log] [blame]
/*
* Copyright (c) 2006, 2008 Borland Software 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:
* Artem Tikhomirov (Borland)
* Boris Blajer (Borland) - support for composite resources
*/
package org.eclipse.gmf.internal.xpand.util;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import java.util.Map;
import java.util.TreeMap;
import org.eclipse.gmf.internal.xpand.ResourceManager;
import org.eclipse.gmf.internal.xpand.expression.SyntaxConstants;
import org.eclipse.gmf.internal.xpand.migration.Activator;
import org.eclipse.gmf.internal.xpand.model.XpandResource;
import org.eclipse.gmf.internal.xpand.xtend.ast.XtendResource;
// FIXME it's not a good idea to parse file on every proposal computation
public abstract class ResourceManagerImpl implements ResourceManager {
private final Map<String, XtendResource> cachedXtend = new TreeMap<String, XtendResource>();
private final Map<String, XpandResource> cachedXpand = new TreeMap<String, XpandResource>();
public XtendResource loadXtendResource(String fullyQualifiedName) {
try {
return loadXtendThroughCache(fullyQualifiedName);
} catch (FileNotFoundException ex) {
return null; //Missing resource is an anticipated situation, not a error that should be handled
} catch (IOException ex) {
Activator.logError(ex);
} catch (ParserException ex) {
handleParserException(ex);
}
return null;
}
protected XtendResource loadXtendThroughCache(String qualifiedName) throws IOException, ParserException {
if (hasCachedXtend(qualifiedName)) {
return cachedXtend.get(qualifiedName);
}
final XtendResource loaded = doLoadXtendResource(qualifiedName);
assert loaded != null; // this is the contract of loadXtendResource
if (shouldCache()) {
cachedXtend.put(qualifiedName, loaded);
}
return loaded;
}
private XtendResource doLoadXtendResource(String fullyQualifiedName) throws IOException, ParserException {
Reader[] rs = resolveMultiple(fullyQualifiedName, XtendResource.FILE_EXTENSION);
assert rs != null && rs.length > 0;
XtendResource[] result = loadXtendResources(rs, fullyQualifiedName);
if (result.length == 1) {
return result[0];
}
return new CompositeXtendResource(this, result);
}
public XpandResource loadXpandResource(String fullyQualifiedName) {
try {
return loadXpandThroughCache(fullyQualifiedName);
} catch (FileNotFoundException ex) {
return null; //Missing resource is an anticipated situation, not a error that should be handled
} catch (IOException ex) {
// XXX come up with better handling
Activator.logWarn(ex.getMessage());
} catch (ParserException ex) {
handleParserException(ex);
}
return null;
}
protected XpandResource loadXpandThroughCache(String qualifiedName) throws IOException, ParserException {
if (hasCachedXpand(qualifiedName)) {
return cachedXpand.get(qualifiedName);
}
final XpandResource loaded = doLoadXpandResource(qualifiedName);
if (shouldCache()) {
cachedXpand.put(qualifiedName, loaded);
}
return loaded;
}
private XpandResource doLoadXpandResource(String fullyQualifiedName) throws IOException, ParserException {
Reader[] rs1 = resolveMultiple(fullyQualifiedName, XpandResource.TEMPLATE_EXTENSION);
assert rs1 != null && rs1.length > 0; // exception should be thrown to indicate issues with resolve
XpandResource[] unadvised = loadXpandResources(rs1, fullyQualifiedName);
XpandResource[] advices = null;
try {
String aspectsTemplateName = getAspectsTemplateName(fullyQualifiedName);
Reader[] rs2 = resolveMultiple(aspectsTemplateName, XpandResource.TEMPLATE_EXTENSION);
// XXX relax resolveMultiple to return empty array and use length==0 here instead of exception
advices = loadXpandResources(rs2, aspectsTemplateName);
} catch (FileNotFoundException e) {
} catch (IOException ex) {
// XXX come up with better handling
Activator.logWarn(ex.getMessage());
} catch (ParserException ex) {
handleParserException(ex);
}
if (advices == null && unadvised.length == 1) {
return unadvised[0];
}
return new CompositeXpandResource(this, unadvised, advices);
}
/**
* XXX: only to simplify tests, should be private or inlined
*/
protected String getAspectsTemplateName(String fullyQualifiedName) {
return ASPECT_PREFIX + fullyQualifiedName;
}
/**
* If the given fully-qualified name is an aspect, transforms it to its "host" fully-qualified name. Otherwise,
* returns the given fully-qualified name.
*/
protected String getNonAspectsTemplateName(String possiblyAspectedFullyQualifiedName) {
if (possiblyAspectedFullyQualifiedName == null) {
return null;
}
if (possiblyAspectedFullyQualifiedName.startsWith(ASPECT_PREFIX)) {
return possiblyAspectedFullyQualifiedName.substring(ASPECT_PREFIX.length());
}
return possiblyAspectedFullyQualifiedName;
}
protected abstract void handleParserException(ParserException ex);
/**
* Readers get closed after parse attempt.
*/
protected XtendResource[] loadXtendResources(Reader[] readers, String fullyQualifiedName) throws IOException, ParserException {
XtendResource[] result = new XtendResource[readers.length];
for (int i = 0; i < readers.length; i++) {
assert readers[i] != null;
try {
result[i] = new XtendResourceParser().parse(readers[i], fullyQualifiedName);
assert result[i] != null; // this is the contract of loadXpandResource
} finally {
try {
readers[i].close();
} catch (Exception ex) {/*IGNORE*/}
}
}
return result;
}
/**
* Readers get closed after parse attempt.
*/
protected XpandResource[] loadXpandResources(Reader[] readers, String fullyQualifiedName) throws IOException, ParserException {
XpandResource[] result = new XpandResource[readers.length];
for (int i = 0; i < readers.length; i++) {
assert readers[i] != null;
try {
result[i] = new XpandResourceParser().parse(readers[i], fullyQualifiedName);
assert result[i] != null; // this is the contract of parse
} finally {
try {
readers[i].close();
} catch (Exception ex) {/*IGNORE*/}
}
}
return result;
}
protected abstract boolean shouldCache();
protected final boolean hasCachedXpand(String fullyQualifiedName) {
return shouldCache() && cachedXpand.containsKey(fullyQualifiedName);
}
protected final boolean hasCachedXtend(String fullyQualifiedName) {
return shouldCache() && cachedXtend.containsKey(fullyQualifiedName);
}
protected final void forgetCachedXpand(String fullyQualifiedName) {
cachedXpand.remove(fullyQualifiedName);
}
protected final void forgetCachedXtend(String fullyQualifiedName) {
cachedXtend.remove(fullyQualifiedName);
}
protected final void forgetAll() {
cachedXpand.clear();
cachedXtend.clear();
}
private static final String ASPECT_PREFIX = "aspects" + SyntaxConstants.NS_DELIM; //$NON-NLS-1$
}