001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2006.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.query.parser.serql;
007:
008: import java.util.ArrayList;
009: import java.util.Collection;
010: import java.util.Collections;
011: import java.util.List;
012:
013: import org.openrdf.query.algebra.And;
014: import org.openrdf.query.algebra.Filter;
015: import org.openrdf.query.algebra.Join;
016: import org.openrdf.query.algebra.LeftJoin;
017: import org.openrdf.query.algebra.SingletonSet;
018: import org.openrdf.query.algebra.StatementPattern;
019: import org.openrdf.query.algebra.TupleExpr;
020: import org.openrdf.query.algebra.ValueExpr;
021: import org.openrdf.query.algebra.Var;
022:
023: /**
024: * A graph pattern consisting of (required and optional) tuple expressions and
025: * boolean constraints.
026: */
027: class GraphPattern {
028:
029: /**
030: * The graph pattern's parent, if any.
031: */
032: private GraphPattern parent = null;
033:
034: /**
035: * The context of this graph pattern.
036: */
037: private Var contextVar;
038:
039: /**
040: * The StatementPattern-scope of this graph pattern.
041: */
042: private StatementPattern.Scope spScope = StatementPattern.Scope.DEFAULT_CONTEXTS;
043:
044: /**
045: * The required tuple expressions in this graph pattern.
046: */
047: private List<TupleExpr> requiredTEs = new ArrayList<TupleExpr>();
048:
049: /**
050: * The optional tuple expressions and their constraints in this graph
051: * pattern.
052: */
053: private List<OptionalTupleExpr> optionalTEs = new ArrayList<OptionalTupleExpr>();
054:
055: /**
056: * The boolean constraints in this graph pattern.
057: */
058: private List<ValueExpr> constraints = new ArrayList<ValueExpr>();
059:
060: /**
061: * Creates a new graph pattern.
062: */
063: public GraphPattern() {
064: }
065:
066: /**
067: * Creates a new graph pattern that inherits the context and scope from a
068: * parent graph pattern.
069: */
070: public GraphPattern(GraphPattern parent) {
071: if (parent != null) {
072: this .parent = parent;
073: contextVar = parent.contextVar;
074: spScope = parent.spScope;
075: }
076: }
077:
078: public GraphPattern getParent() {
079: return parent;
080: }
081:
082: public void setContextVar(Var contextVar) {
083: this .contextVar = contextVar;
084: }
085:
086: public Var getContextVar() {
087: return contextVar;
088: }
089:
090: public void setStatementPatternScope(StatementPattern.Scope spScope) {
091: this .spScope = spScope;
092: }
093:
094: public StatementPattern.Scope getStatementPatternScope() {
095: return spScope;
096: }
097:
098: public void addRequiredTE(TupleExpr te) {
099: requiredTEs.add(te);
100: }
101:
102: public List<TupleExpr> getRequiredTEs() {
103: return Collections.unmodifiableList(requiredTEs);
104: }
105:
106: public void addOptionalTE(GraphPattern gp) {
107: List<ValueExpr> constraints = gp.removeAllConstraints();
108: TupleExpr tupleExpr = gp.buildTupleExpr();
109:
110: OptionalTupleExpr optTE;
111:
112: if (constraints.isEmpty()) {
113: optTE = new OptionalTupleExpr(tupleExpr);
114: } else {
115: ValueExpr constraint = constraints.get(0);
116: for (int i = 1; i < constraints.size(); i++) {
117: constraint = new And(constraint, constraints.get(i));
118: }
119:
120: optTE = new OptionalTupleExpr(tupleExpr, constraint);
121: }
122:
123: optionalTEs.add(optTE);
124: }
125:
126: public List<OptionalTupleExpr> getOptionalTEs() {
127: return Collections.unmodifiableList(optionalTEs);
128: }
129:
130: public void addConstraint(ValueExpr constraint) {
131: constraints.add(constraint);
132: }
133:
134: public void addConstraints(Collection<ValueExpr> constraints) {
135: this .constraints.addAll(constraints);
136: }
137:
138: public List<ValueExpr> getConstraints() {
139: return Collections.unmodifiableList(constraints);
140: }
141:
142: public List<ValueExpr> removeAllConstraints() {
143: List<ValueExpr> constraints = this .constraints;
144: this .constraints = new ArrayList<ValueExpr>();
145: return constraints;
146: }
147:
148: /**
149: * Removes all tuple expressions and constraints.
150: */
151: public void clear() {
152: requiredTEs.clear();
153: optionalTEs.clear();
154: constraints.clear();
155: }
156:
157: /**
158: * Builds a combined tuple expression from the tuple expressions and
159: * constraints in this graph pattern.
160: *
161: * @return A tuple expression for this graph pattern.
162: */
163: public TupleExpr buildTupleExpr() {
164: TupleExpr result;
165:
166: if (requiredTEs.isEmpty()) {
167: result = new SingletonSet();
168: } else {
169: result = requiredTEs.get(0);
170:
171: for (int i = 1; i < requiredTEs.size(); i++) {
172: result = new Join(result, requiredTEs.get(i));
173: }
174: }
175:
176: for (OptionalTupleExpr optTE : optionalTEs) {
177: if (optTE.hasConstraint()) {
178: result = new LeftJoin(result, optTE.getTupleExpr(),
179: optTE.getConstraint());
180: } else {
181: result = new LeftJoin(result, optTE.getTupleExpr());
182: }
183: }
184:
185: for (ValueExpr constraint : constraints) {
186: result = new Filter(result, constraint);
187: }
188:
189: return result;
190: }
191: }
|