KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > mapper > storage > QueryBuilder


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 Universite de Versailles Saint-Quentin.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 /*
24  * DocumentGenerator.java
25  *
26  * Created on 12 mars 2001, 18:01
27  */

28
29 package org.xquark.mapper.storage;
30
31 import java.sql.SQLException JavaDoc;
32 import java.util.Collection JavaDoc;
33 import java.util.Collections JavaDoc;
34 import java.util.Iterator JavaDoc;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.xml.sax.ContentHandler JavaDoc;
39 import org.xml.sax.ErrorHandler JavaDoc;
40 import org.xml.sax.SAXException JavaDoc;
41 import org.xml.sax.ext.LexicalHandler JavaDoc;
42 import org.xquark.mapper.RepositoryException;
43 import org.xquark.mapper.mapping.TableMapping;
44 import org.xquark.mapper.metadata.MetadataIterator;
45 import org.xquark.mapper.metadata.PathMetadata;
46 import org.xquark.mapper.metadata.PathNode;
47 import org.xquark.xml.xdbc.XMLDBCException;
48 import org.xquark.xpath.NodeKind;
49
50 /**
51  *
52  *
53  * <p>Generation is guided by the schema and indecisions are removed by
54  * document instance information (stored in the structure table).</p>
55  * @see org.xquark.mapper.XMLCollection
56  */

57 public abstract class QueryBuilder extends XMLBuilder
58 {
59     private static final String JavaDoc RCSRevision = "$Revision: 1.2 $";
60     private static final String JavaDoc RCSName = "$Name: $";
61
62     private static Log log = LogFactory.getLog(QueryBuilder.class);
63     
64     private VarInfoSet varInfo;
65     protected long varFirst = -1, varLast = -1;
66     protected int currentRank = -1;
67     protected short currentPath = -1;
68     
69     private int subPathCount = 0;
70     
71     protected QueryExplorer qTuplePool;
72     
73     /** To be used by query reconstruction */
74     protected QueryBuilder(_RepositoryCollection collection, VarInfoSet varInfo) throws XMLDBCException
75     {
76         super(collection);
77         prefixProvider = new PrefixProvider(varInfo.getNamespaceContextStack());
78         this.varInfo = varInfo;
79     }
80     
81     public void setSAXHandlers
82     (
83                         ContentHandler JavaDoc contentHandler,
84                         LexicalHandler JavaDoc lexicalHandler,
85                         ErrorHandler JavaDoc errorHandler
86                         )
87     {
88         this.contentHandler = contentHandler;
89         this.lexicalHandler = lexicalHandler;
90         this.errorHandler = errorHandler;
91     }
92     
93     public void newVariableRange(int rank, long first, long last, short path)
94     throws XMLDBCException
95     {
96         if (log.isDebugEnabled())
97             log.debug("newVariableRange [rank, first, last, path]="
98                     + rank + ',' + first + ',' + last + ',' + path);
99         currentRank = rank;
100         currentPath = path;
101         varFirst = first;
102         varLast = last;
103         if (subPathCount == qTuplePool.getSubPathCount())
104             subPathCount = 0;
105         if (subPathCount == 0)
106             initNewResult(rank);
107     }
108     
109     protected abstract void initNewResult(int rank) throws XMLDBCException;
110     
111     public boolean generateSubPath(PathNode path) throws XMLDBCException, SQLException JavaDoc, SAXException JavaDoc
112     {
113         if (log.isDebugEnabled())
114             log.debug("generateSubPath [path]=" + path);
115         if (path.getType() == NodeKind.ATTRIBUTE)
116         {
117             String JavaDoc attributeValue = fetch(path);
118             contentHandler.characters(attributeValue.toCharArray(), 0, attributeValue.length());
119             return true;
120         }
121         
122         subPathCount++;
123         qTuplePool.freezeCurrentSubPath();
124         
125         // create metadata iterator
126
MetadataIterator metaContext = pathSet.createIterator(path);
127         
128         Collection JavaDoc unconsumedTuples;
129         if (path.getReadColumnMapping() == null)
130            unconsumedTuples = path.getBuilderAncestor().getBuildMappings();
131         else
132            unconsumedTuples = Collections.singletonList(path.getReadColumnMapping().getTableMapping());
133         
134         // Process multivaluated paths
135
long uoid = NO_UOID_FOUND, last = NOT_FOUND, anchor = NO_UOID_FOUND;
136         while (((uoid = scanBrother(varFirst, varLast, path)) > last) || (uoid == -1)) // else entering a new result
137
{
138             if (uoid == NO_UOID_FOUND) // DISCARDED potentially multivalued: consume tuple
139
{
140                 anchor = getElementUOID(varFirst, varFirst, (PathNode)path.getModelAncestor());
141                 if (anchor <= NO_UOID_FOUND)
142                     anchor = varFirst;
143             }
144             else
145                 anchor = uoid;
146             
147             browseBranch(varFirst, varLast, uoid, anchor, metaContext, 0, false);
148             
149             if ((uoid == NO_UOID_FOUND) // DISCARDED potentially multivalued: consume tuple
150
&& !consumeTuple(unconsumedTuples))
151                 break;
152                  
153             // memorize uoid
154
last = uoid;
155         }
156         // removing useless tuples basing on result segmentation
157
// Note: table mappings out of subpath contain data common to all
158
// multivaluated subpaths. This is the reason why consuming is
159
// performed at the end without impact.
160
consumeTuples(unconsumedTuples);
161         return false;
162     }
163     
164     /** Check if a node with the same path is present in results (multivaluated elements).
165      * @return -1 if not found. UOID else.
166      */

167     protected long scanBrother(long first, long last, PathNode path)
168     throws SQLException JavaDoc
169     {
170         long uoid = NOT_FOUND;
171         short pid = path.getPathID();
172         StructExplorer structNode = null;
173         Tuple nextDataTuple = null;
174         
175         switch (path.getStorageMode())
176         {
177             case PathMetadata.STRUCT_ONLY:
178             case PathMetadata.DATA_AND_STRUCT:
179                 // look in the struct table
180
structNode = qTuplePool.getStructNode();
181                 if (structNode.isInRange(first, last, pid))
182                     uoid = qTuplePool.getStructNode().getUOID();
183                 break;
184             case PathMetadata.DATA_ONLY:
185                 nextDataTuple = qTuplePool.get(path.getReadTableMapping().getTableMapping().getTableIndex());
186                 if (nextDataTuple.isInRange(first, last, pid))
187                     uoid = nextDataTuple.getUOID();
188                 break;
189             case PathMetadata.POTENTIAL_STRUCT:
190                 long dataUOID = NO_UOID_FOUND, structUOID = NO_UOID_FOUND;
191                 // look in struct
192
structNode = qTuplePool.getStructNode();
193                 if (structNode.isInRange(first, last, pid))
194                     structUOID = qTuplePool.getStructNode().getUOID();
195                 // look in data
196
if (path.isMixed())
197                     nextDataTuple = qTuplePool.get(path.getTextTableMapping().getTableMapping().getTableIndex());
198                 else if (path.getReadTableMapping() != null)
199                     nextDataTuple = qTuplePool.get(path.getReadTableMapping().getTableMapping().getTableIndex());
200                 if ((nextDataTuple != null) && nextDataTuple.isInRangeAbs(first, last, pid))
201                     dataUOID = nextDataTuple.getUOID();
202                 // take the least
203
if (dataUOID == NO_UOID_FOUND)
204                 {
205                     if (structUOID >= 0)
206                         uoid = structUOID;
207                 }
208                 else if (structUOID == NO_UOID_FOUND)
209                     uoid = dataUOID;
210                 else
211                     uoid = Math.min(structUOID, dataUOID);
212                 break;
213             case PathMetadata.DISCARDED:
214                 uoid = NO_UOID_FOUND;
215             default:
216         }
217         
218         return uoid;
219     }
220    
221     public String JavaDoc fetch(PathNode path)
222     throws SQLException JavaDoc, XMLDBCException
223     {
224         if (log.isDebugEnabled()) log.debug("fetch [path]=" + path);
225         
226         subPathCount++;
227         qTuplePool.freezeCurrentSubPath();
228         
229         // Process multivaluated paths
230
long uoid = -1, last = -2;
231         StringBuffer JavaDoc value = new StringBuffer JavaDoc();
232         String JavaDoc fetchedValue;
233         while ((uoid = scanBrother(varFirst, varLast, path)) > last) // else entering a new result
234
{
235             fetchedValue = getMappedValue(path, varFirst, varLast, true, true, true);
236             if (fetchedValue != null)
237                 value.append(fetchedValue);
238             
239             // memorize uoid
240
last = uoid;
241         }
242         return value.toString();
243     }
244     
245     private void consumeTuples(Collection JavaDoc tableMappings) throws SQLException JavaDoc
246     {
247         if (tableMappings != null)
248         {
249             Iterator JavaDoc it = tableMappings.iterator();
250             Tuple tuple;
251             while (it.hasNext())
252             {
253                 tuple = qTuplePool.get(((TableMapping)it.next()).getTableIndex());
254                 // exhaust tuples
255
while(tuple.fetchNextRow());
256             }
257         }
258     }
259     
260     private boolean consumeTuple(Collection JavaDoc tableMappings) throws SQLException JavaDoc
261     {
262         if (tableMappings != null)
263         {
264             Iterator JavaDoc it = tableMappings.iterator();
265             Tuple tuple;
266             while (it.hasNext())
267             {
268                 tuple = qTuplePool.get(((TableMapping)it.next()).getTableIndex());
269                 // exhaust tuples
270
return tuple.fetchNextRow();
271             }
272         }
273         return false;
274     }
275     
276     public void reset() throws RepositoryException, SQLException JavaDoc
277     {
278         super.reset();
279         varFirst = -1;
280         varLast = -1;
281         currentRank = -1;
282         subPathCount = 0;
283     }
284 }
285
Popular Tags