217 lines
5.8 KiB
Java
217 lines
5.8 KiB
Java
package com.reliancy.dbo;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Ordering specification for multiple fields.
|
|
*
|
|
* <p>This class manages an ordered list of field/direction pairs for sorting.
|
|
* It supports chaining methods to build complex ordering specifications.
|
|
*
|
|
* <p>Example usage:
|
|
* <pre>{@code
|
|
* Ordering ordering = new Ordering("name ASC, created DESC", entity)
|
|
* .orderBy(Field.by("status"))
|
|
* .orderBy(Field.by("priority"), false);
|
|
* }</pre>
|
|
*/
|
|
public class Ordering {
|
|
private static class FieldOrder {
|
|
Field field;
|
|
boolean ascending;
|
|
|
|
FieldOrder(Field field, boolean ascending) {
|
|
this.field = field;
|
|
this.ascending = ascending;
|
|
}
|
|
}
|
|
|
|
private ArrayList<FieldOrder> orders = new ArrayList<>();
|
|
|
|
/**
|
|
* Creates an empty Ordering.
|
|
*/
|
|
public Ordering() {
|
|
}
|
|
|
|
/**
|
|
* Creates an Ordering from a string specification.
|
|
*
|
|
* @param str String in format "field1 ASC, field2 DESC, ..." or "field1, field2, ..."
|
|
* @param entity Entity to resolve field names
|
|
*/
|
|
public Ordering(String str, Entity entity) {
|
|
fromString(str, entity);
|
|
}
|
|
|
|
/**
|
|
* Creates an Ordering with a single field.
|
|
*
|
|
* @param field Field to order by
|
|
* @param ascending true for ascending, false for descending
|
|
*/
|
|
public Ordering(Field field, boolean ascending) {
|
|
orderBy(field, ascending);
|
|
}
|
|
|
|
/**
|
|
* Parses a string specification and adds to this ordering.
|
|
*
|
|
* @param str String in format "field1 ASC, field2 DESC, ..." or "field1, field2, ..."
|
|
* @param entity Entity to resolve field names
|
|
* @return this for chaining
|
|
*/
|
|
public Ordering fromString(String str, Entity entity) {
|
|
if (str == null || str.trim().isEmpty()) {
|
|
return this;
|
|
}
|
|
String[] parts = str.split(",");
|
|
for (String part : parts) {
|
|
part = part.trim();
|
|
if (part.isEmpty()) continue;
|
|
if (!part.contains(" ")) part = part + " ASC";
|
|
String[] fieldParts = part.split("\\s+");
|
|
Field field = entity.getField(fieldParts[0]);
|
|
if (field == null) {
|
|
throw new IllegalArgumentException("Field " + fieldParts[0] + " not found in entity " + entity.getName());
|
|
}
|
|
boolean ascending = fieldParts.length > 1 && fieldParts[1].equalsIgnoreCase("ASC");
|
|
orderBy(field, ascending);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Clears all ordering specifications.
|
|
*
|
|
* @return this for chaining
|
|
*/
|
|
public Ordering clear() {
|
|
orders.clear();
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Adds a field to order by (ascending by default).
|
|
*
|
|
* @param field Field to order by
|
|
* @return this for chaining
|
|
*/
|
|
public Ordering orderBy(Field field) {
|
|
return orderBy(field, true);
|
|
}
|
|
|
|
/**
|
|
* Adds a field to order by with specified direction.
|
|
*
|
|
* @param field Field to order by
|
|
* @param ascending true for ascending, false for descending
|
|
* @return this for chaining
|
|
*/
|
|
public Ordering orderBy(Field field, boolean ascending) {
|
|
if (field != null) {
|
|
orders.add(new FieldOrder(field, ascending));
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Gets the number of ordering specifications.
|
|
*
|
|
* @return number of fields in this ordering
|
|
*/
|
|
public int size() {
|
|
return orders.size();
|
|
}
|
|
|
|
/**
|
|
* Gets the field at the specified index.
|
|
*
|
|
* @param index index of the field
|
|
* @return Field at the index
|
|
*/
|
|
public Field getField(int index) {
|
|
return orders.get(index).field;
|
|
}
|
|
|
|
/**
|
|
* Gets whether the field at the specified index is ascending.
|
|
*
|
|
* @param index index of the field
|
|
* @return true if ascending, false if descending
|
|
*/
|
|
public boolean isAscending(int index) {
|
|
return orders.get(index).ascending;
|
|
}
|
|
|
|
/**
|
|
* Gets all fields in this ordering.
|
|
*
|
|
* @return list of fields
|
|
*/
|
|
public List<Field> getFields() {
|
|
List<Field> fields = new ArrayList<>();
|
|
for (FieldOrder fo : orders) {
|
|
fields.add(fo.field);
|
|
}
|
|
return fields;
|
|
}
|
|
|
|
/**
|
|
* Checks if this ordering is empty.
|
|
*
|
|
* @return true if no fields are specified
|
|
*/
|
|
public boolean isEmpty() {
|
|
return orders.isEmpty();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
if (orders.isEmpty()) {
|
|
return "";
|
|
}
|
|
StringBuilder sb = new StringBuilder();
|
|
for (int i = 0; i < orders.size(); i++) {
|
|
if (i > 0) sb.append(", ");
|
|
FieldOrder fo = orders.get(i);
|
|
sb.append(fo.field.getName()).append(fo.ascending ? " ASC" : " DESC");
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
// Static factory methods for backward compatibility and convenience
|
|
|
|
/**
|
|
* Creates an Ordering with a single ascending field.
|
|
*
|
|
* @param field Field to order by
|
|
* @return new Ordering instance
|
|
*/
|
|
public static Ordering ascending(Field field) {
|
|
return new Ordering(field, true);
|
|
}
|
|
|
|
/**
|
|
* Creates an Ordering with a single descending field.
|
|
*
|
|
* @param field Field to order by
|
|
* @return new Ordering instance
|
|
*/
|
|
public static Ordering descending(Field field) {
|
|
return new Ordering(field, false);
|
|
}
|
|
|
|
/**
|
|
* Creates an Ordering with a single ascending field.
|
|
*
|
|
* @param field Field to order by
|
|
* @return new Ordering instance
|
|
*/
|
|
public static Ordering by(Field field) {
|
|
return new Ordering(field, true);
|
|
}
|
|
|
|
}
|