package com.brightgenerous.orm; import static com.brightgenerous.orm.ICloneable.Utils.*; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import com.brightgenerous.commons.EqualsUtils; import com.brightgenerous.commons.HashCodeUtils; import com.brightgenerous.commons.ToStringUtils; import com.brightgenerous.lang.Args; public class Sorts implements Iterable<Sort>, Clearable, ICloneable<Sorts>, Serializable { private static final long serialVersionUID = -8846112615405822485L; private final ConditionContext context; private final UpdatedCallback callback; private List<Sort> list = createList(); private void writeObject(ObjectOutputStream stream) throws IOException { if ((list != null) && !(list instanceof Serializable)) { // convert to java.io.Serializable list = new LinkedList<>(list); } stream.defaultWriteObject(); } private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); if (list != null) { List<Sort> tmp = createList(); if (tmp != null) { Class<?> clazz = list.getClass(); Class<?> tClazz = tmp.getClass(); if (!tClazz.isAssignableFrom(clazz)) { tmp.addAll(list); list = tmp; } } } } protected Sorts(ConditionContext context, UpdatedCallback callback) { this.context = context; this.callback = callback; } protected String convertKey(Object key) { if (key == null) { return null; } if (key instanceof TypeKey) { key = ((TypeKey<?, ?>) key).getKey(); } if (key instanceof Sort) { return ((Sort) key).getKey(); } if (key instanceof String) { return (String) key; } return String.valueOf(key); } protected void notNullKey(Object key) { Args.notNull(key, "key"); if (key instanceof TypeKey) { Args.notNull(((TypeKey<?, ?>) key).getKey(), "TypeKey.key"); } } private List<Sort> createList() { return new LinkedList<>(); } protected ConditionContext getContext() { return context; } @Override public Iterator<Sort> iterator() { return list.iterator(); } public void appendAsc(List<Object> keys) { if ((keys != null) && !keys.isEmpty()) { for (Object k : keys) { notNullKey(k); } for (Object k : keys) { append(k, true); } } } public void appendAsc(Object[] keys) { if ((keys == null) || (keys.length < 1)) { return; } appendAsc(Arrays.asList(keys)); } public void appendAsc(Object key, Object... keys) { List<Object> ks = new ArrayList<>(((keys == null) ? 0 : keys.length) + 1); ks.add(key); if ((keys != null) && (0 < keys.length)) { for (Object k : keys) { ks.add(k); } } appendAsc(ks); } public void appendDesc(List<Object> keys) { if ((keys != null) && !keys.isEmpty()) { for (Object k : keys) { notNullKey(k); } for (Object k : keys) { append(k, false); } } } public void appendDesc(Object[] keys) { if ((keys == null) || (keys.length < 1)) { return; } appendDesc(Arrays.asList(keys)); } public void appendDesc(Object key, Object... keys) { List<Object> ks = new ArrayList<>(((keys == null) ? 0 : keys.length) + 1); ks.add(key); if ((keys != null) && (0 < keys.length)) { for (Object k : keys) { ks.add(k); } } appendDesc(ks); } public void append(Object key, boolean asc) { notNullKey(key); prvAdd(getContext().newSort(convertKey(key), asc)); } public void prependAsc(List<Object> keys) { if ((keys != null) && !keys.isEmpty()) { for (Object k : keys) { notNullKey(k); } for (Object k : keys) { prepend(k, true); } } } public void prependAsc(Object[] keys) { if ((keys == null) || (keys.length < 1)) { return; } prependAsc(Arrays.asList(keys)); } public void prependAsc(Object key, Object... keys) { List<Object> ks = new ArrayList<>(((keys == null) ? 0 : keys.length) + 1); ks.add(key); if ((keys != null) && (0 < keys.length)) { for (Object k : keys) { ks.add(k); } } prependAsc(ks); } public void prependDesc(List<Object> keys) { if ((keys != null) && !keys.isEmpty()) { for (Object k : keys) { notNullKey(k); } for (Object k : keys) { prepend(k, false); } } } public void prependDesc(Object[] keys) { if ((keys == null) || (keys.length < 1)) { return; } prependDesc(Arrays.asList(keys)); } public void prependDesc(Object key, Object... keys) { List<Object> ks = new ArrayList<>(((keys == null) ? 0 : keys.length) + 1); ks.add(key); if ((keys != null) && (0 < keys.length)) { for (Object k : keys) { ks.add(k); } } prependDesc(ks); } public void prepend(Object key, boolean asc) { notNullKey(key); prvAdd(0, getContext().newSort(convertKey(key), asc)); } public void insertAsc(int index, List<Object> keys) { if ((keys != null) && !keys.isEmpty()) { for (Object k : keys) { notNullKey(k); } for (Object k : keys) { insert(index, k, true); } } } public void insertAsc(int index, Object[] keys) { if ((keys == null) || (keys.length < 1)) { return; } insertAsc(index, Arrays.asList(keys)); } public void insertAsc(int index, Object key, Object... keys) { List<Object> ks = new ArrayList<>(((keys == null) ? 0 : keys.length) + 1); ks.add(key); if ((keys != null) && (0 < keys.length)) { for (Object k : keys) { ks.add(k); } } insertAsc(index, ks); } public void insertDesc(int index, List<Object> keys) { if ((keys != null) && !keys.isEmpty()) { for (Object k : keys) { notNullKey(k); } for (Object k : keys) { insert(index, k, false); } } } public void insertDesc(int index, Object[] keys) { if ((keys == null) || (keys.length < 1)) { return; } insertDesc(index, Arrays.asList(keys)); } public void insertDesc(int index, Object key, Object... keys) { List<Object> ks = new ArrayList<>(((keys == null) ? 0 : keys.length) + 1); ks.add(key); if ((keys != null) && (0 < keys.length)) { for (Object k : keys) { ks.add(k); } } insertDesc(index, ks); } public void insert(int index, Object key, boolean asc) { notNullKey(key); prvAdd(index, getContext().newSort(convertKey(key), asc)); } private void prvAdd(Sort sort) { Args.notNull(sort, "sort"); prvRemove(sort); list.add(sort); callbackUpdated(); } private void prvAdd(int index, Sort sort) { Args.notNull(sort, "sort"); int size = list.size(); if ((index < 0) || (size < index)) { throw new IndexOutOfBoundsException(String.format( "The index is out of range. size => %d, index => %d", Integer.valueOf(size), Integer.valueOf(index))); } prvRemove(sort); list.add(index, sort); callbackUpdated(); } public boolean isEmpty() { return list.isEmpty(); } @Override public void clear() { if (!list.isEmpty()) { list.clear(); callbackUpdated(); } } public void remove(Object key) { if (prvRemove(key)) { callbackUpdated(); } } public void removeAll(Collection<?> keys) { if ((keys == null) || keys.isEmpty()) { return; } boolean del = false; for (Object k : keys) { del |= prvRemove(k); } if (del) { callbackUpdated(); } } public void removeAll(Object[] keys) { if ((keys == null) || (keys.length < 1)) { return; } removeAll(Arrays.asList(keys)); } public void removeAll(Object key, Object... keys) { List<Object> ks = new ArrayList<>(((keys == null) ? 0 : keys.length) + 1); ks.add(key); if ((keys != null) && (0 < keys.length)) { for (Object k : keys) { ks.add(k); } } removeAll(ks); } private boolean prvRemove(Object key) { if (key == null) { return false; } String k = convertKey(key); if (k == null) { return false; } Sort del = null; for (Sort sort : list) { String sk = sort.getKey(); if ((sk != null) && k.equals(sk)) { del = sort; break; } } if (del == null) { return false; } return list.remove(del); } public List<? extends Sort> getAll(List<Object> keys) { List<Sort> ret = new ArrayList<>((keys == null) ? 0 : keys.size()); if ((keys != null) && !keys.isEmpty()) { for (Object k : keys) { Sort sort = prvGetContains(k); if (sort != null) { ret.add(sort); } } } return Collections.unmodifiableList(ret); } public List<? extends Sort> getAll(Object[] keys) { if ((keys == null) || (keys.length < 1)) { return Collections.EMPTY_LIST; } return getAll(Arrays.asList(keys)); } public List<? extends Sort> getAll(Object key, Object... keys) { List<Object> os = new ArrayList<>(((keys == null) ? 0 : keys.length) + 1); os.add(key); if ((keys != null) && (0 < keys.length)) { for (Object k : keys) { os.add(k); } } return getAll(os); } private Sort prvGetContains(Object key) { if (key == null) { return null; } String k = convertKey(key); if (k == null) { return null; } for (Sort s : list) { if (s == null) { continue; } String sk = s.getKey(); if ((sk != null) && k.equals(sk)) { return s; } } return null; } @Override public Sorts clone() { Sorts ret; try { ret = (Sorts) super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(e.getMessage()); } ret.list = createList(); for (Sort sort : list) { ret.list.add(getIfClone(sort)); } return ret; } private void callbackUpdated() { if (callback != null) { callback.updated(); } } @Override public int hashCode() { if (HashCodeUtils.resolved()) { return HashCodeUtils.hashCodeAlt(null, this); } return super.hashCode(); } @Override public boolean equals(Object obj) { if (EqualsUtils.resolved()) { return EqualsUtils.equalsAlt(null, this, obj); } return super.equals(obj); } @Override public String toString() { if (ToStringUtils.resolved()) { return ToStringUtils.toStringAlt(this); } return super.toString(); } }