package de.hftstuttgart.unifiedticketing.core; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; /** * Filtered Ticket Request
*
* This class provides a builder like interface, * to get a filtered list of Tickets.
*
* It provides some basic filter options by itself. * The request logic has to be provided from each System specific * implementation for it. * * @param The type of Ticket this Filter implementation delivers * @param The type of the System specific implementation of this class */ public abstract class Filter> { private static Logger logger = Logging.getLogger(Filter.class.getName()); protected int lastReceivedItemCount; protected Map setFilters;// = new HashMap<>(); protected enum FilterNames { ASSIGNEEID, ASSIGNEENAME, DESCRIPTION_CONTAIN, DESCRIPTION_MATCH, IDS, LABELS, OPEN, PAGE, PAGINATION, TITLE_CONTAINS, TITLE_MATCH, } public Filter() { logger.log(Level.FINEST, String.format( "%s request builder started", this.getClass().getSimpleName() )); setFilters = new HashMap<>(); lastReceivedItemCount = -1; } /** * Counter how many items received on last {@link #get()} call. * * As local filtering can lower the items delivered from {@link #get()}, * you can't check that no more pages are available comparing the delivered item * count with your set page size.
* * @return item count received from external Ticketsystem on last call of {@link #get()} */ public int getLastReceivedItemCount() { return lastReceivedItemCount; } /** * Add assignee id to query * @return this query builder */ public F withAssigneeId(String id) { addToSet(FilterNames.ASSIGNEEID, this.setFilters, id); return (F) this; } /** * Add assignee name to query * @return this query builder */ public F withAssigneeName(String name) { addToSet(FilterNames.ASSIGNEENAME, this.setFilters, name); return (F) this; } /** * adds description contain constraint * @param substring element to be contained in the description * @return this query builder */ public F withDescriptionContain(String substring) { setFilters.put(FilterNames.DESCRIPTION_CONTAIN.name(), substring); logger.log(Level.FINEST, String.format("added constraint: %s %s", FilterNames.DESCRIPTION_CONTAIN.name(), substring)); return (F) this; } /** * regex that the whole description must match * @param regex fully qualified regex * @return this query builder */ public F withDescriptionMatch(String regex) { setFilters.put(FilterNames.DESCRIPTION_MATCH.name(), regex); logger.log(Level.FINEST, String.format("added constraint: %s %s", FilterNames.DESCRIPTION_MATCH.name(), regex)); return (F) this; } /** * adds an ticket id to the constraint list * @param id * @return this query builder */ public F withId(String id) { addToSet(FilterNames.IDS, this.setFilters, id); return (F) this; } /** * adds a constraint for only open considered tickets * @return this query builder */ public F isOpen() { setFilters.put(FilterNames.OPEN.name(), true); logger.log(Level.FINEST, String.format("added constraint: %s %s", FilterNames.OPEN.name(), true)); return (F) this; } /** * adds a constraint for only closed considered tickets * @return this query builder */ public F isClosed() { setFilters.put(FilterNames.OPEN.name(), false); logger.log(Level.FINEST, String.format("added constraint: %s %s", FilterNames.OPEN.name(), false)); return (F) this; } /** * add a label to the constraints list
*
* multiple calls of this delivers only tickets holding ALL given labels. * @param label * @return this query builder */ public F withLabel(String label) { addToSet(FilterNames.LABELS, this.setFilters, label); return (F) this; } /** * set the page number of the pagination
*
* Attention: some systems paginate by default. * You can check that with {@link TicketSystem}s "has..." methods. * @param page * @return this query builder */ public F setPage(int page) { this.setFilters.put(FilterNames.PAGE.name(), page); logger.log(Level.FINEST, String.format("set page: %d", page)); return (F) this; } /** * defines the page size of a single pagination page
*
* Attention: some systems have a default in place, if nothing custom is set. * You can check that with {@link TicketSystem}s "has..." methods. * @param size * @return this query builder */ public F setPageSize(int size) { this.setFilters.put(FilterNames.PAGINATION.name(), size); logger.log(Level.FINEST, String.format("set pagination size: %d", size)); return (F) this; } /** * adds a constraint for title containing the given string * @param substring string the title must contain * @return this query builder */ public F withTitleContain(String substring) { setFilters.put(FilterNames.TITLE_CONTAINS.name(), substring); logger.log(Level.FINEST, String.format("added constraint: %s %s", FilterNames.TITLE_CONTAINS.name(), substring)); return (F) this; } /** * adds a regex constraint, that the title has to match * @param regex fully qualified regex * @return this query builder */ public F withTitleMatch(String regex) { setFilters.put(FilterNames.TITLE_MATCH.name(), regex); logger.log(Level.FINEST, String.format("added constraint: %s %s", FilterNames.TITLE_MATCH.name(), regex)); return (F) this; } /** * Requesting the tickets
*
* This will prepare the request according to the system specific implementation, * run the request, if needed post-filter the results and form it into a List * @return List of Tickets, matching all previously set constraints */ public abstract List get(); protected static void addToSet(FilterNames filterName, Map map, String newValue) { logger.log(Level.FINEST, String.format("attempting to add new %s constraint", filterName.name())); Set values; if (map.containsKey(filterName.name())) { logger.log(Level.FINEST, String.format("existing %s constraints found", filterName.name())); Object stored = map.get(filterName.name()); if (stored instanceof Set) { values = (Set) stored; } else { logger.log(Level.WARNING, String.format( "found filter object under key %s was not from Type %s but %s", filterName.name(), Set.class.getName(), stored.getClass().getName())); values = new HashSet<>(); map.put(filterName.name(), values); logger.log(Level.INFO, String.format( "replaced wrong typed filter object under key %s with new instance of type %s", filterName.name(), Set.class.getName())); } } else { logger.log(Level.FINEST, String.format("no previous %s constraints found", filterName)); values = new HashSet<>(); map.put(filterName.name(), values); } values.add(newValue); logger.log(Level.FINEST, String.format("added constraint: %s %s", filterName.name(), newValue)); } }