| /* |
| * 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$ |
| } |