/** * Copyright (c) 2002-2010 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.ecore.resource.impl; import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.ContentHandler; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.URIConverter; /** * An extensible implementation of a resource factory registry. */ public class ResourceFactoryRegistryImpl implements Resource.Factory.Registry { /** * The protocol map. */ protected Map<String, Object> protocolToFactoryMap = new HashMap<String, Object>(); /** * The extension map. */ protected Map<String, Object> extensionToFactoryMap = new HashMap<String, Object>(); /** * The content type identifier map. */ protected Map<String, Object> contentTypeIdentifierToFactoryMap = new HashMap<String, Object>(); /** * Creates an instance. */ public ResourceFactoryRegistryImpl() { super(); } /** * Returns the resource factory appropriate for the given URI. * <p> * This implementation does the {@link org.eclipse.emf.ecore.resource.Resource.Factory.Registry#getFactory(URI) typical} thing. * It will delegate to {@link #delegatedGetFactory(URI, String)} * in the case that the typical behaviour doesn't produce a result; * clients are encouraged to override that method only. * </p> * @param uri the URI. * @return the resource factory appropriate for the given URI. * @see org.eclipse.emf.ecore.resource.ResourceSet#createResource(URI) */ public Resource.Factory getFactory(URI uri) { return convert(getFactory(uri, protocolToFactoryMap, extensionToFactoryMap, contentTypeIdentifierToFactoryMap, ContentHandler.UNSPECIFIED_CONTENT_TYPE, true)); } /** * Returns the resource factory appropriate for the given URI. * <p> * This implementation does the {@link org.eclipse.emf.ecore.resource.Resource.Factory.Registry#getFactory(URI, String) typical} thing. * It will delegate to {@link #delegatedGetFactory(URI, String)} * in the case that the typical behaviour doesn't produce a result; * clients are encouraged to override that method only. * </p> * @param uri the URI. * @return the resource factory appropriate for the given URI. * @see org.eclipse.emf.ecore.resource.ResourceSet#createResource(URI) */ public Resource.Factory getFactory(URI uri, String contentType) { return convert(getFactory(uri, protocolToFactoryMap, extensionToFactoryMap, contentTypeIdentifierToFactoryMap, contentType, true)); } public static Resource.Factory convert(Object resourceFactory) { return resourceFactory instanceof Resource.Factory.Descriptor ? ((Resource.Factory.Descriptor)resourceFactory).createFactory() : (Resource.Factory)resourceFactory; } protected Object getFactory (URI uri, Map<String, Object> protocolToFactoryMap, Map<String, Object> extensionToFactoryMap, Map<String, Object> contentTypeIdentifierToFactoryMap, String contentTypeIdentifier, boolean delegate) { Object resourceFactory = null; if (!protocolToFactoryMap.isEmpty()) { resourceFactory = protocolToFactoryMap.get(uri.scheme()); } if (resourceFactory == null) { boolean extensionToFactoryMapIsEmpty = extensionToFactoryMap.isEmpty(); if (!extensionToFactoryMapIsEmpty) { resourceFactory = extensionToFactoryMap.get(uri.fileExtension()); } if (resourceFactory == null) { boolean contentTypeIdentifierToFactoryMapIsEmpty = contentTypeIdentifierToFactoryMap.isEmpty(); if (!contentTypeIdentifierToFactoryMapIsEmpty) { if (ContentHandler.UNSPECIFIED_CONTENT_TYPE.equals(contentTypeIdentifier)) { contentTypeIdentifier = getContentTypeIdentifier(uri); } if (contentTypeIdentifier != null) { resourceFactory = contentTypeIdentifierToFactoryMap.get(contentTypeIdentifier); } } if (resourceFactory == null) { if (!extensionToFactoryMapIsEmpty) { resourceFactory = extensionToFactoryMap.get(Resource.Factory.Registry.DEFAULT_EXTENSION); } if (resourceFactory == null) { if (!contentTypeIdentifierToFactoryMapIsEmpty) { resourceFactory = contentTypeIdentifierToFactoryMap.get(Resource.Factory.Registry.DEFAULT_CONTENT_TYPE_IDENTIFIER); } if (resourceFactory == null && delegate) { resourceFactory = delegatedGetFactory(uri, contentTypeIdentifier); } } } } } return resourceFactory; } protected String getContentTypeIdentifier(URI uri) { try { Map<String, ?> contentDescription = getURIConverter().contentDescription(uri, getContentDescriptionOptions()); return (String)contentDescription.get(ContentHandler.CONTENT_TYPE_PROPERTY); } catch (IOException e) { return null; } } /** * Returns the URI converter that's used to {@link URIConverter#contentDescription(URI, Map) compute} the content type identifier. * @return the URI converter that's used to compute the content type identifier. */ protected URIConverter getURIConverter() { return URIConverter.INSTANCE; } /** * A constant read only map of {@link URIConverter#contentDescription(URI, Map) options} used to request just the {@link ContentHandler#CONTENT_TYPE_PROPERTY content type}. */ protected static final Map<?, ?> CONTENT_DESCRIPTION_OPTIONS; static { Map<Object, Object> contentDescriptionOptions = new HashMap<Object, Object>(); Set<String> requestedProperties = new HashSet<String>(); requestedProperties.add(ContentHandler.CONTENT_TYPE_PROPERTY); contentDescriptionOptions.put(ContentHandler.OPTION_REQUESTED_PROPERTIES, requestedProperties); CONTENT_DESCRIPTION_OPTIONS = Collections.unmodifiableMap(contentDescriptionOptions); } /** * Returns the default options used to {@link URIConverter#contentDescription(URI, Map) compute} the content type identifier. * @return the default options used to compute the content type identifier. */ protected Map<?, ?> getContentDescriptionOptions() { return CONTENT_DESCRIPTION_OPTIONS; } /** * Returns the resource factory appropriate for the given URI and {@link ContentHandler#CONTENT_TYPE_PROPERTY content type identifier}, when standard alternatives fail. * <p> * This implementation calls {@link #delegatedGetFactory(URI)}; * clients are encouraged to override it. * </p> * @param uri the URI. * @param contentTypeIdentifier the {@link ContentHandler#CONTENT_TYPE_PROPERTY content type identifier}. * @return the resource factory appropriate for the given URI and content type identifier. * @see #getFactory(URI) */ protected Resource.Factory delegatedGetFactory(URI uri, String contentTypeIdentifier) { return delegatedGetFactory(uri); } /** * Returns the resource factory appropriate for the given URI, when standard alternatives fail. * <p> * This implementation returns <code>null</code>; * clients are encouraged to override {@link #delegatedGetFactory(URI, String)} instead. * </p> * @param uri the URI. * @return the resource factory appropriate for the given URI. * @see #getFactory(URI) * @deprecated since 2.4 */ @Deprecated protected Resource.Factory delegatedGetFactory(URI uri) { return null; } /* * Javadoc copied from interface. */ public Map<String, Object> getExtensionToFactoryMap() { return extensionToFactoryMap; } /* * Javadoc copied from interface. */ public Map<String, Object> getProtocolToFactoryMap() { return protocolToFactoryMap; } /* * Javadoc copied from interface. */ public Map<String, Object> getContentTypeToFactoryMap() { return contentTypeIdentifierToFactoryMap; } }