/** * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.ut.biolab.medsavant.client.query; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.ut.biolab.medsavant.client.query.SearchConditionItem.SearchConditionListener; import org.ut.biolab.medsavant.client.query.view.SearchConditionItemView; /** * * @author mfiume */ public class SearchConditionGroupItem extends SearchConditionItem implements SearchConditionListener { private final List<SearchConditionItem> items; private static int groupNo; private final int thisGroupNo; public enum QueryRelation { AND { @Override public String toString() { return "and"; }; }, OR { @Override public String toString() { return "or"; }; } }; public SearchConditionGroupItem(SearchConditionGroupItem parent) { this(QueryRelation.AND, parent); } public SearchConditionGroupItem(QueryRelation r, SearchConditionItem i, SearchConditionGroupItem parent) { super(null, r, parent); thisGroupNo = (++groupNo); items = new ArrayList<SearchConditionItem>(); if (i != null) { items.add(i); i.setParent(this); i.addListener(this); } } public boolean isGroup(){ return true; } @Override public String getName() { return "Group " + thisGroupNo; } public boolean isFirstItem(SearchConditionItem item) { return items.indexOf(item) == 0; } public SearchConditionGroupItem(QueryRelation r, SearchConditionGroupItem parent) { this(r, null, parent); } @Override public String toString() { String s = ""; for (int i = 0; i < items.size(); i++) { SearchConditionItem item = items.get(i); if (item instanceof SearchConditionGroupItem) { s += "(" + item.toString() + ")"; } else { s += item.toString(); } if (i != items.size()) { s += " " + this.getRelation() + " "; } } return s; } protected String toXML(int indent){ String tab = ""; for(int i = 0; i < indent; ++i){ tab += "\t"; } String xml = tab + "<Group "; xml += " queryRelation=\""+escape(getRelation().toString()) + "\""; if(getDescription() != null){ xml += " description=\""+escape(getDescription())+"\""; } xml += ">\n"; for(SearchConditionItem sci : items){ xml += sci.toXML(indent+1); } xml += tab+"</Group>\n"; return xml; } public String toXML(){ return this.toXML(0); } public void removeItem(SearchConditionItem i) { i.removeListener(this); items.remove(i); i.setParent(null); // the only child is a group // Commented out, June 8,2013 // The group functionality is being used to search Genomic Regions (sets // of (chromosome, position) tuples), and it's easier if these always // stay grouped. /* if (items.size() == 1 && items.get(0) instanceof SearchConditionGroupItem) { SearchConditionGroupItem child = (SearchConditionGroupItem) items.get(0); for (SearchConditionItem c : child.getItems()) { c.removeListener(child); child.items.remove(i); c.setParent(null); c.addListener(this); c.setParent(this); items.add(c); } child.removeListener(this); this.items.remove(child); child.setParent(null); } */ // remove the group entirely, parent notifies of update if (items.isEmpty() && this.getParent() != null) { this.getParent().removeItem(this); // notify listeners of change } else { fireSearchConditionOrderChangedEvent(); fireSearchConditionItemRemovedEvent(i); } } public void addItem(SearchConditionItem i, int atIndex) { i.addListener(this); i.setParent(this); items.add(atIndex, i); fireSearchConditionOrderChangedEvent(); fireSearchConditionItemAddedEvent(i); } public void addItem(SearchConditionItem i) { addItem(i, items.size()); // add to the end } public void createGroupFromItem(SearchConditionItem i) { i.removeListener(this); int indexOfItem = items.indexOf(i); items.remove(i); SearchConditionGroupItem g = new SearchConditionGroupItem(QueryRelation.AND, i, this); addItem(g, indexOfItem); } public void moveItemToGroupAtIndex(SearchConditionItem i, SearchConditionGroupItem g, int newIndex) { i.removeListener(this); items.remove(i); i.setParent(null); g.addItem(i); g.moveItemToIndex(i, newIndex); fireSearchConditionOrderChangedEvent(); } public void moveItemToGroup(SearchConditionItem i, SearchConditionGroupItem g) { i.removeListener(this); items.remove(i); i.setParent(null); g.addItem(i); if(items.size() < 1){ if(getParent() != null){ getParent().removeItem(this); } }else{ fireSearchConditionOrderChangedEvent(); } } public void moveItemToIndex(SearchConditionItem i, int newIndex) { int currentIndex = items.indexOf(i); items.remove(i); items.add(newIndex, i); fireSearchConditionOrderChangedEvent(); } public void clearItems() { for (SearchConditionItem i : items) { i.removeListener(this); } this.items.removeAll(items); fireSearchConditionOrderChangedEvent(); } public List<SearchConditionItem> getItems() { return this.items; } @Override public void searchConditionsOrderChanged(SearchConditionItem m) { this.fireSearchConditionOrderChangedEvent(); } @Override public void searchConditionItemRemoved(SearchConditionItem m) { this.fireSearchConditionItemRemovedEvent(m); } @Override public void searchConditionItemAdded(SearchConditionItem m) { this.fireSearchConditionItemAddedEvent(m); } @Override public void searchConditionEdited(SearchConditionItem m) { this.fireSearchConditionsEditedEvent(m); } }