001: package org.osbl.agent.gui;
002:
003: import java.util.Arrays;
004: import java.util.Comparator;
005: import java.util.List;
006:
007: import org.osbl.agent.model.Rule;
008: import org.wingx.table.XTableModel;
009:
010: /**
011: * The table-model for the table in the SidePanel showing the Rules.
012: *
013: * @author Sebastian Nozzi.
014: */
015: abstract class SidePanelTableModel extends XTableModel {
016:
017: /** The current user. */
018: private String currentUser;
019:
020: /**
021: * Gets the current rules, taking the filters into account.
022: *
023: * @return the current rules
024: */
025: abstract List<Rule> getCurrentRules();
026:
027: /**
028: * Called when the Rules are updated.
029: */
030: abstract void rulesUpdated();
031:
032: /**
033: * Gets the current user.
034: *
035: * @return the current user
036: */
037: public String getCurrentUser() {
038: return currentUser;
039: }
040:
041: /**
042: * Sets the current user.
043: *
044: * @param currentUser the new current user
045: */
046: public void setCurrentUser(String currentUser) {
047: this .currentUser = currentUser;
048: }
049:
050: /*
051: * (non-Javadoc)
052: *
053: * @see javax.swing.table.AbstractTableModel#getColumnClass(int)
054: */
055: public Class<?> getColumnClass(int columnIndex) {
056:
057: // As the first column corresponds to the Rule name...
058: if (columnIndex == 0)
059: // ...class of column is String
060: return String.class;
061: // The second column corresponds to the public/non-public checkbox...
062: else
063: // ...which results in a Boolean value.
064: return Boolean.class;
065: }
066:
067: /*
068: * (non-Javadoc)
069: *
070: * @see javax.swing.table.TableModel#getColumnCount()
071: */
072: public int getColumnCount() {
073: // Columns are "name" and "public" (or not).
074: return 2;
075: }
076:
077: /*
078: * (non-Javadoc)
079: *
080: * @see javax.swing.table.AbstractTableModel#getColumnName(int)
081: */
082: public String getColumnName(int columnIndex) {
083: final String[] names = { DesignContext.getMsg("name"),
084: DesignContext.getMsg("public") };
085: return names[columnIndex];
086: }
087:
088: /*
089: * (non-Javadoc)
090: *
091: * @see javax.swing.table.TableModel#getRowCount()
092: */
093: public int getRowCount() {
094: // There are as many rows as applicable (depending on selected
095: // process/activity pair) Rules.
096: int result = getCurrentRules().size();
097: return result;
098: }
099:
100: /*
101: * (non-Javadoc)
102: *
103: * @see javax.swing.table.TableModel#getValueAt(int, int)
104: */
105: public Object getValueAt(int rowIndex, int columnIndex) {
106:
107: Object result = null;
108:
109: // ...
110: Rule aRule = getCurrentRules().get(rowIndex);
111:
112: // First column is Rules's name.
113: if (columnIndex == 0) {
114: result = aRule.getName();
115: // If the name is too long...
116: if (((String) result).length() > 16)
117: // ...truncate it.
118: result = ((String) result).substring(0, 16) + "...";
119: }
120: // Second column is the Rule's public state...
121: if (columnIndex == 1) {
122:
123: // For Rules that the user owns, return the public state...
124: if (aRule.getCreatorUser().equals(currentUser))
125: // ...as a Boolean instance.
126: result = new Boolean(aRule.isPublic());
127: // For foreign Rules return the creator's user-id as a String.
128: else
129: result = aRule.getCreatorUser();
130: }
131:
132: // Return the gathered result.
133: return result;
134: }
135:
136: /*
137: * (non-Javadoc)
138: *
139: * @see javax.swing.table.AbstractTableModel#isCellEditable(int, int)
140: */
141: public boolean isCellEditable(int rowIndex, int columnIndex) {
142: // Cell is not directly editable (which would allow the Rule's name to
143: // be editable after a double-click) but through custom renderers.
144: return false;
145: }
146:
147: /*
148: * (non-Javadoc)
149: *
150: * @see javax.swing.table.AbstractTableModel#setValueAt(java.lang.Object,
151: * int, int)
152: */
153: public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
154:
155: List<Rule> rules = getCurrentRules();
156:
157: // Return immediately if there are no current Rules.
158: if (rules.size() == 0)
159: return;
160:
161: // Get current Rule (from the RulesWithContext).
162: Rule aRule = rules.get(rowIndex);
163:
164: // Return immediately if an attempt is being made to modify
165: // a foreign Rule (not from this user).
166: if (aRule.getCreatorUser().equals(currentUser) == false)
167: return;
168:
169: // After this, the Rule is from the current user.
170:
171: // Let the user change the public/non-public state of the Rule
172: if (columnIndex == 1) {
173:
174: boolean oldPublicStatus = aRule.isPublic();
175: boolean newPublicStatus = ((Boolean) aValue).booleanValue();
176:
177: if (oldPublicStatus != newPublicStatus) {
178:
179: aRule.setPublic(newPublicStatus);
180:
181: // Since the internal state of the Rule changed, we
182: // need to notify of this fact...
183: rulesUpdated();
184: }
185:
186: }
187:
188: }
189:
190: /*
191: * (non-Javadoc)
192: *
193: * @see org.wingx.table.RefreshableModel#refresh()
194: */
195: public void refresh() {
196:
197: // Convert current RuleWithContext list to an array.
198: Rule[] rulesAsArray = getCurrentRules()
199: // Note that we can't call toArray() since we want a RuleWithContext[] and not
200: // an Object[], so we have to use the "too small array" trick.
201: .toArray(new Rule[0]);
202:
203: // Sort our newly created array using a custom-defined criteria, which reflects
204: // the current column-sorting settings of the table...
205: Arrays.sort(rulesAsArray, new Comparator<Rule>() {
206:
207: // Sorting setting for first column (name of Rule).
208: int nameSort = SidePanelTableModel.this .getSort(0);
209: // Sorting setting for second column (public state of Rule).
210: int publicSort = SidePanelTableModel.this .getSort(1);
211:
212: // Compare two RuleWithContext...
213: public int compare(Rule left, Rule right) {
214:
215: // This forces our own Rules to appear first on the table...
216: if (left.getCreatorUser().equals(currentUser)
217: && right.getCreatorUser().equals(currentUser) == false)
218: // Own Rules (left) always win (are "less") over foreign Rules.
219: return -1;
220: // Take the opposite case (foreign, left vs. own, right) into account.
221: else if (left.getCreatorUser().equals(currentUser) == false
222: && right.getCreatorUser().equals(currentUser))
223: return 1;
224:
225: // At this point the Rules are either both our own, or both foreign.
226:
227: // So, further comparison DOES depend on the table criteria from now on.
228:
229: // Are we sorting by name?
230: if (nameSort != XTableModel.SORT_NONE) {
231:
232: // Compare names with String's compareTo...
233: int nameComparison = (left.getName()
234: .compareTo(right.getName()));
235:
236: // If names are not equal
237: if (nameComparison != 0)
238: // Return the String comparison we did, taking into account
239: // the sorting order of the column.
240: return nameComparison
241: * ((nameSort == XTableModel.SORT_ASCENDING) ? 1
242: : -1);
243: else {
244: // Names WERE equal but we are we ALSO sorting by public-state?
245: if (publicSort != XTableModel.SORT_NONE) {
246: // Public-states are different?
247: if (left.isPublic() != right.isPublic()) {
248: // Return boolean comparison modified by
249: // sorting order
250: return (new Boolean(left.isPublic())
251: .compareTo(new Boolean(right
252: .isPublic())))
253: * ((publicSort == XTableModel.SORT_ASCENDING) ? 1
254: : -1);
255: }
256: }
257: }
258: // We are JUST sorting by public-state...
259: } else if (publicSort != XTableModel.SORT_NONE) {
260: // Public-states are different?
261: if (left.isPublic() != right.isPublic()) {
262: // Return boolean comparison modified by sorting
263: // order
264: return (new Boolean(left.isPublic())
265: .compareTo(new Boolean(right.isPublic())))
266: * ((publicSort == XTableModel.SORT_ASCENDING) ? 1
267: : -1);
268: }
269: }
270:
271: // At this point no acceptable comparison criterum was found/met.
272:
273: // Consider the Rules equal and finish the comparison.
274: return 0;
275: }
276: });
277:
278: // Get the List of current RuleWithContext...
279: List<Rule> currentRules = getCurrentRules();
280:
281: // ...empty it...
282: currentRules.clear();
283:
284: // ... and re-fill it with the same RuleWithContext, but ordered...
285: for (Rule r : rulesAsArray) {
286: currentRules.add(r);
287: }
288:
289: // ... force table to re-render...
290: fireTableDataChanged();
291: }
292:
293: }
|