001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.admin.dso;
005:
006: import com.tc.admin.AdminClient;
007: import com.tc.admin.AdminClientContext;
008: import com.tc.admin.ConnectionContext;
009: import com.tc.admin.common.XAbstractAction;
010: import com.tc.admin.common.XTreeModel;
011: import com.tc.admin.common.XTreeNode;
012:
013: import java.awt.event.ActionEvent;
014: import java.awt.event.KeyEvent;
015: import java.awt.event.MouseEvent;
016: import java.util.Vector;
017:
018: import javax.swing.Icon;
019: import javax.swing.JPopupMenu;
020: import javax.swing.JTree;
021: import javax.swing.KeyStroke;
022: import javax.swing.SwingUtilities;
023: import javax.swing.event.TreeSelectionEvent;
024: import javax.swing.tree.TreeNode;
025: import javax.swing.tree.TreePath;
026:
027: public class FieldTreeNode extends XTreeNode implements
028: DSOObjectTreeNode {
029: protected ConnectionContext m_cc;
030: protected DSOField m_field;
031: private MoreAction m_moreAction;
032: private LessAction m_lessAction;
033: private JPopupMenu m_popupMenu;
034: private int m_batchSize;
035: private RefreshAction m_refreshAction;
036:
037: private static final String REFRESH_ACTION = "RefreshAction";
038:
039: public FieldTreeNode(ConnectionContext cc, DSOField field) {
040: super (field);
041:
042: m_cc = cc;
043: m_field = field;
044: m_batchSize = ConnectionContext.DSO_SMALL_BATCH_SIZE;
045:
046: if (!field.isPrimitive()) {
047: init();
048: initMenu();
049: }
050: }
051:
052: public DSOObject getDSOObject() {
053: return getField();
054: }
055:
056: protected void init() {
057: int count = m_field.getFieldCount();
058:
059: if (children == null) {
060: children = new Vector();
061: }
062: children.setSize(count);
063: }
064:
065: private void initMenu() {
066: m_refreshAction = new RefreshAction();
067:
068: m_popupMenu = new JPopupMenu("Root Actions");
069: m_popupMenu.add(m_refreshAction);
070:
071: if (m_field.isArray() || m_field.isCollection()) {
072: m_popupMenu.add(m_moreAction = new MoreAction());
073: m_popupMenu.add(m_lessAction = new LessAction());
074: }
075:
076: addActionBinding(REFRESH_ACTION, m_refreshAction);
077: }
078:
079: public JPopupMenu getPopupMenu() {
080: return m_popupMenu;
081: }
082:
083: public DSOField getField() {
084: return m_field;
085: }
086:
087: private void fillInChildren() {
088: int childCount = getChildCount();
089: boolean nso = false;
090:
091: for (int i = 0; i < childCount; i++) {
092: if (children.elementAt(i) == null) {
093: DSOObject field = m_field.getField(i);
094: XTreeNode child = createFieldNode(field);
095:
096: children.setElementAt(child, i);
097: child.setParent(FieldTreeNode.this );
098:
099: if (field == null) {
100: nso = true;
101: }
102: }
103: }
104:
105: if (nso) {
106: SwingUtilities.invokeLater(new AncestorReaper());
107: }
108: }
109:
110: class AncestorReaper implements Runnable {
111: public void run() {
112: XTreeNode node = FieldTreeNode.this ;
113:
114: while (node != null) {
115: if (node instanceof FieldTreeNode) {
116: FieldTreeNode ftn = (FieldTreeNode) node;
117:
118: if (ftn.getField().isValid()) {
119: ftn.refreshChildren();
120: return;
121: }
122: } else if (node instanceof RootTreeNode) {
123: ((RootTreeNode) node).refresh();
124: return;
125: }
126:
127: node = (XTreeNode) node.getParent();
128: }
129: }
130: }
131:
132: public TreeNode getChildAt(int index) {
133: if (children != null && children.elementAt(index) == null) {
134: AdminClientContext acc = AdminClient.getContext();
135:
136: acc.controller.block();
137: fillInChildren();
138: acc.controller.unblock();
139: }
140:
141: return super .getChildAt(index);
142: }
143:
144: private XTreeNode createFieldNode(DSOObject field) {
145: return RootsHelper.getHelper().createFieldNode(m_cc, field);
146: }
147:
148: public int getChildCount() {
149: return m_field != null ? m_field.getFieldCount() : 0;
150: }
151:
152: public Icon getIcon() {
153: RootsHelper helper = RootsHelper.getHelper();
154:
155: return m_field.isCycle() ? helper.getCycleIcon() : helper
156: .getFieldIcon();
157: }
158:
159: public void nodeSelected(TreeSelectionEvent e) {
160: if (m_field.isCycle()) {
161: DSOObject cycleRoot = m_field.getCycleRoot();
162: XTreeNode parentNode = (XTreeNode) getParent();
163:
164: while (parentNode != null) {
165: if (parentNode instanceof DSOObjectTreeNode) {
166: if (((DSOObjectTreeNode) parentNode).getDSOObject() == cycleRoot) {
167: JTree tree = (JTree) e.getSource();
168: TreePath path = new TreePath(parentNode
169: .getPath());
170: TreePath[] paths = ((JTree) e.getSource())
171: .getSelectionPaths();
172: TreePath[] newPaths = new TreePath[paths.length + 1];
173:
174: newPaths[0] = path;
175: System.arraycopy(paths, 0, newPaths, 1,
176: paths.length);
177: tree.getSelectionModel().setSelectionPaths(
178: newPaths);
179: return;
180: }
181: }
182:
183: parentNode = (XTreeNode) parentNode.getParent();
184: }
185: }
186: }
187:
188: public void refreshChildren() {
189: tearDownChildren();
190:
191: if (m_field != null) {
192: m_field.initFields();
193: children.setSize(getChildCount());
194: fillInChildren();
195: }
196:
197: getModel().nodeStructureChanged(this );
198: }
199:
200: public void refresh() {
201: AdminClientContext acc = AdminClient.getContext();
202: boolean expanded = acc.controller.isExpanded(this );
203: XTreeModel model = getModel();
204: XTreeNode node;
205:
206: for (int i = getChildCount() - 1; i >= 0; i--) {
207: node = (XTreeNode) getChildAt(i);
208: node.tearDown();
209: model.removeNodeFromParent(node);
210: }
211:
212: try {
213: m_field.refresh();
214: } catch (Exception e) {
215: // TODO: ask parent to teardown
216: e.printStackTrace();
217: }
218:
219: init();
220:
221: model.nodeStructureChanged(FieldTreeNode.this );
222: if (expanded) {
223: acc.controller.expand(this );
224: }
225: }
226:
227: private class RefreshAction extends XAbstractAction {
228: private RefreshAction() {
229: super ("Refresh", RootsHelper.getHelper().getRefreshIcon());
230: setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0,
231: true));
232: }
233:
234: public void actionPerformed(ActionEvent ae) {
235: AdminClientContext acc = AdminClient.getContext();
236: String name = m_field.getName();
237:
238: acc.controller
239: .setStatus("Refreshing field " + name + "...");
240: acc.controller.block();
241:
242: refresh();
243:
244: acc.controller.clearStatus();
245: acc.controller.unblock();
246: }
247: }
248:
249: public void nodeClicked(MouseEvent me) {
250: if (m_refreshAction != null) {
251: m_refreshAction.actionPerformed(null);
252: }
253: }
254:
255: private class MoreAction extends XAbstractAction {
256: private MoreAction() {
257: super ("More");
258: }
259:
260: public void actionPerformed(ActionEvent ae) {
261: AdminClientContext acc = AdminClient.getContext();
262: String name = m_field.getName();
263:
264: if (incrementDSOBatchSize() == ConnectionContext.DSO_MAX_BATCH_SIZE) {
265: setEnabled(false);
266: }
267: m_lessAction.setEnabled(true);
268: m_field.setBatchSize(m_batchSize);
269:
270: acc.controller.setStatus("Refreshing root " + name + "...");
271: acc.controller.block();
272:
273: refresh();
274:
275: acc.controller.clearStatus();
276: acc.controller.unblock();
277: }
278: }
279:
280: private class LessAction extends XAbstractAction {
281: private LessAction() {
282: super ("Less");
283: setEnabled(false);
284: }
285:
286: public void actionPerformed(ActionEvent ae) {
287: AdminClientContext acc = AdminClient.getContext();
288: String name = m_field.getName();
289:
290: if (decrementDSOBatchSize() == ConnectionContext.DSO_SMALL_BATCH_SIZE) {
291: setEnabled(false);
292: }
293: m_moreAction.setEnabled(true);
294: m_field.setBatchSize(m_batchSize);
295:
296: acc.controller
297: .setStatus("Refreshing field " + name + "...");
298: acc.controller.block();
299:
300: refresh();
301:
302: acc.controller.clearStatus();
303: acc.controller.unblock();
304: }
305: }
306:
307: int incrementDSOBatchSize() {
308: switch (m_batchSize) {
309: case ConnectionContext.DSO_SMALL_BATCH_SIZE:
310: m_batchSize = ConnectionContext.DSO_MEDIUM_BATCH_SIZE;
311: break;
312: case ConnectionContext.DSO_MEDIUM_BATCH_SIZE:
313: m_batchSize = ConnectionContext.DSO_LARGE_BATCH_SIZE;
314: break;
315: case ConnectionContext.DSO_LARGE_BATCH_SIZE:
316: m_batchSize = ConnectionContext.DSO_MAX_BATCH_SIZE;
317: break;
318: }
319:
320: return m_batchSize;
321: }
322:
323: int decrementDSOBatchSize() {
324: switch (m_batchSize) {
325: case ConnectionContext.DSO_MEDIUM_BATCH_SIZE:
326: m_batchSize = ConnectionContext.DSO_SMALL_BATCH_SIZE;
327: break;
328: case ConnectionContext.DSO_LARGE_BATCH_SIZE:
329: m_batchSize = ConnectionContext.DSO_MEDIUM_BATCH_SIZE;
330: break;
331: case ConnectionContext.DSO_MAX_BATCH_SIZE:
332: m_batchSize = ConnectionContext.DSO_LARGE_BATCH_SIZE;
333: break;
334: }
335:
336: return m_batchSize;
337: }
338:
339: public int resetDSOBatchSize() {
340: return m_batchSize = ConnectionContext.DSO_SMALL_BATCH_SIZE;
341: }
342:
343: public void tearDown() {
344: super.tearDown();
345:
346: m_cc = null;
347: m_field = null;
348: }
349: }
|