+++ /dev/null
-/*--------------------------------------------------------------------------\r
- * Copyright 2008 Taro L. Saito\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- *--------------------------------------------------------------------------*/\r
-//--------------------------------------\r
-// Xerial Raquel Project\r
-//\r
-// RelationHolder.java\r
-// Since: Nov 7, 2008 2:28:57 PM\r
-//\r
-// $URL: http://www.xerial.org/svn/project/XerialJ/trunk/xerial-core/src/main/java/org/xerial/lens/relation/query/RelationFragmentHolder.java $\r
-// $Author: leo $\r
-//--------------------------------------\r
-package org.xerial.lens.relation.query;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-\r
-import org.xerial.lens.relation.TupleElement;\r
-import org.xerial.lens.relation.TupleVisitor;\r
-import org.xerial.lens.relation.Node;\r
-import org.xerial.lens.relation.Tuple;\r
-import org.xerial.lens.relation.TupleIndex;\r
-import org.xerial.lens.relation.schema.Schema;\r
-import org.xerial.lens.relation.schema.SchemaBuilder;\r
-import org.xerial.util.ArrayDeque;\r
-import org.xerial.util.Deque;\r
-import org.xerial.util.log.Logger;\r
-\r
-/**\r
- * Relation fragment holder used in {@link StreamAmoebaJoin}\r
- * \r
- * \r
- * @author leo\r
- * \r
- */\r
-public class RelationFragmentHolder {\r
- private static Logger _logger = Logger.getLogger(RelationFragmentHolder.class);\r
-\r
- private final Schema relation;\r
- private final Schema schemaWithoutCoreNode;\r
- // private IndexedSet<String> nodeNameIndex = new IndexedSet<String>();\r
-\r
- private LinkedList<RelationFragment> fragmentStack = new LinkedList<RelationFragment>();\r
- private Deque<Node> coreNodeStack = new ArrayDeque<Node>();\r
- private HashMap<Node, Integer> fragmentListStartPosition = new HashMap<Node, Integer>();\r
-\r
- private final int relationSize;\r
-\r
- private final RelationHandler handler;\r
-\r
- private class RelationFragment {\r
- //private BitVector activeStackFlag;\r
- private Tuple<Node> relationFragment;\r
-\r
- public RelationFragment() {\r
- //activeStackFlag = new BitVector(relationSize - 1);\r
- relationFragment = emptyTuple(schemaWithoutCoreNode);\r
- }\r
-\r
- public Tuple<Node> emptyTuple(Schema schema) {\r
- List<TupleElement<Node>> nodeList = new ArrayList<TupleElement<Node>>(schema.size());\r
- for (int i = 0; i < schema.size(); i++) {\r
- Schema subSchema = schema.get(i);\r
- if (subSchema.isAtom())\r
- nodeList.add(null);\r
- else\r
- nodeList.add(emptyTuple(subSchema));\r
- }\r
- return new Tuple<Node>(nodeList);\r
- }\r
-\r
- class CompletenessTester implements TupleVisitor<Node> {\r
- boolean hasNull = false;\r
-\r
- public boolean isComplete() {\r
- relationFragment.accept(this);\r
- return !hasNull;\r
- }\r
-\r
- public void visitNode(Node node) {\r
- if (node == null)\r
- hasNull = true;\r
- }\r
-\r
- public void visitTuple(Tuple<Node> tuple) {\r
- if (tuple == null) {\r
- hasNull = true;\r
- return;\r
- }\r
-\r
- for (TupleElement<Node> each : tuple) {\r
- if (hasNull)\r
- break;\r
-\r
- if (each == null) {\r
- hasNull = true;\r
- break;\r
- }\r
-\r
- each.accept(this);\r
- }\r
-\r
- }\r
-\r
- }\r
-\r
- public boolean isComplete() {\r
- return new CompletenessTester().isComplete();\r
- }\r
-\r
- public void set(Node node) {\r
- TupleIndex flagIndex = getIndexOf(node);\r
- relationFragment.set(flagIndex, node);\r
- }\r
-\r
- private TupleIndex getIndexOf(Node node) {\r
- return schemaWithoutCoreNode.getNodeIndex(node.nodeName);\r
- }\r
-\r
- public String toString() {\r
- return relationFragment.toString();\r
- }\r
-\r
- }\r
-\r
- public RelationFragmentHolder(Schema targetRelation, RelationHandler handler) {\r
- this.relation = targetRelation;\r
-\r
- SchemaBuilder builder = new SchemaBuilder();\r
- for (int i = 1; i < relation.size(); ++i)\r
- builder.add(relation.get(i));\r
- this.schemaWithoutCoreNode = builder.build();\r
-\r
- this.handler = handler;\r
-\r
- relationSize = targetRelation.size();\r
-\r
- }\r
-\r
- public Schema getRelation() {\r
-\r
- return relation;\r
- }\r
-\r
- public boolean isCoreNode(TupleIndex nodeID) {\r
- return nodeID.size() == 1 && nodeID.get(0) == 0;\r
- }\r
-\r
- /**\r
- * @param node\r
- * @return is changed?\r
- */\r
- public boolean push(Node node) {\r
- if (_logger.isTraceEnabled())\r
- _logger.trace("push: " + node);\r
- TupleIndex nodeNameID = relation.getNodeIndex(node.nodeName);\r
- if (isCoreNode(nodeNameID)) {\r
- // core node\r
- if (coreNodeStack.isEmpty()) {\r
- coreNodeStack.addLast(node);\r
- fragmentListStartPosition.put(node, 0);\r
- return true;\r
- }\r
- else if (coreNodeStack.getLast().nodeID != node.nodeID) {\r
- coreNodeStack.addLast(node);\r
- fragmentListStartPosition.put(node, fragmentStack.size());\r
- return true;\r
- }\r
- }\r
- else {\r
- // fragment node\r
- RelationFragment target = getTargetRelationFragmentFromStack();\r
- target.set(node);\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- public void pop(Node node) {\r
- if (_logger.isTraceEnabled())\r
- _logger.trace("pop: " + node);\r
- TupleIndex nodeNameID = relation.getNodeIndex(node.nodeName);\r
- RelationFragment target = getTargetRelationFragmentFromStack();\r
- if (isCoreNode(nodeNameID)) {\r
- // for setting text values\r
- coreNodeStack.removeLast();\r
- coreNodeStack.addLast(node);\r
-\r
- int stackStart = fragmentListStartPosition.get(node);\r
-\r
- for (Iterator<RelationFragment> it = fragmentStack.listIterator(stackStart); it\r
- .hasNext();) {\r
- RelationFragment fragment = it.next();\r
- if (fragment.isComplete()) {\r
- output(node, target);\r
- }\r
- }\r
- while (fragmentStack.size() > stackStart) {\r
- fragmentStack.removeLast();\r
- }\r
- coreNodeStack.removeLast();\r
- }\r
- else {\r
- // for setting text values\r
- target.set(node);\r
- if (target.isComplete()) {\r
- if (!coreNodeStack.isEmpty()) {\r
- output(coreNodeStack.getLast(), target);\r
- fragmentStack.removeLast();\r
- }\r
- }\r
- }\r
- }\r
-\r
- public void output(Node coreNode, RelationFragment fragment) {\r
- //_logger.info(String.format("[%s, %s]", coreNode, fragment));\r
-\r
- Tuple<Node> rel = new Tuple<Node>(relationSize);\r
- rel.add(coreNode);\r
- for (TupleElement<Node> each : fragment.relationFragment)\r
- rel.add(each);\r
-\r
- handler.relation(relation, rel);\r
- }\r
-\r
- public RelationFragment getTargetRelationFragmentFromStack() {\r
- if (coreNodeStack.isEmpty()) {\r
- RelationFragment fragment;\r
- if (fragmentStack.isEmpty()) {\r
- fragment = new RelationFragment();\r
- fragmentStack.add(fragment);\r
- }\r
- else\r
- fragment = fragmentStack.getLast();\r
- return fragment;\r
- }\r
- else {\r
- Node latestCoreNode = coreNodeStack.getLast();\r
- int stackPos = fragmentListStartPosition.get(latestCoreNode);\r
- if (stackPos >= fragmentStack.size()) // if no relation fragment is stacked\r
- {\r
- // add a new relation fragment \r
- RelationFragment fragment = new RelationFragment();\r
- fragmentStack.add(fragment);\r
- return fragment;\r
- }\r
- else {\r
- return fragmentStack.getLast();\r
- }\r
- }\r
- }\r
-\r
-}\r