/*
   Copyright 2007 Attila Szegedi

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
package org.dynalang.mop;

import java.util.Map;


/**
 * An interface for objects that are capable of creating alternative 
 * representations for objects, for purposes of converting between types where
 * necessary (usually used for arguments of method invocation and property 
 * setters). It is also capable of invoking callable objects, and retrieving
 * a property from an object. Note that {@link BaseMetaobjectProtocol} extends 
 * this interface.
 * @author Attila Szegedi
 * @version $Id: $
 */
public interface CallProtocol
{
    /**
     * Returns a representation of the specified target object as an object of 
     * the specified target class. Typical supported target classes would be 
     * wrappers for Java primitive types that map to native types of the higher
     * level languages. I.e. if an object is used as a boolean expression, then
     * the language would ask the protocol to interpret it as boolean by 
     * calling <tt>representAs(Boolean.TYPE)</tt>.
     * @param object the object to represent
     * @param targetClass the target class for representation.
     * @return the representation that must be instance of the targetClass, or
     * in case targetClass is primitive, of its adequate boxing class. It can
     * also be a special value to indicate conversion failure: 
     * {@link BaseMetaobjectProtocol.Result#noAuthority} is returned if the 
     * marshaller can not authoritatively decide on a representation; 
     * {@link BaseMetaobjectProtocol.Result#noRepresentation} is returned if 
     * the marshaller can authoritatively decide that the requested 
     * representation is not possible. representation of null should be null, 
     * except when the target class is a primitive type in which case 
     * {@link BaseMetaobjectProtocol.Result#noRepresentation} should be 
     * returned.
     */
    public Object representAs(Object object, Class targetClass);


    /**
     * Retrieves the property value from the target object.
     * @param target the target object
     * @param propertyId the ID of the property. Usually a String or an 
     * Integer, but other property ID types can also be supported.
     * @return the property value for the target object. A null value means 
     * that the protocol authoritatively decided that the value of the property
     * is null. If the protocol decides that the property does not exist, it
     * will return {@link BaseMetaobjectProtocol.Result#doesNotExist}. If the protocol decides that
     * the property exists, but is not readable, it will return 
     * {@link BaseMetaobjectProtocol.Result#notReadable}. If the protocol can not make
     * an authoritative decision, it will return {@link BaseMetaobjectProtocol.Result#noAuthority}.
     */
    public Object get(Object target, Object propertyId);

    /**
     * Calls a callable object with named arguments.
     * @param callProtocol a marshaller that should be used by this
     * metaobject protocol to convert the arguments to conform to expected
     * argument types for the call.
     * @param args the named arguments for the callable object. null must
     * be treated as empty map. Usually, the map keys are strings, but it is
     * possible that some protocols support non-string keys.
     * @param callable the callable object
     * @return the return value of the call, or a special result. 
     * {@link BaseMetaobjectProtocol.Result#notCallable} is returned if the protocol can 
     * authoritatively decide that the target is not a callable, or is not
     * callable with named arguments. {@link BaseMetaobjectProtocol.Result#doesNotExist} is returned
     * if the callable does not exist at all. {@link BaseMetaobjectProtocol.Result#noAuthority} is 
     * returned if the protocol can not authoritatively decide whether the 
     * target is callable.  
     */
    public Object call(Object callable, CallProtocol callProtocol, Map args);
    
    /**
     * Calls a callable object with positional arguments.
     * @param callable the callable object
     * @param callProtocol a marshaller that should be used by this
     * metaobject protocol to convert the arguments to conform to expected
     * argument types for the call.
     * @param args the positional arguments for the callable object. null must
     * be treated as empty array.
     * @return the return value of the call, or a special result. 
     * {@link BaseMetaobjectProtocol.Result#notCallable} is returned if the protocol can 
     * authoritatively decide that the target is not a callable, or is not
     * callable with positional arguments. {@link BaseMetaobjectProtocol.Result#doesNotExist} is 
     * returned if the callable does not exist at all. 
     * {@link BaseMetaobjectProtocol.Result#noAuthority} is returned if the protocol can not 
     * authoritatively decide whether the target is callable.
     */
    public Object call(Object callable, CallProtocol callProtocol, Object... args);
}
