/****************************************************************************** * * Copyright 2014 Paphus Solutions Inc. * * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html * * 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.botlibre.sense.context; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.logging.Level; import org.botlibre.Bot; import org.botlibre.api.knowledge.Network; import org.botlibre.api.knowledge.Vertex; import org.botlibre.knowledge.Primitive; import org.botlibre.sense.BasicSense; /** * Allows a vertices to be explicitly selected. * Allows thought to associate the current context with the selection. * Similar to vision or touch focusing on an object. */ public class Context extends BasicSense { public static int CONTEXT_SIZE = 16; /** Allows notification of the stack top. */ protected Selector selector; /** Keeps track of objects in the current context, for language and association. */ protected List<Long> contextStack = new ArrayList<Long>(); public Context() { } public List<Long> getContextStack() { return this.contextStack; } /** * Return the top of the context stack. */ public Vertex top(Network network) { if (this.contextStack.isEmpty()) { return null; } return network.findById(this.contextStack.get(this.contextStack.size() - 1)); } /** * Self API * Return the top of the context stack. */ public Vertex top(Vertex source) { return top(source.getNetwork()); } /** * Self API * Return the top of the context stack. */ public Vertex top(Vertex source, Vertex vertex) { if (!vertex.hasData() || !(vertex.getData() instanceof Number)) { return null; } int index = ((Number)vertex.getData()).intValue(); if (this.contextStack.size() < index) { return null; } return vertex.getNetwork().findById(this.contextStack.get(this.contextStack.size() - index)); } /** * Self API * Clear the current context. */ public void clear(Vertex source) { clear(); } /** * Clear the current context. */ public void clear() { this.contextStack.clear(); } /** * Self API * Return the first element on the stack matching the variable. */ public Vertex search(Vertex source, Vertex variable) { for (int index = this.contextStack.size() - 1; index >= 0; index--) { Vertex context = variable.getNetwork().findById(this.contextStack.get(index)); if ((context != null) && (!context.hasRelationship(Primitive.VARIABLE)) && (variable.matches(context, new HashMap<Vertex, Vertex>()) == Boolean.TRUE)) { log("search", Level.FINE, context); return context; } } return null; } /** * Self API * Add the vertex to the context. */ public void push(Vertex source, Vertex vertex) { push(vertex); } /** * Add the vertex to the context. */ public void push(Vertex vertex) { log("push", Level.FINE, vertex); this.contextStack.add(vertex.getId()); while (this.contextStack.size() > CONTEXT_SIZE) { this.contextStack.remove(0); } } /** * Return the selector used to access the current selection. */ public Selector getSelector() { return this.selector; } /** * Set the selector used to access the current selection. */ public void setSelector(Selector selector) { this.selector = selector; } /** * Process the input. * Add the vertex to active memory */ public void input(Object input) { if (!isEnabled()) { return; } log("Input", Bot.FINE, input); push(getBot().memory().addActiveMemory((Vertex)input)); } /** * Set the vertex as the current selection. */ public void output(Vertex output) { if (!isEnabled() || (getSelector() == null)) { return; } getSelector().setSelection(output); } public String toString() { return getClass().getSimpleName() + "(" + getContextStack() + ")"; } }