001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.pojotools; 014 015import java.lang.reflect.*; 016import java.util.*; 017 018import org.apache.juneau.*; 019import org.apache.juneau.internal.*; 020 021/** 022 * Sorts arrays and collections of maps and beans. 023 */ 024@SuppressWarnings({"unchecked","rawtypes"}) 025public final class PojoSorter implements PojoTool<SortArgs> { 026 027 @Override /* PojoTool */ 028 public Object run(BeanSession session, Object input, SortArgs args) { 029 if (input == null) 030 return null; 031 032 // If sort or view isn't empty, then we need to make sure that all entries in the 033 // list are maps. 034 Map<String,Boolean> sort = args.getSort(); 035 036 if (sort.isEmpty()) 037 return input; 038 039 ClassMeta type = session.getClassMetaForObject(input); 040 041 if (! type.isCollectionOrArray()) 042 return input; 043 044 ArrayList<SortEntry> l = null; 045 046 if (type.isArray()) { 047 int size = Array.getLength(input); 048 l = new ArrayList<>(size); 049 for (int i = 0; i < size; i++) 050 l.add(new SortEntry(session, Array.get(input, i))); 051 } else /* isCollection() */ { 052 Collection c = (Collection)input; 053 l = new ArrayList<>(c.size()); 054 for (Object o : c) 055 l.add(new SortEntry(session, o)); 056 } 057 058 // We reverse the list and sort last to first. 059 List<String> columns = new ArrayList<>(sort.keySet()); 060 Collections.reverse(columns); 061 062 for (final String c : columns) { 063 final boolean isDesc = sort.get(c); 064 for (SortEntry se : l) 065 se.setSort(c, isDesc); 066 Collections.sort(l); 067 } 068 069 ArrayList<Object> l2 = new ArrayList<>(l.size()); 070 for (SortEntry se : l) 071 l2.add(se.o); 072 073 return l2; 074 } 075 076 private static class SortEntry implements Comparable { 077 Object o; 078 ClassMeta<?> cm; 079 BeanSession bs; 080 081 Object sortVal; 082 boolean isDesc; 083 084 SortEntry(BeanSession bs, Object o) { 085 this.o = o; 086 this.bs = bs; 087 this.cm = bs.getClassMetaForObject(o); 088 } 089 090 void setSort(String sortCol, boolean isDesc) { 091 this.isDesc = isDesc; 092 093 if (cm == null) 094 sortVal = null; 095 else if (cm.isMap()) 096 sortVal = ((Map)o).get(sortCol); 097 else if (cm.isBean()) 098 sortVal = bs.toBeanMap(o).get(sortCol); 099 else 100 sortVal = null; 101 } 102 103 @Override 104 public int compareTo(Object o) { 105 if (isDesc) 106 return ObjectUtils.compare(((SortEntry)o).sortVal, this.sortVal); 107 return ObjectUtils.compare(this.sortVal, ((SortEntry)o).sortVal); 108 } 109 } 110}