
edu.uiuc.ncsa.security.storage.GenericStoreUtils Maven / Gradle / Ivy
package edu.uiuc.ncsa.security.storage;
import edu.uiuc.ncsa.security.core.DateComparable;
import edu.uiuc.ncsa.security.core.Identifiable;
import edu.uiuc.ncsa.security.core.Store;
import edu.uiuc.ncsa.security.core.util.StringUtils;
import java.util.*;
import java.util.regex.Pattern;
/**
* This is where static generic methods for stores like searches live.
* These are horribly inefficient but sometimes there is no other
* way. The intent is that if you need to use these, they are centralized
* to prevent boiler plating.
* Created by Jeff Gaynor
* on 8/10/21 at 6:38 AM
*/
public class GenericStoreUtils {
public static List search(Store store,
String key,
String condition,
boolean isRegEx,
List attr) {
ArrayList results = new ArrayList();
Collection values = store.values();
Iterator iterator = values.iterator();
Pattern pattern = null;
if (isRegEx) {
pattern = Pattern.compile(condition);
}
while (iterator.hasNext()) {
V v = (V) iterator.next();
XMLMap map = new XMLMap();
store.getXMLConverter().toMap(v, map);
String targetValue = map.get(key).toString();
boolean keepV = false;
if (isRegEx) {
keepV = pattern.matcher(targetValue).matches();
} else {
keepV = targetValue.equals(condition);
}
if (keepV) {
map.removeKeys(attr); // return subset
results.add(store.getXMLConverter().fromMap(map, null));
}
}
return results;
}
public static List search(Store store,
String key,
String condition,
boolean isRegEx,
List attr,
String dateField,
Date before, Date after) {
ArrayList results = new ArrayList();
Collection values = store.values();
Iterator iterator = values.iterator();
boolean hasKey = !StringUtils.isTrivial(key);
boolean hasDate = !StringUtils.isTrivial(dateField);
Pattern pattern = null;
if (hasKey && isRegEx) {
pattern = Pattern.compile(condition);
}
while (iterator.hasNext()) {
V v = (V) iterator.next();
XMLMap map = new XMLMap();
store.getXMLConverter().toMap(v, map);
boolean keepV = true;
if (hasKey) {
String targetValue = map.get(key).toString();
if (isRegEx) {
keepV = !pattern.matcher(targetValue).matches();
} else {
keepV = !targetValue.equals(condition);
}
}
if (!keepV) {
continue;
}
if (hasDate) {
if (after != null) {
keepV = 0 <= map.getDate(dateField).compareTo(after);
}
if (before != null) {
keepV = map.getDate(dateField).compareTo(before) <= 0;
}
}
if (keepV) {
map.removeKeys(attr); // return subset
results.add(store.getXMLConverter().fromMap(map, null));
}
}
return results;
}
public static List getMostRecent(Store store, int n, List attributes) {
// Some black magic in Java to cast everything in the Collection as some other type.
// Casts between different object types are finicky, but you can cast a collection of
// objects to anything. Do this so if we ever change our inheritance later it does not break
Collection extends Object> list = store.values();
ArrayList results = new ArrayList();
if (list.isEmpty() || n == 0) {
return results;
}
if (!(list.iterator().next() instanceof DateComparable)) {
throw new UnsupportedOperationException("getting the most recent object is not supported by this store.");
}
// Can still blow up if one of the objects is not DateComparable. Best we can do in Java....
Collection values = (Collection) list;
SortByDate sortByDate = new SortByDate();
TreeSet treeSet = new TreeSet<>(sortByDate);
treeSet.addAll(values);
Iterator iterator;
if (n < 0) {
iterator = treeSet.descendingSet().iterator();// creates a view, then returns iterator in it
n = Math.abs(n);
} else {
iterator = treeSet.iterator();
}
// We are constrained by both n and the number of elements in the store.
// If the store has < n elements, don't try to return extras.
int i = 0;
while (iterator.hasNext() && i < n) {
results.add((V) iterator.next());
i++;
}
return results;
}
static class SortByDate implements Comparator {
@Override
public int compare(V a, V b) {
return a.getCreationTS().compareTo(b.getCreationTS());
}
}
/**
* Convert an identifiable object to an {@link XMLMap}. This is useful for serializing
* objects in the store, backing them up, etc.
* @param store
* @param identifiable
* @return
*/
public static XMLMap toXML(Store store, Identifiable identifiable) {
XMLMap map = new XMLMap();
store.getXMLConverter().toMap(identifiable, map);
return map;
}
/**
* This will convert a map into an object. You must issue a save separately or
* if you prefer, {@link #fromXMLAndSave(Store, XMLMap)}.
* @param store
* @param map
* @return
*/
public static Identifiable fromXML(Store store, XMLMap map) {
return store.getXMLConverter().fromMap(map, null);
}
public static void fromXMLAndSave(Store store, XMLMap map){
store.save(fromXML(store, map));
}
}