001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package org.terracotta.dso.dialogs;
006:
007: import org.eclipse.jface.dialogs.IDialogConstants;
008: import org.eclipse.jface.viewers.StructuredSelection;
009: import org.eclipse.swt.SWT;
010: import org.eclipse.swt.layout.GridData;
011: import org.eclipse.swt.layout.GridLayout;
012: import org.eclipse.swt.widgets.Button;
013: import org.eclipse.swt.widgets.Composite;
014: import org.eclipse.swt.widgets.Control;
015: import org.eclipse.swt.widgets.Label;
016: import org.eclipse.swt.widgets.List;
017: import org.eclipse.swt.widgets.Shell;
018: import org.eclipse.swt.widgets.TableItem;
019: import org.eclipse.swt.widgets.Text;
020: import org.eclipse.swt.widgets.TreeItem;
021: import org.terracotta.dso.ConfigurationHelper;
022: import org.terracotta.dso.TcPlugin;
023: import org.terracotta.ui.util.SWTUtil;
024:
025: import com.tc.admin.common.AbstractResolutionAction;
026: import com.tc.admin.common.AbstractWorkState;
027: import com.tc.admin.common.NonPortableMessages;
028: import com.tc.admin.common.NonPortableResolutionAction;
029: import com.tc.admin.common.NonPortableWorkState;
030: import com.tc.object.appevent.NonPortableEventContext;
031: import com.tc.object.appevent.NonPortableObjectEvent;
032: import com.terracottatech.config.Include;
033:
034: import java.util.ArrayList;
035: import java.util.Iterator;
036:
037: import javax.swing.tree.DefaultMutableTreeNode;
038:
039: public class NonPortableObjectDialog extends
040: AbstractApplicationEventDialog {
041: private Text fIssueDescription;
042: private IncludeTypesPanel fIncludeTypesView;
043: private Button fPreviousIssueButton, fNextIssueButton,
044: fApplyButton;
045:
046: public NonPortableObjectDialog(Shell parentShell,
047: NonPortableObjectEvent event) {
048: super (
049: parentShell,
050: NonPortableMessages.getString("PROBLEM_SHARING_DATA"), event, new String[] { //$NON-NLS-1$
051: IDialogConstants.CANCEL_LABEL,
052: NonPortableMessages.getString("PREVIOUS_ISSUE"), //$NON-NLS-1$
053: NonPortableMessages.getString("NEXT_ISSUE"), //$NON-NLS-1$
054: NonPortableMessages.getString("APPLY"), //$NON-NLS-1$
055: }, 1);
056: }
057:
058: private NonPortableObjectEvent getNonPortableObjectEvent() {
059: return (NonPortableObjectEvent) getApplicationEvent();
060: }
061:
062: private NonPortableEventContext getNonPortableEventContext() {
063: return getNonPortableObjectEvent().getNonPortableEventContext();
064: }
065:
066: protected String getDialogSettingsSectionName() {
067: return TcPlugin.PLUGIN_ID + ".NON_PORTABLE_DIALOG_SECTION"; //$NON-NLS-1$
068: }
069:
070: protected void createButtonsForButtonBar(Composite parent) {
071: super .createButtonsForButtonBar(parent);
072: fPreviousIssueButton = getButton(1);
073: fNextIssueButton = getButton(2);
074: fApplyButton = getButton(3);
075: fPreviousIssueButton.setEnabled(getPreviousIssue() != null);
076: fNextIssueButton.setEnabled(getNextIssue() != null);
077: fApplyButton.setEnabled(false);
078: }
079:
080: protected void createIssueDescriptionArea(Composite parent) {
081: fIssueDescription = new Text(parent, SWT.MULTI | SWT.WRAP
082: | SWT.V_SCROLL | SWT.BORDER | SWT.READ_ONLY);
083: GridData gridData = new GridData(GridData.FILL_BOTH);
084: gridData.widthHint = SWTUtil.textColumnsToPixels(
085: fIssueDescription, 80);
086: gridData.heightHint = SWTUtil.textRowsToPixels(
087: fIssueDescription, 8);
088: fIssueDescription.setLayoutData(gridData);
089: }
090:
091: protected Control createCustomArea(Composite parent) {
092: Control customArea = super .createCustomArea(parent);
093: fIncludeTypesView = new IncludeTypesPanel(fActionPanel);
094: return customArea;
095: }
096:
097: protected void buttonPressed(int buttonId) {
098: switch (buttonId) {
099: case 0:
100: cancelPressed();
101: break;
102: case 1:
103: gotoPreviousIssue();
104: break;
105: case 2:
106: gotoNextIssue();
107: break;
108: case 3:
109: apply();
110: okPressed();
111: break;
112: }
113: }
114:
115: protected boolean anySelectedActions() {
116: for (int i = 0; i < fIssueTable.getItemCount(); i++) {
117: TableItem tableItem = fIssueTable.getItem(i);
118: TreeItem treeItem = (TreeItem) tableItem.getData();
119: DefaultMutableTreeNode node = (DefaultMutableTreeNode) treeItem
120: .getData();
121:
122: if (node != null) {
123: Object userObject = node.getUserObject();
124:
125: if (userObject instanceof AbstractWorkState) {
126: AbstractWorkState workState = (AbstractWorkState) userObject;
127: if (workState.hasSelectedActions()) {
128: return true;
129: }
130: }
131: }
132: }
133:
134: return false;
135: }
136:
137: private void gotoPreviousIssue() {
138: TreeItem item = getPreviousIssue();
139: if (item != null) {
140: fObjectTree.setSelection(item);
141: handleTreeSelectionChange();
142: }
143: }
144:
145: private TreeItem getPreviousIssue(TreeItem item) {
146: while ((item = getPreviousItem(item)) != null) {
147: DefaultMutableTreeNode node = (DefaultMutableTreeNode) item
148: .getData();
149: Object userObject = node.getUserObject();
150:
151: if (userObject instanceof NonPortableWorkState) {
152: NonPortableWorkState workState = (NonPortableWorkState) userObject;
153: if (testIsIssue(workState)) {
154: return item;
155: }
156: }
157: }
158:
159: return null;
160: }
161:
162: private TreeItem getPreviousIssue() {
163: TreeItem[] selection = fObjectTree.getSelection();
164:
165: if (selection != null && selection.length > 0) {
166: return getPreviousIssue(selection[0]);
167: }
168:
169: return null;
170: }
171:
172: private void gotoNextIssue() {
173: TreeItem item = getNextIssue();
174: if (item != null) {
175: fObjectTree.setSelection(item);
176: handleTreeSelectionChange();
177: }
178: }
179:
180: private TreeItem getNextItem(TreeItem item, boolean includeChildren) {
181: if (item == null) {
182: return null;
183: }
184: if (includeChildren) {
185: TreeItem[] children = item.getItems();
186: if (children != null && children.length > 0) {
187: return children[0];
188: }
189: }
190:
191: TreeItem parent = item.getParentItem();
192: if (parent == null) {
193: return null;
194: }
195: TreeItem[] siblings = parent.getItems();
196: if (siblings != null) {
197: if (siblings.length <= 1) {
198: return getNextItem(parent, false);
199: }
200:
201: for (int i = 0; i < siblings.length; i++) {
202: if (siblings[i] == item && i < (siblings.length - 1)) {
203: return siblings[i + 1];
204: }
205: }
206: }
207: return getNextItem(parent, false);
208: }
209:
210: private TreeItem getPreviousItem(TreeItem item) {
211: TreeItem parent = item.getParentItem();
212: if (parent == null) {
213: return null;
214: }
215: TreeItem[] siblings = parent.getItems();
216: if (siblings.length == 0 || siblings[0] == item) {
217: return parent;
218: }
219: TreeItem previous = siblings[0];
220: for (int i = 1; i < siblings.length; i++) {
221: if (siblings[i] == item) {
222: return rightMostDescendent(previous);
223: }
224: previous = siblings[i];
225: }
226: return null;
227: }
228:
229: private TreeItem rightMostDescendent(TreeItem item) {
230: TreeItem[] children = item.getItems();
231: if (children != null && children.length > 0) {
232: return rightMostDescendent(children[children.length - 1]);
233: }
234: return item;
235: }
236:
237: private TreeItem getNextIssue(TreeItem item) {
238: while ((item = getNextItem(item, true)) != null) {
239: DefaultMutableTreeNode node = (DefaultMutableTreeNode) item
240: .getData();
241: Object userObject = node.getUserObject();
242:
243: if (userObject instanceof NonPortableWorkState) {
244: NonPortableWorkState workState = (NonPortableWorkState) userObject;
245: if (testIsIssue(workState)) {
246: return item;
247: }
248: }
249: }
250:
251: return null;
252: }
253:
254: private TreeItem getNextIssue() {
255: TreeItem[] selection = fObjectTree.getSelection();
256:
257: if (selection != null && selection.length > 0) {
258: return getNextIssue(selection[0]);
259: }
260:
261: return null;
262: }
263:
264: // NOTE: this is copied in ui-configurator/src/com/tc/NonPortableObjectPanel. ConfigHelper needs to be
265: // unified before we can move this to NonPortableWorkState.testIsIssue(ConfigHelper).
266:
267: boolean testIsIssue(NonPortableWorkState workState) {
268: String fieldName = workState.getFieldName();
269: boolean isTransientField = fieldName != null
270: && (fConfigHelper.isTransient(fieldName) || workState
271: .isTransient());
272:
273: if (workState.isNull() || workState.isRepeated()
274: || isTransientField)
275: return false;
276:
277: if (workState.isNeverPortable()
278: || workState.extendsLogicallyManagedType()) {
279: return true;
280: }
281:
282: if (workState.hasRequiredBootTypes()) {
283: java.util.List types = workState.getRequiredBootTypes();
284: for (Iterator iter = types.iterator(); iter.hasNext();) {
285: if (!fConfigHelper.isBootJarClass((String) iter.next()))
286: return true;
287: }
288: }
289:
290: if (workState.hasRequiredIncludeTypes()) {
291: java.util.List types = workState.getRequiredIncludeTypes();
292: for (Iterator iter = types.iterator(); iter.hasNext();) {
293: if (!fConfigHelper.isAdaptable((String) iter.next()))
294: return true;
295: }
296: }
297:
298: if (!workState.isPortable()
299: && workState.isSystemType()
300: && !fConfigHelper.isBootJarClass(workState
301: .getTypeName()))
302: return true;
303:
304: if (workState.getExplaination() != null)
305: return true;
306:
307: return !workState.isPortable()
308: && !fConfigHelper.isAdaptable(workState.getTypeName());
309: }
310:
311: boolean checkAddToIssueList(NonPortableWorkState workState) {
312: if (workState.hasSelectedActions()) {
313: return true;
314: }
315: return testIsIssue(workState);
316: }
317:
318: protected void initIssueList() {
319: TreeItem treeItem = fObjectTree.getItem(0);
320:
321: fIssueTable.setRedraw(false);
322: try {
323: fIssueTable.setItemCount(0);
324: while (treeItem != null) {
325: DefaultMutableTreeNode node = (DefaultMutableTreeNode) treeItem
326: .getData();
327: Object userObject = node.getUserObject();
328:
329: if (userObject instanceof NonPortableWorkState) {
330: NonPortableWorkState workState = (NonPortableWorkState) userObject;
331:
332: if (checkAddToIssueList(workState)) {
333: TableItem tableItem = new TableItem(
334: fIssueTable, SWT.NONE);
335:
336: tableItem.setData(treeItem);
337: tableItem.setImage(workState
338: .hasSelectedActions() ? RESOLVED_ICON
339: : BLANK_ICON);
340: tableItem.setText(workState.shortSummary());
341: }
342: }
343:
344: treeItem = getNextItem(treeItem, true);
345: }
346: } finally {
347: fIssueTable.setRedraw(true);
348: }
349: }
350:
351: void syncTableAndTree() {
352: TreeItem[] selection = fObjectTree.getSelection();
353: TreeItem treeItem = selection[0];
354: int tableCount = fIssueTable.getItemCount();
355: TableItem tableItem;
356:
357: for (int i = 0; i < tableCount; i++) {
358: tableItem = fIssueTable.getItem(i);
359: if (tableItem.getData() == treeItem) {
360: fIssueTable.setSelection(i);
361: return;
362: }
363: }
364:
365: fIssueTable.deselectAll();
366: }
367:
368: protected void handleTreeSelectionChange() {
369: TreeItem[] selection = fObjectTree.getSelection();
370: DefaultMutableTreeNode node = (DefaultMutableTreeNode) selection[0]
371: .getData();
372: Object userObject = node.getUserObject();
373:
374: syncTableAndTree();
375: if (userObject instanceof NonPortableWorkState) {
376: setWorkState((NonPortableWorkState) userObject);
377: } else {
378: hideResolutionsPanel();
379: }
380: updateButtons();
381: }
382:
383: void setWorkState(AbstractWorkState workState) {
384: fActionTreeViewer.getTree().setRedraw(false);
385: try {
386: showResolutionsPanel();
387: hideActionPanel();
388:
389: fSummaryLabel.setText(workState.summary());
390: fSummaryLabel.setImage(imageFor(workState));
391: fIssueDescription.setText(workState
392: .descriptionFor(getNonPortableEventContext()));
393: fActionTreeViewer.setInput(workState);
394:
395: AbstractResolutionAction[] actions = getActions(workState);
396: if (actions != null && actions.length > 0) {
397: boolean showComponent = true;
398:
399: for (int i = 0; i < actions.length; i++) {
400: AbstractResolutionAction action = actions[i];
401:
402: if (action.isEnabled()) {
403: boolean isSelected = action.isSelected();
404:
405: fActionTreeViewer
406: .setChecked(action, isSelected);
407: if (isSelected) {
408: if (showComponent) {
409: fActionTreeViewer
410: .setSelection(new StructuredSelection(
411: action));
412: action.showControl(this );
413: showComponent = false;
414: }
415: }
416: }
417: }
418: fActionTreeViewer.expandAll();
419: }
420: setNoAction(!workState.hasSelectedActions());
421: if (!haveAnyActions()) {
422: hideResolutionsPanel();
423: }
424: } finally {
425: fActionTreeViewer.getTree().setRedraw(true);
426: }
427: }
428:
429: private boolean requiresPortabilityAction(
430: NonPortableWorkState workState) {
431: if (workState.isTransient()
432: || workState.extendsLogicallyManagedType())
433: return false;
434: if (workState.hasRequiredBootTypes()) {
435: java.util.List types = workState.getRequiredBootTypes();
436: for (Iterator iter = types.iterator(); iter.hasNext();) {
437: if (!fConfigHelper.isBootJarClass((String) iter.next()))
438: return true;
439: }
440: }
441: if (workState.hasNonPortableBaseTypes()) {
442: java.util.List types = workState.getNonPortableBaseTypes();
443: for (Iterator iter = types.iterator(); iter.hasNext();) {
444: if (!fConfigHelper.isAdaptable((String) iter.next()))
445: return true;
446: }
447: }
448: return !fConfigHelper.isAdaptable(workState.getTypeName());
449: }
450:
451: protected AbstractResolutionAction[] createActions(
452: AbstractWorkState workState) {
453: ArrayList list = new ArrayList();
454:
455: if (workState instanceof NonPortableWorkState) {
456: NonPortableWorkState nonPortableWorkState = (NonPortableWorkState) workState;
457: String fieldName = nonPortableWorkState.getFieldName();
458:
459: if (nonPortableWorkState.isNeverPortable()
460: || nonPortableWorkState.isPortable()) {
461: if (fieldName != null
462: && !nonPortableWorkState.isTransient()
463: && !fConfigHelper.isTransient(fieldName)) {
464: list.add(new MakeTransientAction(
465: nonPortableWorkState));
466: }
467: } else if (!nonPortableWorkState.isPortable()) {
468: if (requiresPortabilityAction(nonPortableWorkState)) {
469: list.add(new MakePortableAction(
470: nonPortableWorkState));
471: }
472: if (fieldName != null
473: && !nonPortableWorkState.isTransient()
474: && !fConfigHelper.isTransient(fieldName)) {
475: list.add(new MakeTransientAction(
476: nonPortableWorkState));
477: }
478: }
479: }
480:
481: return (AbstractResolutionAction[]) list
482: .toArray(new AbstractResolutionAction[0]);
483: }
484:
485: protected void updateButtons() {
486: if (fApplyButton == null)
487: return;
488: fApplyButton.setEnabled(anySelectedActions());
489: if (fPreviousIssueButton != null) {
490: fPreviousIssueButton.setEnabled(getPreviousIssue() != null);
491: fNextIssueButton.setEnabled(getNextIssue() != null);
492: }
493: }
494:
495: class MakeTransientAction extends NonPortableResolutionAction {
496: MakeTransientAction(NonPortableWorkState workState) {
497: super (workState);
498: }
499:
500: public void showControl(Object parentControl) {
501: String fieldName = fWorkState.getFieldName();
502: String declaringType = fieldName.substring(0, fieldName
503: .lastIndexOf('.'));
504: Include include = fConfigHelper
505: .includeRuleFor(declaringType);
506:
507: if (include != null) {
508: fActionStackLayout.topControl = fIncludeRuleView;
509: fIncludeRuleView.setInclude(include);
510: fActionPanel.layout();
511: fActionPanel.redraw();
512: }
513: }
514:
515: public String getText() {
516: return NonPortableMessages.getString("DO_NOT_SHARE"); //$NON-NLS-1$
517: }
518:
519: public void setSelected(boolean selected) {
520: super .setSelected(selected);
521:
522: int index = fIssueTable.getSelectionIndex();
523: TreeItem treeItem = fObjectTree.getSelection()[0];
524:
525: fIssueTable.setRedraw(false);
526: fObjectTree.setRedraw(false);
527: try {
528: if (selected) {
529: fConfigHelper.ensureTransient(fWorkState
530: .getFieldName(), NULL_SIGNALLER);
531: treeItem.removeAll();
532: } else {
533: fConfigHelper.ensureNotTransient(fWorkState
534: .getFieldName(), NULL_SIGNALLER);
535:
536: DefaultMutableTreeNode node = (DefaultMutableTreeNode) treeItem
537: .getData();
538: for (int i = 0; i < node.getChildCount(); i++) {
539: TreeItem childItem = new TreeItem(treeItem,
540: SWT.NONE);
541: DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node
542: .getChildAt(i);
543: initTreeItem(childItem, childNode);
544: }
545: }
546:
547: initIssueList();
548: fObjectTree.setSelection(treeItem);
549: fIssueTable.setSelection(index);
550: } finally {
551: fIssueTable.setRedraw(true);
552: fObjectTree.setRedraw(true);
553: }
554: }
555: }
556:
557: class MakePortableAction extends NonPortableResolutionAction {
558: MakePortableAction(NonPortableWorkState workState) {
559: super (workState);
560: }
561:
562: public void showControl(Object parentControl) {
563: fActionStackLayout.topControl = fIncludeTypesView;
564: fIncludeTypesView.setIncludeTypes(fWorkState
565: .getRequiredIncludeTypes());
566: fIncludeTypesView.setBootTypes(fWorkState
567: .getRequiredBootTypes());
568: fActionPanel.layout();
569: fActionPanel.redraw();
570: }
571:
572: public String getText() {
573: return NonPortableMessages.getString("MAKE_PORTABLE"); //$NON-NLS-1$
574: }
575:
576: public void setSelected(boolean selected) {
577: super .setSelected(selected);
578:
579: if (fWorkState.hasRequiredBootTypes()) {
580: java.util.List types = fWorkState
581: .getRequiredBootTypes();
582: if (selected) {
583: for (Iterator iter = types.iterator(); iter
584: .hasNext();) {
585: fConfigHelper.ensureBootJarClass((String) iter
586: .next(), NULL_SIGNALLER);
587: }
588: } else {
589: for (Iterator iter = types.iterator(); iter
590: .hasNext();) {
591: fConfigHelper.ensureNotBootJarClass(
592: (String) iter.next(), NULL_SIGNALLER);
593: }
594: }
595: }
596:
597: if (fWorkState.hasRequiredIncludeTypes()) {
598: java.util.List types = fWorkState
599: .getRequiredIncludeTypes();
600: if (selected) {
601: for (Iterator iter = types.iterator(); iter
602: .hasNext();) {
603: fConfigHelper.ensureAdaptable((String) iter
604: .next(), NULL_SIGNALLER);
605: }
606: } else {
607: for (Iterator iter = types.iterator(); iter
608: .hasNext();) {
609: fConfigHelper.ensureNotAdaptable((String) iter
610: .next(), NULL_SIGNALLER);
611: }
612: }
613: }
614:
615: int index = fIssueTable.getSelectionIndex();
616:
617: fIssueTable.setRedraw(false);
618: try {
619: initIssueList();
620: fIssueTable.setSelection(index);
621: } finally {
622: fIssueTable.setRedraw(true);
623: }
624: }
625: }
626:
627: class IncludeTypesPanel extends Composite {
628: List fIncludeTypesList;
629: List fBootTypesList;
630:
631: IncludeTypesPanel(Composite parent) {
632: super (parent, SWT.NONE);
633: setLayout(new GridLayout());
634: Label label = new Label(this , SWT.NONE);
635: label.setText(NonPortableMessages
636: .getString("TYPES_TO_INCLUDE")); //$NON-NLS-1$
637: label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
638: fIncludeTypesList = new List(this , SWT.BORDER
639: | SWT.V_SCROLL);
640: fIncludeTypesList.setLayoutData(new GridData(
641: GridData.FILL_BOTH));
642:
643: label = new Label(this , SWT.NONE);
644: label.setText(NonPortableMessages
645: .getString("TYPES_TO_ADD_TO_BOOTJAR")); //$NON-NLS-1$
646: label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
647: fBootTypesList = new List(this , SWT.BORDER | SWT.V_SCROLL);
648: fBootTypesList.setLayoutData(new GridData(
649: GridData.FILL_BOTH));
650: }
651:
652: void setIncludeTypes(java.util.List types) {
653: fIncludeTypesList.setRedraw(false);
654: try {
655: fIncludeTypesList.setItems(new String[0]);
656: if (types != null) {
657: ConfigurationHelper configHelper = TcPlugin
658: .getDefault().getConfigurationHelper(
659: fJavaProject.getProject());
660: for (Iterator iter = types.iterator(); iter
661: .hasNext();) {
662: String type = (String) iter.next();
663: if (!configHelper.isAdaptable(type)) {
664: fIncludeTypesList.add(type);
665: }
666: }
667: }
668: } finally {
669: fIncludeTypesList.setRedraw(true);
670: }
671: }
672:
673: void setBootTypes(java.util.List types) {
674: fBootTypesList.setRedraw(false);
675: try {
676: fBootTypesList.setItems(new String[0]);
677: if (types != null) {
678: ConfigurationHelper configHelper = TcPlugin
679: .getDefault().getConfigurationHelper(
680: fJavaProject.getProject());
681:
682: for (Iterator iter = types.iterator(); iter
683: .hasNext();) {
684: String type = (String) iter.next();
685: if (!configHelper.isBootJarClass(type)) {
686: fBootTypesList.add(type);
687: }
688: }
689: }
690: } finally {
691: fBootTypesList.setRedraw(true);
692: }
693: }
694: }
695: }
|