LocalObjectServer.java

/***************************************************************************
   Copyright 2012 Emily Estes

   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 net.metanotion.simpletemplate.interpreter;


import java.util.Map;

import net.metanotion.functor.Block;
import net.metanotion.scripting.ObjectServer;
import net.metanotion.util.Dictionary;
import net.metanotion.util.Dispatcher;
import net.metanotion.util.DispatcherGenerator;
import net.metanotion.util.Message;

final class LocalObjectServer implements ObjectServer {
	private static final DispatcherGenerator dGen = new DispatcherGenerator();

	private final Dictionary<String,Object> local;
	private final ObjectServer parent;
	public LocalObjectServer(final Dictionary<String,Object> local, final ObjectServer parent) {
		this.local = local;
		this.parent = parent;
	}

	@Override public Dispatcher dispatcher(final String name) {
		if("".equals(name)) {
			return new Dispatcher<Object, Map.Entry<String,Object>>() {
				@Override public Message<Object> dispatch(final Map.Entry<String,Object> data) {
					return new Message<Object>() {
						@Override public Object call(Object o) {
							final Object result = local.get(data.getKey());
							if(result == null) { return parent.dispatcher("").dispatch(data).call(o); }
							if(result instanceof Block) {
								try {
									return ((Block) result).eval(data.getValue());
								} catch (Exception e) { throw new RuntimeException(e); }
							}
							return result;
						}
						@Override public Class<Object> receiverType() { return Object.class; }
					};
				}
			};
		}
		final Object o = local.get(name);
		if(o != null) { return dGen.get(o); }
		return parent.dispatcher(name);
	}

	@Override public Object get(final String name) {
		final Object o = local.get(name);
		if(o != null) { return o; }
		return parent.get(name);
	}
}