1 /*--------------------------------------------------------------------------
\r
2 * Copyright 2009 Taro L. Saito
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
15 *--------------------------------------------------------------------------*/
\r
16 //--------------------------------------
\r
20 // Since: 2009/05/13 9:19:34
\r
24 //--------------------------------------
\r
25 package org.xerial.lens.relation;
\r
27 import java.util.ArrayList;
\r
28 import java.util.Collection;
\r
29 import java.util.Collections;
\r
30 import java.util.Comparator;
\r
31 import java.util.Iterator;
\r
32 import java.util.List;
\r
34 import org.xerial.core.XerialError;
\r
35 import org.xerial.core.XerialErrorCode;
\r
38 * Tuple is a list of {@link TupleElement}s. This Tuple class allows Non-1NF
\r
39 * representation of the data.
\r
44 public class Tuple<Element> implements TupleElement<Element>, Iterable<TupleElement<Element>> {
\r
46 private final List<TupleElement<Element>> nodeList;
\r
49 this.nodeList = new ArrayList<TupleElement<Element>>();
\r
52 public Tuple(Tuple<Element> other) {
\r
53 this(other.nodeList);
\r
56 public Tuple(int tupleSize) {
\r
57 this.nodeList = new ArrayList<TupleElement<Element>>(tupleSize);
\r
60 public Tuple(List<TupleElement<Element>> nodeList) {
\r
61 this.nodeList = new ArrayList<TupleElement<Element>>(nodeList.size());
\r
62 for (TupleElement<Element> each : nodeList) {
\r
63 this.nodeList.add(each);
\r
67 public void add(TupleElement<Element> node) {
\r
71 public void set(int index, TupleElement<Element> node) {
\r
72 nodeList.set(index, node);
\r
75 public void set(TupleIndex index, TupleElement<Element> node) {
\r
76 if (!index.hasTail()) {
\r
77 set(index.get(0), node);
\r
82 TupleElement<Element> target = get(index.get(0));
\r
83 if (target == null || !target.isTuple())
\r
84 throw new XerialError(XerialErrorCode.INVALID_STATE, String.format(
\r
85 "set to invalid element: index = %s in %s", index, this));
\r
87 ((Tuple<Element>) target).set(index.tail(), node);
\r
91 return nodeList.size();
\r
94 public void clear() {
\r
98 public boolean isEmpty() {
\r
99 return nodeList.isEmpty();
\r
102 public void sort(Comparator<TupleElement<Element>> comparator) {
\r
103 Collections.sort(nodeList, comparator);
\r
106 public Iterator<TupleElement<Element>> iterator() {
\r
107 return nodeList.iterator();
\r
110 public TupleElement<Element> get(int index) {
\r
111 return nodeList.get(index);
\r
114 private static <T> String join(Collection<T> c, String concatinator) {
\r
117 int size = c.size();
\r
121 Iterator<T> it = c.iterator();
\r
122 StringBuilder buf = new StringBuilder();
\r
123 for (int i = 0; it.hasNext() && i < size - 1; i++) {
\r
124 Object data = it.next();
\r
126 buf.append(data.toString());
\r
128 buf.append("null");
\r
129 buf.append(concatinator);
\r
131 Object lastData = it.next();
\r
132 if (lastData != null)
\r
133 buf.append(lastData.toString());
\r
135 buf.append("null");
\r
136 return buf.toString();
\r
140 public String toString() {
\r
141 return String.format("[%s]", join(nodeList, ", "));
\r
144 public boolean addAll(List<TupleElement<Element>> relationFragment) {
\r
145 return nodeList.addAll(relationFragment);
\r
148 public Element castToElement() {
\r
152 public Tuple<Element> castToTuple() {
\r
156 public boolean isAtom() {
\r
160 public boolean isTuple() {
\r
164 public TupleElement<Element> get(TupleIndex index) {
\r
165 TupleElement<Element> cell = nodeList.get(index.get(0));
\r
166 if (index.hasTail())
\r
167 return cell.get(index.tail());
\r
172 @SuppressWarnings("unchecked")
\r
173 public Element getNode(int index) {
\r
174 TupleElement<Element> node = get(index);
\r
176 return (Element) node;
\r
178 throw new XerialError(XerialErrorCode.MISSING_ELEMENT, "node is not found: " + index);
\r
181 @SuppressWarnings("unchecked")
\r
182 public Element getElement(TupleIndex index) {
\r
183 TupleElement<Element> node = get(index);
\r
188 return (Element) node;
\r
190 throw new XerialError(XerialErrorCode.MISSING_ELEMENT, "node is not found: " + index);
\r
194 public Tuple<Element> flatten() {
\r
195 ArrayList<TupleElement<Element>> array = new ArrayList<TupleElement<Element>>();
\r
196 flatten(array, this);
\r
197 return new Tuple<Element>(array);
\r
200 private void flatten(List<TupleElement<Element>> result, TupleElement<Element> cell) {
\r
204 for (TupleElement<Element> each : cell.castToTuple()) {
\r
205 flatten(result, each);
\r
210 public void accept(TupleElementVisitor<Element> visitor) {
\r
211 visitor.visitTuple(this);
\r