Package org.openquark.cal.services

Source Code of org.openquark.cal.services.ProgramModelManager

/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*
*     * Neither the name of Business Objects nor the names of its contributors
*       may be used to endorse or promote products derived from this software
*       without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/


/*
* ProgramModelManager.java
* Creation date: Nov 7, 2005.
* By: Edward Lam
*/
package org.openquark.cal.services;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.openquark.cal.compiler.Compiler;
import org.openquark.cal.compiler.CompilerMessage;
import org.openquark.cal.compiler.CompilerMessageLogger;
import org.openquark.cal.compiler.EntryPointGenerator;
import org.openquark.cal.compiler.ForeignContextProvider;
import org.openquark.cal.compiler.MessageKind;
import org.openquark.cal.compiler.ModuleName;
import org.openquark.cal.compiler.ModuleSourceDefinition;
import org.openquark.cal.compiler.ModuleSourceDefinitionGroup;
import org.openquark.cal.compiler.ModuleTypeInfo;
import org.openquark.cal.compiler.ProgramModifier;
import org.openquark.cal.compiler.QualifiedName;
import org.openquark.cal.compiler.TypeChecker;
import org.openquark.cal.machine.CALExecutor;
import org.openquark.cal.machine.MachineFunction;
import org.openquark.cal.machine.MachineStatistics;
import org.openquark.cal.machine.Module;
import org.openquark.cal.machine.ProgramManager;
import org.openquark.cal.machine.StatusListener;
import org.openquark.cal.machine.Program.ProgramException;
import org.openquark.cal.runtime.ExecutionContext;
import org.openquark.cal.runtime.ExecutionContextProperties;
import org.openquark.cal.runtime.MachineType;



/**
* This class presents a higher-level abstraction to the program manager.
* It can manage queries and changes to the program without having to know about a program manager.
* @author Edward Lam
*/
public class ProgramModelManager {
   
    /** The program manager. */
    private final ProgramManager programManager;
   
    /** The set of StatusListeners that want to listen to program generation changes in the program model. */
    private final Set<StatusListener> statusListeners;

    /**
     * Constructor for a program model manager. This is intended to be called
     * by the unit testing infrastructure to specify a custom ProgramManager.
     *
     * @param programManager the ProgramManager for this ProgramModelManager.
     */
    public ProgramModelManager(ProgramManager programManager) {
       
        if (programManager == null) {
            throw new NullPointerException("Argument 'programManager' must not be null.");
        }
       
        this.programManager = programManager;
        this.statusListeners = Collections.synchronizedSet(new HashSet<StatusListener>());
    }
   
    /**
     * Makes a new disposable copy of the program modifier.
     * @param options - the values for compiler options
     * @return a copy of the program modifier, either a new one, or the private copy held by this workspace manager.
     */
    protected ProgramModifier makeProgramModifier(CompilationOptions options) {
       
        ProgramModifier newProgramModifier = programManager.makeProgramModifier();
       
        for (final StatusListener statusListener : statusListeners) {
            newProgramModifier.addStatusListener(statusListener);
        }
       
        if (options != null) {
            newProgramModifier.setForceCodeRegen(options.isForceCodeRegeneration());
            newProgramModifier.setForImmediateUse(options.isForImmediateUse());
            newProgramModifier.setIgnoreCompiledModuleInfo(options.isIgnoreCompiledModuleInfo());
            newProgramModifier.setForeignContextProvider(options.getCustomForeignContextProvider());
        }
       
        return newProgramModifier;
    }

    /**
     * Makes a new disposable copy of the entry point generator.
     * @param options - the values for compiler options
     * @return a new entry point generator.
     */
    private EntryPointGenerator makeEntryPointGenerator(CompilationOptions options) {
       
        EntryPointGenerator newEntryPointGenerator = programManager.makeEntryPointGenerator();
       
        for (final StatusListener statusListener : statusListeners) {
            newEntryPointGenerator.addStatusListener(statusListener);
        }
       
        if (options != null) {
            newEntryPointGenerator.setForceCodeRegen(options.isForceCodeRegeneration());
            newEntryPointGenerator.setForImmediateUse(options.isForImmediateUse());
           
            // TODOEL: Should we provide some kind of warning if inapplicable options are set?
            // eg. Can't override the foreign context for a module.
            //     ignoreCompiledModuleInfo doesn't apply.
        }
       
        return newEntryPointGenerator;
    }

    /**
     * Get the Compiler for this manager.
     * @return Compiler
     */
    public Compiler getCompiler() {
        return getCompiler(new CompilationOptions());
    }
   
    /**
     * Get the Compiler for this manager.
     *
     * @param compilationOptions the compilation options for the compiler.
     * @return Compiler
     */
    public Compiler getCompiler(CompilationOptions compilationOptions) {
        Assert.isNotNullArgument(compilationOptions, "compilationOptions");
        return makeEntryPointGenerator(compilationOptions);
    }

    /**
     * @return a type checker associated with this manager.
     */
    public TypeChecker getTypeChecker() {
        // Make a new disposable copy of the type checker.
        return programManager.makeTypeCheckerImpl();
    }
   
    /**
     * Factory method for creating a machine-specific execution context.
     * @param properties the ExecutionContextProperties instance encapsulating an immutable map of key-value pairs which is exposed
     *                   as system properties from within CAL.
     *
     * @return a new CALExecutor.Context instance.
     */
    public ExecutionContext makeExecutionContext(ExecutionContextProperties properties) {
        return programManager.makeExecutionContext(properties);
    }
   
    /**
     * Factory method for creating a machine-specific execution context with default values for
     * the execution context's properties.
     *
     * @return a new CALExecutor.Context instance.
     */
    public ExecutionContext makeExecutionContextWithDefaultProperties() {
        return programManager.makeExecutionContext(makeDefaultExectionContextProperties());
    }

    /**
     * Factory method for creating a machine-specific executor.
     *
     * @param context
     *            the execution context to be used by the executor.
     * @return a new CALExecutor instance.
     */
    public CALExecutor makeExecutor(ExecutionContext context) {
        return programManager.makeExecutor(context);
    }
   
    /**
     * Factory method for creating a machine-specific executor with a new
     * execution context.
     * @param properties the ExecutionContextProperties instance encapsulating an immutable map of key-value pairs which is exposed
     *                   as system properties from within CAL.
     *
     * @return a new CALExecutor instance with a new execution context.
     */
    public CALExecutor makeExecutorWithNewContext(ExecutionContextProperties properties) {
        return programManager.makeExecutor(programManager.makeExecutionContext(properties));
    }
   
    /**
     * Factory method for creating a machine-specific executor with a new
     * execution context and default values for the execution context's properties.
     *
     * @return a new CALExecutor instance with a new execution context.
     */
    public CALExecutor makeExecutorWithNewContextAndDefaultProperties() {
        return programManager.makeExecutor(programManager.makeExecutionContext(makeDefaultExectionContextProperties()));
    }
   
    /**
     * @return a ExecutionContextProperties instance encapsulating the default values for the execution context's properties.
     */
    private ExecutionContextProperties makeDefaultExectionContextProperties() {
        ExecutionContextProperties.Builder propertiesBuilder = new ExecutionContextProperties.Builder();
        ExecutionContextProperties defaultProperties = propertiesBuilder.toProperties();
        return defaultProperties;
    }
   
    /**
     * Compile the modules in this manager.
     * @param logger the logger used to log error messages.
     * @param dirtyModulesOnly if true, only dirty (uncompiled or changed) modules will be compiled.
     * @param statusListener a listener, possibly null, for the status of the compilation process
     */
    public void compile(ModuleSourceDefinitionGroup definitionGroup, CompilerMessageLogger logger, boolean dirtyModulesOnly, StatusListener statusListener) {
        compile(definitionGroup, logger, dirtyModulesOnly, statusListener, new CompilationOptions());
    }

    /**
     * Compile the modules in this manager.
     * @param logger the logger used to log error messages.
     * @param dirtyModulesOnly if true, only dirty (uncompiled or changed) modules will be compiled.
     * @param statusListener a listener, possibly null, for the status of the compilation process
     * @param options - values for compilation options
     */
    public void compile(ModuleSourceDefinitionGroup definitionGroup, CompilerMessageLogger logger,
            boolean dirtyModulesOnly, StatusListener statusListener, CompilationOptions options) {
       
        if (definitionGroup == null) {
            logger.logMessage(new CompilerMessage(new MessageKind.Fatal.CouldNotFindWorkspaceDefinition()));
            return;
        }
       
        ProgramModifier newProgramModifier = makeProgramModifier(options);
       
        if (statusListener != null) {
            newProgramModifier.addStatusListener(statusListener);
        }
       
        try {
            newProgramModifier.compile(definitionGroup, logger, dirtyModulesOnly);
           
        } finally {
            if (statusListener != null) {
                newProgramModifier.removeStatusListener(statusListener);
            }
        }
    }
   
    /**
     * @return the program manager.
     */
    protected final ProgramManager getProgramManager() {
        // TODOEL: remove this method!(?)
        return programManager;
    }
   
    /**
     * Compile a module to the current program.
     *   Dependent modules will be removed from the program.
     * @param sourceDef the ModuleSourceDefinition to compile.
     * @param logger the logger to use during the compile.
     * @return the highest error condition experienced
     */
    public CompilerMessage.Severity makeModule (ModuleSourceDefinition sourceDef, CompilerMessageLogger logger) {
        return makeModule(sourceDef, logger, new CompilationOptions());
    }

    /**
     * Compile a module to the current program.
     *   Dependent modules will be removed from the program.
     * @param sourceDef the ModuleSourceDefinition to compile.
     * @param logger the logger to use during the compile.
     * @param options - values for the compilation options
     * @return the highest error condition experienced
     */
    public CompilerMessage.Severity makeModule (ModuleSourceDefinition sourceDef, CompilerMessageLogger logger, CompilationOptions options) {
       
        // We want to always force code regeneration when compiling a module (vs. compiling the entire workspace).
        // This is partly to workaround the issue where compiling multiple SourceModelModuleSource
        // objects with the same timestamp back-to-back would erroneously supress the code
        // generation for the second and subsequent compilation attempts.
        CompilationOptions modifiedOptions = new CompilationOptions(options);
        modifiedOptions.setForceCodeRegeneration(true);
       
        ProgramModifier pm = makeProgramModifier(modifiedOptions);
        return pm.compile (sourceDef, logger);
    }

    /**
     * Compile module(s) to the current program.
     *   Dependent modules will be removed if not included.
     * @param moduleNames a list of the names of the changed modules.
     * @param definitionGroup the definition group from which the module definitions may be retrieved.
     * @param logger the logger to use during the compile.
     * @return the highest error condition experienced
     */
    public CompilerMessage.Severity makeModules (ModuleName[] moduleNames, ModuleSourceDefinitionGroup definitionGroup, CompilerMessageLogger logger) {
        return makeModules (moduleNames, definitionGroup, logger, new CompilationOptions());
    }
   
    /**
     * Compile module(s) to the current program.
     *   Dependent modules will be removed if not included.
     * @param moduleNames a list of the names of the changed modules.
     * @param definitionGroup the definition group from which the module definitions may be retrieved.
     * @param logger the logger to use during the compile.
     * @param options - the values for compilation options
     * @return the highest error condition experienced
     */
    public CompilerMessage.Severity makeModules (ModuleName[] moduleNames, ModuleSourceDefinitionGroup definitionGroup, CompilerMessageLogger logger, CompilationOptions options) {
       
        // We want to always force code regeneration when compiling a given set of modules (vs. compiling the entire workspace).
        // This is partly to workaround the issue where compiling multiple SourceModelModuleSource
        // objects with the same timestamp back-to-back would erroneously supress the code
        // generation for the second and subsequent compilation attempts.
        CompilationOptions modifiedOptions = new CompilationOptions(options);
        modifiedOptions.setForceCodeRegeneration(true);
       
        ProgramModifier pm = makeProgramModifier(modifiedOptions);
        return pm.compile (moduleNames, definitionGroup, logger);
    }

    /**
     * @param listener StatusListener
     */
    public void addStatusListener(StatusListener listener) {
        statusListeners.add(listener);
    }

    /**
     * @param listener StatusListener
     */
    public void removeStatusListener(StatusListener listener) {
        statusListeners.remove(listener);
    }

    /**
     * Discarded any cached (memoized) results in this program.
     * @param context the context with which the cached results are associated.
     */
    public void resetCachedResults(ExecutionContext context) {
        programManager.resetCachedResults (context);
    }
   
    /**
     * Discard any cached (memoized) results in the named module and any dependent modules.
     * @param moduleName
     * @param context the context with which the cached results are associated.
     */
    public void resetCachedResults(ModuleName moduleName, ExecutionContext context) {
        programManager.resetCachedResults (moduleName, context);
    }

    /**
     * Discarded the machine state, including any cached (memoized) results in this program.
     * @param context the context with which the machine state is associated.
     */
    public void resetMachineState(ExecutionContext context) {
        programManager.resetMachineState(context);
    }
   
    /**
     * Discard the machine state, including any cached (memoized) results in the named module and any dependent modules.
     * @param moduleName
     * @param context the context with which the machine state is associated.
     */
    public void resetMachineState(ModuleName moduleName, ExecutionContext context) {
        programManager.resetMachineState(moduleName, context);
    }

    /**
     * Remove a module from the program.
     * Its dependents will also be removed.
     *
     * @param moduleName the name of the module to remove.
     * @return whether removing the module was successful.
     */
    public final boolean removeModule (ModuleName moduleName) {
        makeProgramModifier(new CompilationOptions()).removeModule(moduleName, true);
        return true;
    }
   
    /**
     *
     * @param targetModule
     * @return the names of the dependent modules.
     */
    public Set<ModuleName> getDependentModuleNames (ModuleName targetModule) {
        return programManager.getSetOfDependentModuleNames(targetModule, true);
    }
   
    /**
     *
     * @param moduleName
     * @return type info for the named module.  Null if module doesn't exist.
     */
    public ModuleTypeInfo getModuleTypeInfo (ModuleName moduleName) {
        return programManager.getModuleTypeInfo(moduleName);
    }
   
    /**
     * Gets the module with a given moduleName.
     * @return the module with a given module name
     * @param name  the module name
     */
    public Module getModule(ModuleName name) {
        return programManager.getModule(name);
    }

    /**
     * Return a list of Module object for modules contained the ProgramManager instance
     * encapsulated by this ProgramModleManager.
     *
     * @return a list of Module objects for the modules in this program.
     */
    public List<Module> getModules() {
        return programManager.getModules();
    }
   
    /**
     * Returns true iff the specified module is in the Program instance
     * encapsulated by this WorkspaceManager.
     *
     * @param moduleName
     *            the name of the module to check.
     * @return true iff the specified module is in the program.
     */
    public boolean hasModuleInProgram(ModuleName moduleName) {
        // this is purely a query on the program, so we do not check whether the module
        // is in the workspace
        return programManager.containsModule(moduleName);
    }
   
    /**
     * Returns the names of the modules contained by the Program instance
     * encapsulated by this WorkspaceManager.
     *
     * @return an array of module names for the modules in the program.
     */
    public ModuleName[] getModuleNamesInProgram() {
        // this is purely a query on the program, and differs in semantics from
        // the method getModuleNames(), which returns the names of the modules in
        // the workspace rather than the program
        return programManager.getModuleNames();
    }
   
    /**
     * Returns the number of functions in the specified module.
     *
     * @param moduleName
     *            the name of the module.
     * @return the number of functions in the specified module, or 0 if the
     *         module is not in the program.
     */
    public int getNFunctionsInModule(ModuleName moduleName) {
        // this is purely a query on the program, so we do not check whether the module
        // is in the workspace
        return programManager.getNFunctionsInModule(moduleName);
    }
   
    /**
     * Retrieves the specified machine function.
     *
     * @param functionName
     *            the qualified name of the function.
     * @return the specified machine function, or null if it does not exist.
     * @throws ProgramException
     *             if the program does not contain the module for the function.
     */
    public MachineFunction getMachineFunction(QualifiedName functionName) throws ProgramException {
        return programManager.getMachineFunction(functionName);
    }
      
   
    /**
     * Returns the machine type associated with this WorkspaceManager.
     *
     * @return the machine type.
     */
    public MachineType getMachineType() {
        return programManager.getMachineType();
    }

    /**
     * @return the machine statistics associated with this program.
     */
    public MachineStatistics getMachineStatistics() {
        return programManager.getMachineStatistics();
    }
   
    /**
     * @param moduleName
     * @return the machine statistics associated with the given module.
     */
    public MachineStatistics getMachineStatisticsForModule(ModuleName moduleName) {
        return programManager.getMachineStatisticsForModule(moduleName);
    }
   
    /**
     * A class to encapsulate the various compilation options
     * when compiling a module or adjunct.
     * @author rcypher
     */
    public static class CompilationOptions {
        /** Set to true if all existing generated code should be discarded and regenerated. */
        private boolean forceCodeRegeneration;
       
        /** Set to true if any compiled module files (i.e. type info etc.) should be ignored.
         * This is used in situations where we want to force compilation of all modules
         * without necessarily forcing re-generation of machine specific code.
         * This is useful in situation where the user has manually deleted/modified
         * the generated machine-specific code. */
        private boolean ignoreCompiledModuleInfo;
       
        /** Indicates to the compiler/code generator that the entities being compiled will be used immediately. */
        private boolean forImmediateUse;
       
        /** Any custom foreign context provider specified by the client. */
        private ForeignContextProvider customForeignContextProvider;
       
        public CompilationOptions () {
        }
       
        /**
         * Copy-constructor for CompilationOptions.
         *
         * This copy-constructor is meant to facilitate the task of making a
         * copy of an existing CompilationOptions instance so that the
         * compilation options can be modified without affecting the original
         * copy.
         *
         * @param other
         *            the CompilationOptions instance to be copied.
         */
        public CompilationOptions(CompilationOptions other) {
            this.forceCodeRegeneration = other.forceCodeRegeneration;
            this.ignoreCompiledModuleInfo = other.ignoreCompiledModuleInfo;
            this.forImmediateUse = other.forImmediateUse;
            this.customForeignContextProvider = other.customForeignContextProvider;
        }
       
        /**
         * @return Returns the forceCodeRegeneration.
         */
        public boolean isForceCodeRegeneration() {
            return forceCodeRegeneration;
        }
        /**
         * @param forceCodeRegeneration The forceCodeRegeneration to set.
         */
        public void setForceCodeRegeneration(boolean forceCodeRegeneration) {
            this.forceCodeRegeneration = forceCodeRegeneration;
        }
        /**
         * @return Returns the forImmediateUse.
         */
        public boolean isForImmediateUse() {
            return forImmediateUse;
        }
        /**
         * @param forImmediateUse The forImmediateUse to set.
         */
        public void setForImmediateUse(boolean forImmediateUse) {
            this.forImmediateUse = forImmediateUse;
        }

        /**
         * @return Returns the ignoreCompiledModuleInfo.
         */
        public boolean isIgnoreCompiledModuleInfo() {
            return ignoreCompiledModuleInfo;
        }
       
        /**
         * @param ignoreCompiledModuleInfo The ignoreCompiledModuleInfo to set.
         */
        public void setIgnoreCompiledModuleInfo(boolean ignoreCompiledModuleInfo) {
            this.ignoreCompiledModuleInfo = ignoreCompiledModuleInfo;
        }

       
        /**
         * @return Any custom foreign context provider specified by the client.  Null if not specified.
         */
        public ForeignContextProvider getCustomForeignContextProvider() {
            return customForeignContextProvider;
        }
       
        /**
         * @param customForeignContextProvider Set the custom foreign context provider to use.  Null to use the default.
         * Note that in most cases it is sensible to set this as null.
         * This is provided as a way for the Eclipse dev tools to provide context not visible to the compiler.
         */
        public void setCustomForeignContextProvider(ForeignContextProvider customForeignContextProvider) {
            this.customForeignContextProvider = customForeignContextProvider;
        }
    }
}
TOP

Related Classes of org.openquark.cal.services.ProgramModelManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.