org.apache.ambari.server.api.query.JpaSortBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ambari.server.api.query.JpaSortBuilder.java

Source

/**
 * 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.ambari.server.api.query;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.SingularAttribute;

import org.apache.ambari.server.controller.spi.SortRequest;
import org.apache.ambari.server.controller.spi.SortRequestProperty;
import org.apache.commons.lang.ObjectUtils;

/**
 * The {@link JpaSortBuilder} class is used to convert and Ambari
 * {@link SortRequest} and list of {@link SortRequestProperty} into a JPA
 * {@link Order} list. This can then be given to a {@link CriteriaBuilder} to
 * provide sorting in the JPA layer during a query.
 * <p/>
 * This classes uses the {@link JpaPredicateVisitor} for the entity being
 * queried in order to convert the entity fields into {@link Path} expressions.
 */
public class JpaSortBuilder<T> {

    /**
     * Constructor.
     *
     */
    public JpaSortBuilder() {
    }

    /**
     * Builds the list of sort orders based on the supplied request and JPA
     * predicate visitor.
     *
     * @param sortRequests
     *          the Ambari sort request properties to turn into a JPA sort
     *          request. If {@code null} or the {@link SortRequestProperty} list
     *          is null, an empty list is returned.
     * @param visitor
     *          a visitor that knows how to convert the Ambari properties into
     *          {@link SingularAttribute} (not {@code null}).
     * @return a list of sorts or an empty list if none (never {@code null}).
     */
    public List<Order> buildSortOrders(SortRequest sortRequest, JpaPredicateVisitor<T> visitor) {

        if (null == sortRequest || null == sortRequest.getProperties()) {
            return Collections.emptyList();
        }

        CriteriaBuilder builder = visitor.getCriteriaBuilder();
        List<SortRequestProperty> sortProperties = sortRequest.getProperties();
        List<Order> sortOrders = new ArrayList<Order>(sortProperties.size());

        for (SortRequestProperty sort : sortProperties) {
            String propertyId = sort.getPropertyId();

            List<? extends SingularAttribute<?, ?>> singularAttributes = visitor.getPredicateMapping(propertyId);

            if (null == singularAttributes || singularAttributes.size() == 0) {
                continue;
            }

            Path<?> path = null;
            for (SingularAttribute<?, ?> singularAttribute : singularAttributes) {
                if (null == path) {

                    CriteriaQuery<T> query = visitor.getCriteriaQuery();
                    Set<Root<?>> roots = query.getRoots();

                    // if there are existing roots; use the existing roots to prevent more
                    // roots from being added potentially causing a cartesian product
                    // where we don't want one
                    if (null != roots && !roots.isEmpty()) {
                        Iterator<Root<?>> iterator = roots.iterator();
                        while (iterator.hasNext()) {
                            Root<?> root = iterator.next();

                            Class<?> visitorEntityClass = visitor.getEntityClass();
                            if (ObjectUtils.equals(visitorEntityClass, root.getJavaType())
                                    || ObjectUtils.equals(visitorEntityClass, root.getModel().getJavaType())) {
                                path = root.get(singularAttribute.getName());
                                break;
                            }
                        }
                    }

                    // no roots exist already which match this entity class, create a new
                    // path
                    if (null == path) {
                        path = query.from(visitor.getEntityClass()).get(singularAttribute.getName());
                    }
                } else {
                    path = path.get(singularAttribute.getName());
                }
            }

            Order sortOrder = null;
            if (sort.getOrder() == org.apache.ambari.server.controller.spi.SortRequest.Order.ASC) {
                sortOrder = builder.asc(path);
            } else {
                sortOrder = builder.desc(path);
            }

            sortOrders.add(sortOrder);
        }

        return sortOrders;
    }
}