/*
   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.impl;

import java.util.Iterator;
import java.util.Map;

import org.dynalang.mop.CallProtocol;
import org.dynalang.mop.MetaobjectProtocol;

/**
 * A convenient base class for implementing a {@link MetaobjectProtocol} that
 * requires you to only implement {@link MetaobjectProtocolBase} methods on it.
 * @author Attila Szegedi
 * @version $Id: $
 */
public abstract class MetaobjectProtocolBase implements MetaobjectProtocol {
    public Object call(Object target, Object callableId, CallProtocol callProtocol, Map args) {
        Object callable = callProtocol.get(target, callableId);
        if(callable instanceof Result) {
            return callable;
        }
        return callProtocol.call(callable, callProtocol, args);
    }

    public Object call(Object target, Object callableId, CallProtocol callProtocol, Object... args) {
        Object callable = callProtocol.get(target, callableId);
        if(callable instanceof Result) {
            return callable;
        }
        return callProtocol.call(callable, callProtocol, args);
    }

    public Result delete(Object target, long propertyId) {
        return delete(target, Long.valueOf(propertyId));
    }

    public Object get(Object target, long propertyId) {
        return get(target, Long.valueOf(propertyId));
    }
    
    public Boolean has(Object target, long propertyId) {
        return has(target, Long.valueOf(propertyId));
    }

    public Iterator<? extends Object> propertyIds(Object target) {
        final Iterator<Map.Entry> it = properties(target);
        assert it != null : getClass().getName() + " returned null properties iterator";
        return new Iterator<Object>() {
            public boolean hasNext() {
                return it.hasNext();
            }
            public Object next() {
                return it.next().getKey();
            }
            public void remove() {
                it.remove();
            }
        };
    }

    public Result put(Object target, long propertyId, Object value, CallProtocol callProtocol) {
        return put(target, Long.valueOf(propertyId), value, callProtocol);
    }
}
