⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oaamapper.java

📁 SRI international 发布的OAA框架软件
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
// $CALOLSI$
/*
 * #=========================================================================
 * # Copyright 2004 SRI International.  All rights reserved.
 * #
 * # The material contained in this file is confidential and proprietary to SRI
 * # International and may not be reproduced, published, or disclosed to others
 * # without authorization from SRI International.
 * #
 * # DISCLAIMER OF WARRANTIES
 * #
 * # SRI International MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 * # SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
 * # LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * # PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SRI International SHALL NOT BE
 * # LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * # OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
 * #=========================================================================
 * Author : evans
 * Date: May 10, 2004
 * Time: 11:07:01 AM
 */
package com.sri.oaa2.mapper;

import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;

import com.sri.oaa2.icl.*;
import com.sri.oaa2.lib.LibOaa;
import com.sri.oaa2.lib.OAAEventListener;

import org.apache.log4j.Logger;

/**
 * OAAMapper maps OAA solvable calls to Java function calls, and maps the results back.
 * It takes an XML OAAMapper mapping file and a set of Java objects that the solvables are
 * executed over.  It then can act as an OAAEventListener and respond to OAA solvables directly,
 * or it can be passed pieces of ICL to act upon.<p>
 * <p/>
 * Function calls made through the callFunction() or doOAAEvent() methods are not synchronized, so
 * Java objects to which these calls are mapped must be thread-safe.
 */
public class OAAMapper
        implements OAAEventListener
{
    private Logger logger = Logger.getLogger(super.getClass());
    private List solvableObjects = new LinkedList();
    private IclMapping iclMapping;
    private LibOaa libOaa;

    /**
     * @param iclMapping
     */
    public OAAMapper(IclMapping iclMapping)
    {
        this.iclMapping = iclMapping;
    }

    /**
     * @param mappingFile
     * @throws MappingException
     */
    public OAAMapper(InputStream mappingFile)
            throws MappingException
    {
        IclMappingParser iclMappingParser = new IclMappingParser();
        iclMapping = iclMappingParser.parse(mappingFile);
    }

    /**
     * @param mappingFile
     * @throws MappingException
     */
    public OAAMapper(Reader mappingFile)
            throws MappingException
    {
        IclMappingParser iclMappingParser = new IclMappingParser();
        iclMapping = iclMappingParser.parse(mappingFile);
    }

    /**
     * Adds an object upon which callFunction() and doOAAEvent function calls are invoked.
     *
     * @param o
     */
    public void addSolvableObject(Object o)
    {
        solvableObjects.add(o);
    }

    /**
     * Creates a proxy object that implements the specified interfaces, translates calls on those
     * interfaces into OAA solvable calls, and translates the results into Java objects.  The returned object
     * can be cast to any of the specified interfaces, and functions on thos interfaces are callable if the
     * functions have a mapping in the XML OAAMapper file and if the specified LibOaa object is connected to
     * an OAA facilitator.
     *
     * @param proxyInterfaces
     * @param oaaFacilitator
     * @return
     */
    public Object createOAAProxy(Class[] proxyInterfaces, LibOaa oaaFacilitator)
    {
        OAAProxy oaaProxy = new OAAProxy(this, oaaFacilitator);
        Object proxy = Proxy.newProxyInstance(super.getClass().getClassLoader(), proxyInterfaces, oaaProxy);
        return proxy;
    }

    /**
     * Given the result of callFunction, convert it to an OAA answer and append to list o
     * answers.  Handles the special case where function returns null as a way of signaling
     * failure.
     *
     * @param origGoal the original OAA goal that this function call is solving
     * @param result   from callFunction
     * @param answers  Will append the result to this list.  Or, if function returns null
     *                 will do nothing.
     */
    private void answerFromResult(IclTerm origGoal, FunctionBinding functionBinding, Object result, IclList answers)
            throws Exception
    {
        // this is a hack because .clone() obliterates IclVar names:
        IclTerm answer = IclUtils.fromString(origGoal.toString());
        if(functionBinding.getFunctionMapping().isReturnsResult())
        {
            // As a special feature.  If function returns a result, it can return null
            // as a way of signaling that it found no solutions.  So, don't add any
            // solution to the return list.
            if(result == null)
            {
                return;
            }

            if(logger.isDebugEnabled())
                logger.debug("Result from " + functionBinding.getFunctionMapping().getFunctionSignature().getName() +
                        ": " + result);
            IclTerm iclResult = javaToIcl(result);
            ResultSetter resultSetter = new ResultSetter(iclResult);
            resultSetter.traverse(functionBinding.getFunctionMapping().getIcl(), answer);
        }

        answers.add(answer);
    }

    /**
     * Maps an OAA solvable to a function call, and parses and returns the result.
     */
    public boolean doOAAEvent(final IclTerm goal, IclList params, IclList answers)
    {
        try
        {
            final FunctionBinding functionBinding = findFunctionBinding(goal);
            if(logger.isDebugEnabled())
                logger.debug("Matched " + goal + " to function " +
                        functionBinding.getFunctionMapping().getFunctionSignature());

            // Oaa Delay returning results and start new thread to call the function
            // and return the delayed results when done.
            if(functionBinding.getFunctionMapping().isOwnThread())
            {
                final String oaaSolvableId = "OaaMap" + Long.toString(System.currentTimeMillis());
                boolean res = libOaa.oaaDelaySolution(oaaSolvableId);
                if(res)
                {
                    new Thread(new Runnable()
                    {
                        public void run()
                        {
                            try
                            {
                                IclList answers = new IclList();
                                Object result = callFunction(goal, functionBinding);
                                answerFromResult(goal, functionBinding, result, answers);
                                if(!libOaa.oaaReturnDelayedSolutions(oaaSolvableId, answers))
                                {
                                    logger.error("Could not oaaReturnDelayedSolutions for goal: " + goal);
                                }
                            }
                            catch(Exception e)
                            {
                                logger.error("Could not call function for goal:" + goal, e);
                            }

                        }
                    }).start();
                }
                else
                {
                    logger.error("Could not oaaDelaySolution for goal: " + goal);
                    return false;
                }

            }
            // Just call the function directly.  No threads necessary.
            else
            {
                Object result = callFunction(goal, functionBinding);
                answerFromResult(goal, functionBinding, result, answers);
            }
            return true;
        }
        catch(Exception e)
        {
            logger.error("Error invoking solvable " + goal, e);
        }
        return false;
    }

    /**
     * Calls the function indicated by the solvable.
     *
     * @param goal
     * @return
     * @throws MappingException
     */
    public Object callFunction(IclTerm goal)
            throws MappingException
    {
        FunctionBinding functionBinding = findFunctionBinding(goal);
        if(logger.isDebugEnabled())
            logger.debug(
                    "Matched " + goal + " to function " + functionBinding.getFunctionMapping().getFunctionSignature());
        return callFunction(goal, functionBinding);
    }

    public IclTerm createSolvable(Class functionClass, Method functionSignature, Object[] parameters)
            throws MappingException
    {
        try
        {
            FunctionMapping functionMapping = null;
            for(int i = 0; i < iclMapping.getFunctionMappings().length && functionMapping == null; i++)
            {
                FunctionMapping currentMapping = iclMapping.getFunctionMappings()[i];
                if(currentMapping.getFunctionClass().isAssignableFrom(functionClass) &&
                        currentMapping.getFunctionSignature().equals(functionSignature) &&
                        currentMapping.getParameters().length == parameters.length)
                    functionMapping = currentMapping;
            }
            if(functionMapping == null)
                throw new MappingException("No function mapping found for " + functionClass + " " + functionSignature);

            // TODO: hack b/c of ICL variable problems;
            IclTerm solvable = IclUtils.fromString(functionMapping.getFunctionSignature().toString());

            // set parameters:
            Map parameterMap = new HashMap();
            for(int i = 0; i < functionMapping.getParameters().length; i++) parameterMap.put("Arg" + i, parameters[i]);
            PropertySetter propertySetter = new PropertySetter(parameterMap);
            propertySetter.traverse(solvable);

            return solvable;
        }
        catch(MappingException me)
        {
            throw me;
        }
        catch(Exception e)
        {
            throw new MappingException(
                    "Error creating solvable for " + functionClass + " " + functionSignature + ": " + e, e);
        }
    }

    /**
     * Maps a Java object to ICL as indicated by the mapping file.
     *
     * @param value
     * @return
     * @throws MappingException
     */
    public IclTerm javaToIcl(Object value)
            throws MappingException
    {
        try
        {
            if(value == null) throw new MappingException("Null object cannot be mapped");
            else if(value instanceof String)
                return new IclStr((String)value);
            else if(value instanceof Float)
                return new IclFloat((Float)value);
            else if(value instanceof Double)
                return new IclFloat((Double)value);
            else if(value instanceof Integer)
                return new IclInt(((Integer)value).intValue());
            else if(value instanceof Long)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -