/** * 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 Corporation - Initial API and implementation */ package net.enilink.komma.model; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; import java.util.Set; import net.enilink.composition.annotations.Iri; import net.enilink.komma.core.IEntityManager; import net.enilink.komma.core.IReference; import net.enilink.komma.core.KommaException; import net.enilink.komma.core.KommaModule; import net.enilink.komma.core.URI; import net.enilink.komma.em.concepts.IOntology; @Iri(MODELS.NAMESPACE + "Model") public interface IModel { /** * A save option that can be used only with {@link #save(Map)} to specify * that the model is to be saved only if the new contents are different from * actual contents; this compares the bytes in the backing store against the * new bytes that would be saved. The value on this option can be either * <code>null</code>, {@link #OPTION_SAVE_ONLY_IF_CHANGED_FILE_BUFFER}, or * {@link #OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER}. */ String OPTION_SAVE_ONLY_IF_CHANGED = "SAVE_ONLY_IF_CHANGED"; /** * A value for {@link #OPTION_SAVE_ONLY_IF_CHANGED} to specify that an * in-memory buffer should be used to compare the new contents with the * actual contents. This will be faster than * {@link #OPTION_SAVE_ONLY_IF_CHANGED_FILE_BUFFER} but will use up more * memory. */ String OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER = "MEMORY_BUFFER"; /** * A value for {@link #OPTION_SAVE_ONLY_IF_CHANGED} to specify that a file * buffer should be used to compare the new contents with the actual * contents. This will be slower than * {@link #OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER} but will use up less * memory. */ String OPTION_SAVE_ONLY_IF_CHANGED_FILE_BUFFER = "FILE_BUFFER"; /** * A load and save option that can be used to specify a content description * object. */ String OPTION_CONTENT_DESCRIPTION = "CONTENT_DESCRIPTION"; /** * A load and save option that can be used to specify the MIME type of the * contents. */ String OPTION_MIME_TYPE = "MIME_TYPE"; /** * A load and save option that can be used to specify the character set * (like UTF-8) of the contents. */ String OPTION_CHARSET = "CHARSET"; /** * Adds an import to the model * * @param uri * @param prefix * @throws KommaException */ void addImport(URI uri, String prefix) throws KommaException; /** * {@link IURIConverter#delete(URI, Map) deletes} the model resource using * the specified options, {@link #unload() unloads} it, and then removes it * from the {@link #getModelSet() containing} model set. * <p> * Options are handled generically as feature-to-setting entries; the model * will ignore options it doesn't recognize. The options could even include * things like an Eclipse progress monitor... * </p> * <p> * An implementation typically uses the {@link IModelSet#getURIConverter URI * converter} of the {@link #getModelSet() containing} resource set to * {@link IURIConverter#delete(URI, Map)} the ontology's {@link #getURI() * URI}. * </p> */ void delete(Map<?, ?> options) throws IOException; /** * Returns all directly imported models. */ Set<URI> getImports(); /** * Returns all imported models, transitive imports included. */ Set<URI> getImportsClosure(); /** * Returns the {@link IEntityManager} manager which is responsible for * loading and modifying the ontology's contents * * @return manager instance */ IEntityManager getManager(); /** * Returns the ontology resource which is managed by this ontology model * * @return ontology resource */ IOntology getOntology(); /** * Returns the containing model set. A model is contained by a model set if * it appears in the {@link IModelSet#getModels models}, i.e., the contents, * of that model set. This reference can only be modified by altering the * contents of the model set directly. * * @return the containing model set, or <code>null</code> if there isn't * one. * @see IModelSet#getModels */ IModelSet getModelSet(); /** * Returns the URI of this model. The URI is normally expected to be * {@link URI#isRelative absolute} and {@link URI#isHierarchical * hierarchical}; document-relative references will not be serialized and * will not be {@link URI#resolve(URI) resolved}, if this is not the case. * * @return the URI of this model, or <code>null</code> if there isn't one. * @see #setURI(URI) * @see URI#isRelative * @see URI#isHierarchical */ URI getURI(); /** * Returns whether the model is loaded. * <p> * This will be <code>false</code> when the model is first * {@link IModelSet#createModel(URI) created} and will be set to * <code>false</code>, when the model is {@link #unload unloaded}. It will * be set to <code>true</code> when the model is {@link #load(Map) loaded}. * </p> * * @return whether the model is loaded. */ boolean isLoaded(); /** * Sets whether this model has been loaded. * <p> * A model is set to be loaded after it is {@link #load(Map) loaded} and * unset to be loaded after it is {@link #unload unloaded}. * </p> * * @param isLoaded * whether this model has been loaded. * @see #isLoaded */ void setLoaded(boolean isLoaded); /** * Returns whether this model has been modified. * <p> * A model is set to be unmodified after it is loaded or saved. * </p> * * @return whether this resource has been modified. * @see #setModified(boolean) */ boolean isModified(); /** * Sets whether this model has been modified. * <p> * A model is set to be unmodified after it is loaded or saved. * </p> * * @param isModified * whether this model has been modified. * @see #isModified */ void setModified(boolean isModified); /** * Loads the model using the specified options. * <p> * Options are handled generically as feature-to-setting entries; the * model will ignore options it doesn't recognize. The options could even * include things like an Eclipse progress monitor... * </p> * <p> * An implementation typically uses the {@link IModelSet#getURIConverter URI * converter} of the {@link #getModelSet() containing} model set to * {@link IURIConverter#createInputStream(URI, Map) create} an input stream, * and then delegates to {@link #load(InputStream, Map) load(InputStream, * Map)}. * </p> * <p> * When the load completes, the {@link #getErrors errors} and * {@link #getWarnings warnings} can be consulted. An implementation will * typically deserialize as much of a document as possible while producing * diagnostics for any problems that are encountered. * </p> * * @param options * the load options. */ void load(Map<?, ?> options) throws IOException; /** * Resolve the given reference in this model * * @param reference * Reference to an {@link IObject} * @return the resolved {@link IObject} */ IObject resolve(IReference reference); /** * Returns the resolved URI for the given local part. * * @param localPart * the local part to resolve. * @return the resolved URI for the given local part. */ URI resolveURI(String localPart); /** * Loads the model from the URI using the specified options. * * @see #load(Map) * @see #load(InputStream) * @param options * the load options. */ void load(URI uri, Map<?, ?> options) throws IOException; /** * Loads the model from the input stream using the specified options. * * @param inputStream * the stream * @param options * the load options. * @see #load(Map) * @see #load(URI) * @see #save(OutputStream, Map) */ void load(InputStream inputStream, Map<?, ?> options) throws IOException; /** * Removes the import from this model * * @param importedOnt * the imported model */ void removeImport(URI importedOnt); /** * Saves the resource using the specified options. * <p> * Options are handled generically as feature-to-setting entries; the * resource will ignore options it doesn't recognize. The options could even * include things like an Eclipse progress monitor... * </p> * <p> * An implementation typically uses the {@link IModelSet#getURIConverter URI * converter} of the {@link #getOntologySet containing} model set to * {@link UIRIConverter#createOutputStream(URI, Map) create} an output * stream, and then delegates to {@link #save(OutputStream, Map) * save(OutputStream, Map)}. * </p> * * @param options * the save options. * @see #save(OutputStream, Map) */ void save(Map<?, ?> options) throws IOException; /** * Saves the model to the output stream using the specified options. * <p> * Usually, {@link #save(Map) save(Map)} is called directly and it calls * this. * </p> * * @param outputStream * the stream * @param options * the save options. * @see #save(Map) * @see #load(InputStream, Map) */ void save(OutputStream outputStream, Map<?, ?> options) throws IOException; /** * Sets the URI of this resource. * * @param uri * the new URI. * @see #getURI */ void setURI(URI uri); /** * Clears the {@link #getErrors errors}, and {@link #getWarnings warnings} * of the model and {@link #isLoaded marks} it as unloaded. */ void unload(); /** * Unloads the manager and internal module. */ void unloadManager(); /** * Returns a list of the errors in the model; each error will be of type * {@link IDiagnostic}. * <p> * These will typically be produced as the model is {@link #load(Map) * loaded}. * </p> * * @return a list of the errors in the resource. * @see #load(Map) */ Set<IDiagnostic> getErrors(); /** * Returns a list of the warnings and informational messages in the model; * each warning will be of type {@link IDiagnostic}. * <p> * These will typically be produced as the model is {@link #load(Map) * loaded}. * </p> * * @return a list of the warnings in the resource. * @see #load(Map) */ Set<IDiagnostic> getWarnings(); /** * A factory for creating resources. * <p> * A factory is implemented to {@link #createResource create} a specialized * type of resource and is typically registered in * {@link IModel.Factory.Registry registry}. * </p> * * @see IModelSet#createModel(URI) */ interface Factory { /** * Creates an model with the given URI and returns it. * <p> * Clients will typically not call this directly themselves; it's called * by the model set to {@link IModelSet#createModel(URI) create} a * model. * </p> * * @param modelSet * the containing model set. * @param uri * the URI. * @return a new model. * @see IModelSet#createModel(URI) */ IModel createModel(IModelSet modelSet, URI uri); /** * A descriptor used by a model factory registry to defer factory * creation. * <p> * The creation is deferred until the factory is * {@link IModel.Factory.Registry#getFactory(URI) fetched} for the first * time. * </p> * * @see IModel.Factory.Registry#getFactory(URI) */ interface IDescriptor { /** * Creates a factory and returns it. * <p> * An implementation may and usually does choose to create only one * instance, which it returns for each call. * </p> * * @return a factory. */ Factory createFactory(); } /** * A registry of model factories. * <p> * A {@link IModel.Factory.IDescriptor descriptor} can be used in place * of an actual {@link IModel.Factory factory} as a value in the map. * </p> * * @see IModelSet#getModelFactoryRegistry() */ interface Registry { /** * Returns the resource factory appropriate for the given URI. * <p> * An implementation will (typically) use the URI's * {@link URI#scheme scheme} to search the * {@link #getProtocolToFactoryMap protocol} map the URI's * {@link URI#fileExtension file extension} to search * {@link #getExtensionToFactoryMap extension} map, and the URI's * {@link URIConverter#contentDescription(URI, Map) content type * identifier} to search the {@link #getContentTypeToFactoryMap() * content type} map. It will * {@link org.eclipse.ModelSetFactory.ecore.resource.Resource.Factory.Descriptor#createFactory * convert} a resulting descriptor into a factory. It may choose to * provide additional mechanisms and algorithms to determine a * factory appropriate for the given URI. * </p> * * @param uri * the URI. * @return the resource factory appropriate for the given URI, or * <code>null</code> if there isn't one. * @see ResourceSet#createModel(URI) */ Factory getFactory(URI uri); /** * Returns the resource factory appropriate for the given URI with * the given {@link URIConverter#contentDescription(URI, Map) * content type} identifier. * <p> * An implementation will (typically) use the URI's * {@link URI#scheme scheme} to search the * {@link #getProtocolToFactoryMap protocol} map the URI's * {@link URI#fileExtension file extension} to search * {@link #getExtensionToFactoryMap extension} map, and the given * content type identifier to search the * {@link #getContentTypeToFactoryMap() content type} map. It will * {@link org.eclipse.ModelSetFactory.ecore.resource.Resource.Factory.Descriptor#createFactory * convert} a resulting descriptor into a factory. It may choose to * provide additional mechanisms and algorithms to determine a * factory appropriate for the given URI. * </p> * * @param uri * the URI. * @param contentType * the content type of the URI or <code>null</code> if a * content type should not be used during lookup. * @return the resource factory appropriate for the given URI with * the content content type, or <code>null</code> if there * isn't one. * @see IModelSet#createModel(URI) */ Factory getFactory(URI uri, String contentType); /** * Returns a map from {@link URI#scheme protocol} to * {@link org.eclipse.ModelSetFactory.ecore.resource.Resource.Factory} * or * {@link org.eclipse.ModelSetFactory.ecore.resource.Resource.Factory.Descriptor} * . * * @return the protocol map. */ Map<String, Object> getProtocolToFactoryMap(); /** * The file extension <code>"*"</code> that matches any extension. * * @see #getExtensionToFactoryMap */ String DEFAULT_EXTENSION = "*"; /** * Returns a map from {@link URI#fileExtension file extension} to * {@link org.eclipse.ModelSetFactory.ecore.resource.Resource.Factory} * or * {@link org.eclipse.ModelSetFactory.ecore.resource.Resource.Factory.Descriptor} * . * <p> * The {@link #DEFAULT_EXTENSION default} file extension * <code>"*"</code> can be registered as a default that matches any * file extension. This is typically reserved for a default factory * that supports XMI serialization; clients are strongly discouraged * from using this feature in the global registry, particularly * those that must function effectively within an Eclipse * environment. * </p> * * @return the file extension map. * @see #DEFAULT_EXTENSION */ Map<String, Object> getExtensionToFactoryMap(); /** * The content type identifier <code>"*"</code> that matches any * content type identifier. * * @see #getContentTypeToFactoryMap() */ String DEFAULT_CONTENT_TYPE_IDENTIFIER = "*"; /** * Returns a map from content type identifier to * {@link org.eclipse.ModelSetFactory.ecore.resource.Resource.Factory} * or * {@link org.eclipse.ModelSetFactory.ecore.resource.Resource.Factory.Descriptor} * . * <p> * The {@link #DEFAULT_CONTENT_TYPE_IDENTIFIER default} content type * identifier <code>"*"</code> can be registered as a default that * matches any content type identifier. This is typically reserved * for a default factory that supports XMI serialization; clients * are strongly discouraged from using this feature in the global * registry, particularly those that must function effectively * within an Eclipse environment. * </p> * * @return the content type identifier map. * @see #DEFAULT_CONTENT_TYPE_IDENTIFIER */ Map<String, Object> getContentTypeToFactoryMap(); } } /** * A noteworthy issue in a document. */ @Iri("http://enilink.net/vocab/komma/models#Diagnostic") interface IDiagnostic { /** * Returns a translated message describing the issue. * * @return a translated message. */ String getMessage(); /** * Returns the source location of the issue. This will typically be just * the {@link IModel#getURI URI} of the ontology containing this * diagnostic. * * @return the location of the issue, or <code>null</code> if it's * unknown. */ String getLocation(); /** * Returns the line location of the issue within the source. Line * <code>1</code> is the first line. * * @return the line location of the issue. */ int getLine(); /** * Returns the column location of the issue within the source. Column * <code>1</code> is the first column. * * @return the column location of the issue. */ int getColumn(); } /** * An internal interface implemented by all models. * * @see IModel#getModelSet * @see IModelSet#getModels */ interface Internal extends IModel { /** * Allows to avoid demand-loading of an imported model, e.g. for * security reasons. * * @param imported * The imported model * @return <code>true</code> if demand-loading should be used, else * <code>false</code>. */ boolean demandLoadImport(URI imported); /** * Returns a module for this model. */ KommaModule getModule(); /** * Returns a module that includes all imported model modules. */ KommaModule getModuleClosure(); /** * Indicates whether the model is currently being loaded. * <p> * This will be <code>true</code> during a call to * {@link #load(InputStream, Map) load(InputStream, Map)}, before * notifications are dispatched. * </p> * * @return whether this model is currently being loaded. */ boolean isLoading(); } /** * An IO exception that wraps another exception. * <p> * Since save and load throw an IO Exception, it may be convenient for an * implementation to wrap another exception in order to throw it as an IO * exception. * </p> */ class IOWrappedException extends IOException { static final long serialVersionUID = 1L; /** * Creates an instance which wraps the given exception. * * @param exception * the exception to wrap. */ public IOWrappedException(Exception exception) { super(exception.getLocalizedMessage()); initCause(exception); } /** * Creates an instance which wraps the given exception. * * @param throwable * the exception to wrap. */ public IOWrappedException(Throwable throwable) { super(throwable.getLocalizedMessage()); initCause(throwable); } } }