private static SortField.Type getSortType(FieldMetadata fieldMetadata) { TypeMetadata fieldType = fieldMetadata.getType(); String type = MetadataUtils.getSuperConcreteType(fieldType).getName(); if (Types.STRING.equals(type) || Types.ANY_URI.equals(type) || Types.BOOLEAN.equals(type) || Types.BASE64_BINARY.equals(type) || Types.QNAME.equals(type) || Types.HEX_BINARY.equals(type) || Types.DURATION.equals(type)) { return SortField.Type.STRING_VAL; // STRING does not work well for 'long' strings. } else if (Types.INT.equals(type) || Types.INTEGER.equals(type) || Types.POSITIVE_INTEGER.equals(type) || Types.NON_POSITIVE_INTEGER.equals(type) || Types.NON_NEGATIVE_INTEGER.equals(type) || Types.NEGATIVE_INTEGER.equals(type) || Types.UNSIGNED_INT.equals(type)) { return SortField.Type.INT; } else if (Types.DECIMAL.equals(type) || Types.DOUBLE.equals(type)) { return SortField.Type.DOUBLE; } else if (Types.DATE.equals(type) || Types.DATETIME.equals(type) || Types.TIME.equals(type)) { return SortField.Type.STRING; } else if (Types.UNSIGNED_SHORT.equals(type) || Types.SHORT.equals(type)) { return SortField.Type.SHORT; } else if (Types.UNSIGNED_LONG.equals(type) || Types.LONG.equals(type)) { return SortField.Type.LONG; } else if (Types.FLOAT.equals(type)) { return SortField.Type.FLOAT; } else if (Types.BYTE.equals(type) || Types.UNSIGNED_BYTE.equals(type)) { return SortField.Type.BYTE; } else { throw new UnsupportedOperationException("No support for field typed as '" + type + "'"); } }
@Override public StorageResults visit(OrderBy orderBy) { TypedExpression field = orderBy.getExpression(); if (field instanceof Field) { FieldMetadata fieldMetadata = ((Field) field).getFieldMetadata(); SortField sortField = new SortField( fieldMetadata.getName(), getSortType(fieldMetadata), orderBy.getDirection() == OrderBy.Direction.DESC); query.setSort(new Sort(sortField)); return null; } else { throw new NotImplementedException( "No support for order by for full text search on non-field."); } }
@Override public List<DataRecord> visit(Alias alias) { alias.getTypedExpression().accept(this); FieldMetadata aliasField = new SimpleTypeFieldMetadata( explicitProjection, false, lastField.isMany(), lastField.isMandatory(), alias.getAliasName(), lastField.getType(), Collections.<String>emptyList(), Collections.<String>emptyList(), Collections.<String>emptyList(), StringUtils.EMPTY); ValueBuilder previousValueBuilder = recordProjection.remove(lastField); if (previousValueBuilder == null) { AggregateValueBuilder previous = aggregateProjection.remove(lastField); aggregateProjection.put(aliasField, previous); } else { recordProjection.put(aliasField, previousValueBuilder); } return records; }
@Override public StorageResults visit(Select select) { // TMDM-4654: Checks if entity has a composite PK. Set<ComplexTypeMetadata> compositeKeyTypes = new HashSet<ComplexTypeMetadata>(); // TMDM-7496: Search should include references to reused types Collection<ComplexTypeMetadata> types = new HashSet<ComplexTypeMetadata>(select.accept(new SearchTransitiveClosure())); for (ComplexTypeMetadata type : types) { if (type.getKeyFields().size() > 1) { compositeKeyTypes.add(type); } } if (!compositeKeyTypes.isEmpty()) { StringBuilder message = new StringBuilder(); Iterator it = compositeKeyTypes.iterator(); while (it.hasNext()) { ComplexTypeMetadata compositeKeyType = (ComplexTypeMetadata) it.next(); message.append(compositeKeyType.getName()); if (it.hasNext()) { message.append(','); } } throw new FullTextQueryCompositeKeyException(message.toString()); } // Removes Joins and joined fields. List<Join> joins = select.getJoins(); if (!joins.isEmpty()) { Set<ComplexTypeMetadata> joinedTypes = new HashSet<ComplexTypeMetadata>(); for (Join join : joins) { joinedTypes.add(join.getRightField().getFieldMetadata().getContainingType()); } for (ComplexTypeMetadata joinedType : joinedTypes) { types.remove(joinedType); } List<TypedExpression> filteredFields = new LinkedList<TypedExpression>(); for (TypedExpression expression : select.getSelectedFields()) { if (expression instanceof Field) { FieldMetadata fieldMetadata = ((Field) expression).getFieldMetadata(); if (joinedTypes.contains(fieldMetadata.getContainingType())) { TypeMapping mapping = mappings.getMappingFromDatabase(fieldMetadata.getContainingType()); filteredFields.add( new Alias( new StringConstant(StringUtils.EMPTY), mapping.getUser(fieldMetadata).getName())); } else { filteredFields.add(expression); } } else { filteredFields.add(expression); } } selectedFields.clear(); selectedFields.addAll(filteredFields); } // Handle condition Condition condition = select.getCondition(); if (condition == null) { throw new IllegalArgumentException("Expected a condition in select clause but got 0."); } // Create Lucene query (concatenates all sub queries together). FullTextSession fullTextSession = Search.getFullTextSession(session); Query parsedQuery = select.getCondition().accept(new LuceneQueryGenerator(types)); // Create Hibernate Search query Set<Class> classes = new HashSet<Class>(); for (ComplexTypeMetadata type : types) { String className = ClassCreator.getClassName(type.getName()); try { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); classes.add(contextClassLoader.loadClass(className)); } catch (ClassNotFoundException e) { throw new RuntimeException("Could not find class '" + className + "'.", e); } } FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( parsedQuery, classes.toArray(new Class<?>[classes.size()])); // Very important to leave this null (would disable ability to search across different types) fullTextQuery.setCriteriaQuery(null); fullTextQuery.setSort(Sort.RELEVANCE); // Default sort (if no order by specified). query = EntityFinder.wrap( fullTextQuery, (HibernateStorage) storage, session); // ensures only MDM entity objects are returned. // Order by for (OrderBy current : select.getOrderBy()) { current.accept(this); } // Paging Paging paging = select.getPaging(); paging.accept(this); pageSize = paging.getLimit(); boolean hasPaging = pageSize < Integer.MAX_VALUE; if (!hasPaging) { return createResults(query.scroll(ScrollMode.FORWARD_ONLY)); } else { return createResults(query.list()); } }