/** * Initiates the assembly of a data graph based on the given results list. * * @param results the results list * @see DataGraphAssembler.getDataGraph() */ @Override public void assemble(List<PropertyPair> results) { long before = System.currentTimeMillis(); DataGraph dataGraph = initRoot(results); CoreNode rootNode = (CoreNode) dataGraph.getRootObject(); // singular reference props for (PropertyPair pair : results) { if (pair.getProp().isMany() || pair.getProp().getType().isDataType()) continue; List<PropertyPair> childKeyProps = this.getChildKeyPairs(pair); assemble( (PlasmaType) pair.getProp().getType(), (PlasmaDataObject) this.root, pair.getProp(), childKeyProps, 1); } // multi reference props (not found in results) Set<Property> props = this.collector.getProperties(this.rootType); for (Property p : props) { PlasmaProperty prop = (PlasmaProperty) p; if (prop.isMany() && !prop.getType().isDataType()) { List<PropertyPair> childKeyProps = this.getChildKeyPairs(root, prop); assemble((PlasmaType) prop.getType(), (PlasmaDataObject) this.root, prop, childKeyProps, 1); } } long after = System.currentTimeMillis(); rootNode .getValueObject() .put(CloudGraphConstants.GRAPH_ASSEMBLY_TIME, Long.valueOf(after - before)); GraphMetricVisitor visitor = new GraphMetricVisitor(); this.root.accept(visitor); rootNode .getValueObject() .put(CloudGraphConstants.GRAPH_NODE_COUNT, Long.valueOf(visitor.getCount())); rootNode .getValueObject() .put(CloudGraphConstants.GRAPH_DEPTH, Long.valueOf(visitor.getDepth())); rootNode .getValueObject() .put(CloudGraphConstants.GRAPH_THREAD_COUNT, Long.valueOf(visitor.getThreadCount())); }
/** * Assembles a data object of the given target type by first forming a query using the given * key/property pairs. If an existing data object is mapped for the given key pairs, the existing * data object is linked. * * @param targetType the type for the data object to be assembled * @param source the source data object * @param sourceProperty the source property * @param childKeyPairs the key pairs for the data object to be assembled */ protected void assemble( PlasmaType targetType, PlasmaDataObject source, PlasmaProperty sourceProperty, List<PropertyPair> childKeyPairs, int level) { Set<Property> props = this.collector.getProperties(targetType, level); if (props == null) props = EMPTY_PROPERTY_SET; if (log.isDebugEnabled()) log.debug( String.valueOf(level) + ":assemble: " + source.getType().getName() + "." + sourceProperty.getName() + "->" + targetType.getName() + ": " + props); List<List<PropertyPair>> result = this.getPredicateResult(targetType, sourceProperty, props, childKeyPairs); if (log.isDebugEnabled()) log.debug(String.valueOf(level) + ":results: " + result.size()); Map<PlasmaDataObject, List<PropertyPair>> resultMap = this.collectResults(targetType, source, sourceProperty, result); // now traverse Iterator<PlasmaDataObject> iter = resultMap.keySet().iterator(); while (iter.hasNext()) { PlasmaDataObject target = iter.next(); List<PropertyPair> row = resultMap.get(target); // traverse singular results props for (PropertyPair pair : row) { if (pair.getProp().isMany() || pair.getProp().getType().isDataType()) continue; // only singular reference props if (!pair.isQueryProperty()) continue; // property is a key or other property not explicitly cited in the source query, // don't traverse it List<PropertyPair> nextKeyPairs = this.getNextKeyPairs(target, pair, level); if (log.isDebugEnabled()) log.debug( String.valueOf(level) + ":traverse: (" + pair.getProp().isMany() + ") " + pair.getProp().toString() + ":" + String.valueOf(pair.getValue())); assemble( (PlasmaType) pair.getProp().getType(), target, pair.getProp(), nextKeyPairs, level + 1); } // traverse multi props based, not on the results // row, but on keys within this data object for (Property p : props) { PlasmaProperty prop = (PlasmaProperty) p; if (!prop.isMany() || prop.getType().isDataType()) continue; // only many reference props List<PropertyPair> childKeyProps = this.getChildKeyProps(target, targetType, prop); if (log.isDebugEnabled()) log.debug( String.valueOf(level) + ":traverse: (" + prop.isMany() + ") " + prop.toString() + " - " + childKeyProps.toArray().toString()); assemble((PlasmaType) prop.getType(), target, prop, childKeyProps, level + 1); } } }
private List<List<PropertyPair>> findResults( Query query, PropertySelectionCollector collector, PlasmaType type, Connection con) { Object[] params = new Object[0]; JDBCDataConverter converter = JDBCDataConverter.INSTANCE; if (log.isDebugEnabled()) { log(query); } AliasMap aliasMap = new AliasMap(type); Map<Type, List<String>> selectMap = collector.getResult(); // construct a filter adding to alias map JDBCFilterAssembler filterAssembler = null; Where where = query.findWhereClause(); if (where != null) { filterAssembler = new JDBCFilterAssembler(where, type, aliasMap); params = filterAssembler.getParams(); } JDBCOrderingDeclarationAssembler orderingDeclAssembler = null; OrderBy orderby = query.findOrderByClause(); if (orderby != null) orderingDeclAssembler = new JDBCOrderingDeclarationAssembler(orderby, type, aliasMap); JDBCGroupingDeclarationAssembler groupingDeclAssembler = null; GroupBy groupby = query.findGroupByClause(); if (groupby != null) groupingDeclAssembler = new JDBCGroupingDeclarationAssembler(groupby, type, aliasMap); String rootAlias = aliasMap.getAlias(type); StringBuilder sqlQuery = new StringBuilder(); sqlQuery.append("SELECT "); int i = 0; List<String> names = selectMap.get(type); for (String name : names) { PlasmaProperty prop = (PlasmaProperty) type.getProperty(name); if (prop.isMany() && !prop.getType().isDataType()) continue; if (i > 0) sqlQuery.append(", "); sqlQuery.append(rootAlias); sqlQuery.append("."); sqlQuery.append(prop.getPhysicalName()); i++; } // construct a FROM clause from alias map sqlQuery.append(" FROM "); Iterator<PlasmaType> it = aliasMap.getTypes(); int count = 0; while (it.hasNext()) { PlasmaType aliasType = it.next(); String alias = aliasMap.getAlias(aliasType); if (count > 0) sqlQuery.append(", "); sqlQuery.append(aliasType.getPhysicalName()); sqlQuery.append(" "); sqlQuery.append(alias); count++; } // append WHERE filter if (filterAssembler != null) { sqlQuery.append(" "); sqlQuery.append(filterAssembler.getFilter()); } // set the result range // FIXME: Oracle specific if (query.getStartRange() != null && query.getEndRange() != null) { if (where == null) sqlQuery.append(" WHERE "); else sqlQuery.append(" AND "); sqlQuery.append("ROWNUM >= "); sqlQuery.append(String.valueOf(query.getStartRange())); sqlQuery.append(" AND ROWNUM <= "); sqlQuery.append(String.valueOf(query.getEndRange())); } if (orderingDeclAssembler != null) { sqlQuery.append(" "); sqlQuery.append(orderingDeclAssembler.getOrderingDeclaration()); } if (groupingDeclAssembler != null) { sqlQuery.append(" "); sqlQuery.append(groupingDeclAssembler.getGroupingDeclaration()); } List<List<PropertyPair>> rows = new ArrayList<List<PropertyPair>>(); PreparedStatement statement = null; ResultSet rs = null; try { statement = con.prepareStatement( sqlQuery.toString(), ResultSet.TYPE_FORWARD_ONLY, /*ResultSet.TYPE_SCROLL_INSENSITIVE,*/ ResultSet.CONCUR_READ_ONLY); // set params // note params are pre-converted // to string in filter assembly // FIXME: are parameters relevant in SQL in this context? if (filterAssembler != null) { params = filterAssembler.getParams(); if (params != null) for (i = 0; i < params.length; i++) statement.setString(i + 1, String.valueOf(params[i])); } if (log.isDebugEnabled()) { if (params == null || params.length == 0) { log.debug("executing: " + sqlQuery.toString()); } else { StringBuilder paramBuf = new StringBuilder(); paramBuf.append(" ["); for (int p = 0; p < params.length; p++) { if (p > 0) paramBuf.append(", "); paramBuf.append(String.valueOf(params[p])); } paramBuf.append("]"); log.debug("executing: " + sqlQuery.toString() + " " + paramBuf.toString()); } } statement.execute(); rs = statement.getResultSet(); int numcols = rs.getMetaData().getColumnCount(); ResultSetMetaData rsMeta = rs.getMetaData(); List<PropertyPair> row = null; PropertyPair pair = null; while (rs.next()) { row = new ArrayList<PropertyPair>(); rows.add(row); for (i = 1; i <= numcols; i++) { String columnName = rsMeta.getColumnName(i); int columnType = rsMeta.getColumnType(i); PlasmaProperty prop = (PlasmaProperty) type.getProperty(columnName); Object value = converter.fromJDBCDataType(rs, i, columnType, prop); pair = new PropertyPair(prop, value); pair.setColumn(i); row.add(pair); } } } catch (Throwable t) { StringBuffer buf = this.generateErrorDetail(t, sqlQuery.toString(), filterAssembler); log.error(buf.toString()); throw new DataAccessException(t); } finally { try { if (rs != null) rs.close(); if (statement != null) statement.close(); } catch (SQLException e) { log.error(e.getMessage(), e); } } return rows; }