1 22 23 28 29 package org.xquark.mapper.storage; 30 31 import java.sql.SQLException ; 32 import java.util.Collection ; 33 import java.util.Collections ; 34 import java.util.Iterator ; 35 36 import org.apache.commons.logging.Log; 37 import org.apache.commons.logging.LogFactory; 38 import org.xml.sax.ContentHandler ; 39 import org.xml.sax.ErrorHandler ; 40 import org.xml.sax.SAXException ; 41 import org.xml.sax.ext.LexicalHandler ; 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 57 public abstract class QueryBuilder extends XMLBuilder 58 { 59 private static final String RCSRevision = "$Revision: 1.2 $"; 60 private static final String 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 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 contentHandler, 84 LexicalHandler lexicalHandler, 85 ErrorHandler 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 , SAXException  112 { 113 if (log.isDebugEnabled()) 114 log.debug("generateSubPath [path]=" + path); 115 if (path.getType() == NodeKind.ATTRIBUTE) 116 { 117 String attributeValue = fetch(path); 118 contentHandler.characters(attributeValue.toCharArray(), 0, attributeValue.length()); 119 return true; 120 } 121 122 subPathCount++; 123 qTuplePool.freezeCurrentSubPath(); 124 125 MetadataIterator metaContext = pathSet.createIterator(path); 127 128 Collection unconsumedTuples; 129 if (path.getReadColumnMapping() == null) 130 unconsumedTuples = path.getBuilderAncestor().getBuildMappings(); 131 else 132 unconsumedTuples = Collections.singletonList(path.getReadColumnMapping().getTableMapping()); 133 134 long uoid = NO_UOID_FOUND, last = NOT_FOUND, anchor = NO_UOID_FOUND; 136 while (((uoid = scanBrother(varFirst, varLast, path)) > last) || (uoid == -1)) { 138 if (uoid == NO_UOID_FOUND) { 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) && !consumeTuple(unconsumedTuples)) 151 break; 152 153 last = uoid; 155 } 156 consumeTuples(unconsumedTuples); 161 return false; 162 } 163 164 167 protected long scanBrother(long first, long last, PathNode path) 168 throws SQLException  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 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 structNode = qTuplePool.getStructNode(); 193 if (structNode.isInRange(first, last, pid)) 194 structUOID = qTuplePool.getStructNode().getUOID(); 195 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 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 fetch(PathNode path) 222 throws SQLException , XMLDBCException 223 { 224 if (log.isDebugEnabled()) log.debug("fetch [path]=" + path); 225 226 subPathCount++; 227 qTuplePool.freezeCurrentSubPath(); 228 229 long uoid = -1, last = -2; 231 StringBuffer value = new StringBuffer (); 232 String fetchedValue; 233 while ((uoid = scanBrother(varFirst, varLast, path)) > last) { 235 fetchedValue = getMappedValue(path, varFirst, varLast, true, true, true); 236 if (fetchedValue != null) 237 value.append(fetchedValue); 238 239 last = uoid; 241 } 242 return value.toString(); 243 } 244 245 private void consumeTuples(Collection tableMappings) throws SQLException  246 { 247 if (tableMappings != null) 248 { 249 Iterator it = tableMappings.iterator(); 250 Tuple tuple; 251 while (it.hasNext()) 252 { 253 tuple = qTuplePool.get(((TableMapping)it.next()).getTableIndex()); 254 while(tuple.fetchNextRow()); 256 } 257 } 258 } 259 260 private boolean consumeTuple(Collection tableMappings) throws SQLException  261 { 262 if (tableMappings != null) 263 { 264 Iterator it = tableMappings.iterator(); 265 Tuple tuple; 266 while (it.hasNext()) 267 { 268 tuple = qTuplePool.get(((TableMapping)it.next()).getTableIndex()); 269 return tuple.fetchNextRow(); 271 } 272 } 273 return false; 274 } 275 276 public void reset() throws RepositoryException, SQLException  277 { 278 super.reset(); 279 varFirst = -1; 280 varLast = -1; 281 currentRank = -1; 282 subPathCount = 0; 283 } 284 } 285
| Popular Tags
|