/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.deltaspike.data.impl.builder.part; import static org.apache.deltaspike.core.util.StringUtils.isNotEmpty; import static org.apache.deltaspike.data.impl.util.QueryUtils.splitByKeyword; import static org.apache.deltaspike.data.impl.util.QueryUtils.uncapitalize; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.apache.deltaspike.data.impl.builder.QueryBuilder; import org.apache.deltaspike.data.impl.builder.QueryBuilderContext; import org.apache.deltaspike.data.impl.meta.RepositoryComponent; public class OrderByQueryPart extends BasePropertyQueryPart { private static final String KEYWORD_ASC = "Asc"; private static final String KEYWORD_DESC = "Desc"; private final List<OrderByQueryAttribute> attributes = new LinkedList<OrderByQueryAttribute>(); @Override protected QueryPart build(String queryPart, String method, RepositoryComponent repo) { Set<String> collect = new TreeSet<String>(); List<String> ascSplit = new LinkedList<String>(); split(queryPart, KEYWORD_ASC, ascSplit); for (String ascPart : ascSplit) { split(ascPart, KEYWORD_DESC, collect); } for (String part : collect) { Direction direction = Direction.fromQueryPart(part); String attribute = direction.attribute(part); validate(attribute, method, repo); attributes.add(new OrderByQueryAttribute(attribute, direction)); } return this; } @Override protected QueryPart buildQuery(QueryBuilderContext ctx) { ctx.append(" order by "); for (Iterator<OrderByQueryAttribute> it = attributes.iterator(); it.hasNext();) { it.next().buildQuery(ctx); if (it.hasNext()) { ctx.append(", "); } } return this; } private void split(String queryPart, String keyword, Collection<String> result) { for (String part : splitByKeyword(queryPart, keyword)) { String attribute = !part.endsWith(KEYWORD_DESC) && !part.endsWith(KEYWORD_ASC) ? part + keyword : part; result.add(attribute); } } private class OrderByQueryAttribute { private final String attribute; private final Direction direction; public OrderByQueryAttribute(String attribute, Direction direction) { this.attribute = attribute; this.direction = direction; } protected void buildQuery(QueryBuilderContext ctx) { String entityPrefix = QueryBuilder.ENTITY_NAME + "."; ctx.append(entityPrefix).append(rewriteSeparator(attribute)) .append(direction.queryDirection()); } } private static enum Direction { ASC(KEYWORD_ASC), DESC(KEYWORD_DESC), DEFAULT(""); private final String postfix; private Direction(String postfix) { this.postfix = postfix; } public boolean endsWith(String queryPart) { return isNotEmpty(postfix) ? queryPart.endsWith(postfix) : false; } public String attribute(String queryPart) { String attribute = isNotEmpty(postfix) ? queryPart.substring(0, queryPart.indexOf(postfix)) : queryPart; return uncapitalize(attribute); } public String queryDirection() { return isNotEmpty(postfix) ? " " + postfix.toLowerCase() : ""; } public static Direction fromQueryPart(String queryPart) { for (Direction dir : values()) { if (dir.endsWith(queryPart)) { return dir; } } return DEFAULT; } } }