001: // This file is part of KeY - Integrated Deductive Software Design
002: // Copyright (C) 2001-2007 Universitaet Karlsruhe, Germany
003: // Universitaet Koblenz-Landau, Germany
004: // Chalmers University of Technology, Sweden
005: //
006: // The KeY system is protected by the GNU General Public License.
007: // See LICENSE.TXT for details.
008: //
009: //
010:
011: package de.uka.ilkd.key.gui;
012:
013: import java.awt.*;
014: import java.awt.datatransfer.DataFlavor;
015: import java.awt.datatransfer.Transferable;
016: import java.awt.datatransfer.UnsupportedFlavorException;
017: import java.awt.dnd.*;
018: import java.awt.event.ActionEvent;
019: import java.awt.event.ActionListener;
020: import java.io.BufferedReader;
021: import java.io.BufferedWriter;
022: import java.io.File;
023: import java.io.FileReader;
024: import java.io.FileWriter;
025: import java.io.IOException;
026: import java.util.HashMap;
027: import java.util.LinkedList;
028: import java.util.ListIterator;
029:
030: import javax.swing.*;
031: import javax.swing.border.EmptyBorder;
032: import javax.swing.border.TitledBorder;
033: import javax.swing.event.ChangeEvent;
034: import javax.swing.table.DefaultTableCellRenderer;
035: import javax.swing.table.TableCellRenderer;
036:
037: import de.uka.ilkd.key.gui.configuration.PathConfig;
038: import de.uka.ilkd.key.logic.NamespaceSet;
039: import de.uka.ilkd.key.logic.Sequent;
040: import de.uka.ilkd.key.proof.*;
041: import de.uka.ilkd.key.rule.Taclet;
042: import de.uka.ilkd.key.rule.TacletApp;
043: import de.uka.ilkd.key.util.Debug;
044: import de.uka.ilkd.key.util.ExceptionHandlerException;
045:
046: public class TacletMatchCompletionDialog extends ApplyTacletDialog {
047:
048: // the table showing the instantiations
049: private DataTable[] dataTable;
050:
051: // the current chosen model
052: private int current = 0;
053:
054: // the gui component used to display the different instantiation
055: // alternatives
056: private JTabbedPane alternatives;
057:
058: /** the goal the application of the rule has to be performed */
059: private Goal goal;
060:
061: private JScrollPane tablePane;
062:
063: public TacletMatchCompletionDialog(ApplyTacletDialogModel[] model,
064: Goal goal, KeYMediator mediator) {
065: super (model, mediator);
066: this .goal = goal;
067: this .current = 0;
068: dataTable = new DataTable[model.length];
069:
070: for (int i = 0; i < model.length; i++) {
071: model[i].prepareUnmatchedInstantiation();
072: }
073:
074: setStatus();
075:
076: // layout dialog
077: layoutDialog();
078: pack();
079: // set at the middle of the main frame
080: //setLocation(dialogPosition());
081: // setSize(800,(int)getSize().getHeight());
082: // setLocation(50,50);
083: setVisible(true);
084: }
085:
086: public TacletMatchCompletionDialog(ApplyTacletDialogModel model,
087: Goal goal, KeYMediator mediator) {
088: this (new ApplyTacletDialogModel[] { model }, goal, mediator);
089: }
090:
091: public static void completeAndApplyApp(TacletApp app, Goal goal,
092: KeYMediator medi) {
093: LinkedList l = new LinkedList();
094: l.add(app);
095: completeAndApplyApp(l, goal, medi);
096: }
097:
098: public static void completeAndApplyApp(java.util.List l, Goal goal,
099: KeYMediator medi) {
100: ApplyTacletDialogModel[] origInstModels = new ApplyTacletDialogModel[l
101: .size()];
102: LinkedList recentInstModels = new LinkedList();
103: ListIterator tacletAppIt = l.listIterator();
104:
105: for (int i = 0; i < l.size(); i++) {
106: TacletApp tA = (TacletApp) tacletAppIt.next();
107: origInstModels[i] = createModel(tA, goal, medi);
108:
109: if (InstantiationFileHandler.hasInstantiationListsFor(tA
110: .taclet())) {
111: ListIterator instListIt = InstantiationFileHandler
112: .getInstantiationListsFor(tA.taclet())
113: .listIterator();
114:
115: while (instListIt.hasNext()) {
116: java.util.List instantiations = (java.util.List) instListIt
117: .next();
118: int start = tA.instantiations().size();
119:
120: if (origInstModels[i].tableModel().getRowCount()
121: - start == instantiations.size()) {
122: ApplyTacletDialogModel m = createModel(tA,
123: goal, medi);
124: recentInstModels.add(m);
125: ListIterator instIt = instantiations
126: .listIterator();
127:
128: while (instIt.hasNext()) {
129: m.tableModel().setValueAt(instIt.next(),
130: start++, 1);
131: }
132:
133: }
134:
135: }
136:
137: }
138:
139: }
140:
141: ApplyTacletDialogModel[] models = new ApplyTacletDialogModel[origInstModels.length
142: + recentInstModels.size()];
143: int i;
144:
145: for (i = 0; i < origInstModels.length; i++) {
146: models[i] = origInstModels[i];
147: }
148:
149: ListIterator recentInstModelIt = recentInstModels
150: .listIterator();
151:
152: while (recentInstModelIt.hasNext()) {
153: models[i++] = (ApplyTacletDialogModel) recentInstModelIt
154: .next();
155: }
156:
157: new TacletMatchCompletionDialog(models, goal, medi);
158: }
159:
160: public static ApplyTacletDialogModel createModel(TacletApp app,
161: Goal goal, KeYMediator medi) {
162: return new ApplyTacletDialogModel(app, goal.sequent(), medi
163: .getServices(), medi.getUserConstraint()
164: .getConstraint(), new NamespaceSet(medi.var_ns(), medi
165: .func_ns(), medi.sort_ns(), medi.heur_ns(), medi
166: .choice_ns(), goal.createGlobalProgVarNamespace()),
167: medi.getNotationInfo().getAbbrevMap(), goal);
168: }
169:
170: public void setStatus() {
171: setStatus(model[current].getStatusString());
172: }
173:
174: private void layoutDialog() {
175:
176: JPanel tacletPanel = createTacletPanel();
177: JPanel downPanel = new JPanel();
178: downPanel.setLayout(new BoxLayout(downPanel, BoxLayout.Y_AXIS));
179: downPanel.add(createInfoPanel());
180: downPanel.add(createStatusPanel());
181: downPanel.add(createButtonPanel(new ButtonListener()));
182:
183: JSplitPane splitPaneBot = new JSplitPane(
184: JSplitPane.VERTICAL_SPLIT, tacletPanel, downPanel) {
185: public void setUI(javax.swing.plaf.SplitPaneUI ui) {
186: try {
187: super .setUI(ui);
188: } catch (NullPointerException e) {
189: Debug
190: .out("Exception thrown by class TacletMatchCompletionDialog at setUI");
191: }
192: }
193: }; // work around bug in
194: // com.togethersoft.util.ui.plaf.metal.OIMetalSplitPaneUI
195: splitPaneBot.setResizeWeight(1);
196:
197: JSplitPane splitPane = new JSplitPane(
198: JSplitPane.VERTICAL_SPLIT, createTacletDisplay(),
199: splitPaneBot) {
200: public void setUI(javax.swing.plaf.SplitPaneUI ui) {
201: try {
202: super .setUI(ui);
203: } catch (NullPointerException e) {
204: Debug
205: .out("Exception thrown by class TacletMatchCompletionDialog at setUI");
206: }
207: }
208: }; // work around bug in
209: // com.togethersoft.util.ui.plaf.metal.OIMetalSplitPaneUI
210:
211: getContentPane().add(splitPane);
212: // add button listener
213: updateDataModel();
214: }
215:
216: private JPanel createTacletPanel() {
217: // the tabbedPane contains different possible instantiations of
218: // the applied Taclet
219: JPanel panel = new JPanel(new GridLayout(1, 1));
220: panel.setBorder(new TitledBorder("Variable Instantiations"));
221:
222: alternatives = new JTabbedPane();
223: // some layout stuff
224: EmptyBorder indents = new EmptyBorder(5, 5, 5, 5);
225:
226: for (int i = 0; i < model.length; i++) {
227: JPanel tabContent = new JPanel();
228: tabContent.setLayout(new BoxLayout(tabContent,
229: BoxLayout.Y_AXIS));
230:
231: JPanel instPanel = createInstantiationDisplay(i);
232: instPanel.setBorder(indents);
233: tabContent.add(instPanel);
234:
235: if (model[i].application().taclet().ifSequent() != Sequent.EMPTY_SEQUENT) {
236:
237: TacletIfSelectionDialog ifSelection = new TacletIfSelectionDialog(
238: model[i], this );
239: dataTable[i].setIfSelectionPanel(ifSelection);
240: tabContent.add(ifSelection);
241: }
242: alternatives.addTab("Alt " + i, null, tabContent,
243: "Instantiations Alternatives");
244: }
245:
246: panel.add(alternatives);
247: return panel;
248: }
249:
250: /** returns the current selected model
251: * @return the current selected model
252: */
253: protected int current() {
254: return alternatives.getSelectedIndex();
255: }
256:
257: protected void pushAllInputToModel() {
258: pushAllInputToModel(current());
259: }
260:
261: protected void pushAllInputToModel(int i) {
262: if (dataTable[i].hasIfSelectionPanel()) {
263: dataTable[i].getIfSelectionPanel().pushAllInputToModel();
264: }
265: if (dataTable[i].isEditing()) {
266: dataTable[i].getCellEditor().stopCellEditing();
267: }
268: }
269:
270: private JPanel createInstantiationDisplay(int i) {
271: JPanel panel = new JPanel(new BorderLayout());
272: // show instantiation
273: dataTable[i] = new DataTable(this , i);
274: tablePane = new JScrollPane(dataTable[i]);
275: dataTable[i].setRowHeight(48);
276: adaptSizes(dataTable[i]);
277: panel.add(tablePane, BorderLayout.CENTER);
278: return panel;
279: }
280:
281: private void adaptSizes(DataTable dt) {
282: int tableSize_x = dt.getTotalColumnWidth();
283: int visible_rows = dt.getRowCount() > 8 ? 8 : dt.getRowCount();
284: int tableSize_y = (visible_rows + 1) * 48;
285: Dimension tableDim = new Dimension(tableSize_x, tableSize_y);
286: tablePane.setMinimumSize(tableDim);
287: tablePane.setPreferredSize(tableDim);
288: tablePane.setMaximumSize(tableDim);
289: validateTree();
290: }
291:
292: private void setColumnName(int model, int col, String name) {
293: dataTable[model].getColumn(dataTable[model].getColumnName(col))
294: .setHeaderValue(name);
295: }
296:
297: /** shows next instantiation suggestion */
298: private void updateDataModel() {
299: for (int i = 0; i < model.length; i++) {
300: if (model[i] != null) {
301: dataTable[i].setModel(model[i].tableModel());
302: //sets column names
303: setColumnName(i, 0, "Variable");
304: setColumnName(i, 1, "Instantiation");
305: }
306: }
307: }
308:
309: class ButtonListener implements ActionListener {
310:
311: public ButtonListener() {
312: }
313:
314: private void errorPositionKnown(String errorMessage, int row,
315: int col, boolean inIfSequent) {
316:
317: if (inIfSequent) {
318: dataTable[current()].getIfSelectionPanel()
319: .requestFocusAt(row, col);
320: } else {
321: // select table cell where the error occured
322: //ALL THIS DOES NOT REALLY WORK!!! BUT WHY???
323: final int tableCol = 1;
324: dataTable[current()].editCellAt(row, tableCol);
325: dataTable[current()].setEditingRow(row);
326: dataTable[current()].setEditingColumn(tableCol);
327:
328: PositionSettable ed = (PositionSettable) dataTable[current()]
329: .getCellEditor(row, tableCol);
330:
331: try {
332:
333: ed.setCaretPosition(col - 1);
334:
335: } catch (IllegalArgumentException iae) {
336: System.out
337: .println("tacletmatchcompletiondialog:: something is "
338: + "wrong with the caret position calculation.");
339:
340: }
341: ed.setVisible(true);
342: ed.validate();
343: ed.requestFocus();
344: }
345: }
346:
347: public void actionPerformed(ActionEvent e) {
348: if (e.getSource() == cancelButton) {
349: closeDialog();
350: } else if (e.getSource() == applyButton) {
351: try {
352: try {
353: pushAllInputToModel();
354: TacletApp app = model[current()]
355: .createTacletApp();
356: if (app == null) {
357: JOptionPane.showMessageDialog(
358: TacletMatchCompletionDialog.this ,
359: "Could not apply rule",
360: "Rule Application Failure",
361: JOptionPane.ERROR_MESSAGE);
362: return;
363: }
364: mediator().applyInteractive(app, goal);
365: } catch (ExceptionHandlerException ex) {
366: throw ex;
367: } catch (Exception ex) {
368: (mediator().getExceptionHandler())
369: .reportException(ex);
370: }
371: } catch (ExceptionHandlerException ex) {
372: Exception exc = (Exception) ((mediator()
373: .getExceptionHandler()).getExceptions())
374: .get(0);
375: if (exc instanceof SVInstantiationExceptionWithPosition) {
376: errorPositionKnown(
377: ((SVInstantiationExceptionWithPosition) exc)
378: .getMessage(),
379: ((SVInstantiationExceptionWithPosition) exc)
380: .getRow(),
381: 1,
382: ((SVInstantiationExceptionWithPosition) exc)
383: .inIfSequent());
384: }
385: new ExceptionDialog(
386: TacletMatchCompletionDialog.this ,
387: mediator().getExceptionHandler()
388: .getExceptions());
389: mediator().getExceptionHandler().clear();
390: return;
391: }
392: InstantiationFileHandler.saveListFor(model[current()]);
393: closeDialog();
394: }
395: }
396:
397: private void closeDialog() {
398: closeDlg();
399: setVisible(false);
400: dispose();
401: }
402:
403: }
404:
405: private static class DataTable extends JTable implements
406: ModelChangeListener {
407:
408: JTextArea inputArea = new JTextArea("Nothing", 3, 16);
409: final InputEditor iEditor = new InputEditor(inputArea);
410: final InputCellRenderer iRenderer = new InputCellRenderer();
411:
412: /** the number of the model the data table belongs to */
413: private int modelNr;
414: /** the enclosing dialog */
415: private TacletMatchCompletionDialog owner;
416: /** the TacletIfSelectionPanel that shows the different possible
417: * instantiations of the if-sequent or a manual entered
418: * instantiation. The value is null if and only if
419: * the taclet has no if-sequent
420: */
421: private TacletIfSelectionDialog ifSelectionPanel;
422:
423: private DataTable(TacletMatchCompletionDialog owner, int modelNr) {
424:
425: super (owner.model[modelNr].tableModel());
426: this .modelNr = modelNr;
427: this .owner = owner;
428: owner.model[modelNr].addModelChangeListener(this );
429: setUpEditor();
430:
431: // And now the Drag'n'drop stuff ...
432: DropTarget aDropTarget = new DropTarget(this ,
433: new DropTargetListener() {
434: public void dragEnter(DropTargetDragEvent event) {
435: }
436:
437: public void dragExit(DropTargetEvent event) {
438: }
439:
440: public void dragOver(DropTargetDragEvent event) {
441: }
442:
443: public void drop(DropTargetDropEvent event) {
444: String droppedString;
445:
446: Point dropLocation = event.getLocation();
447: int row = DataTable.this
448: .rowAtPoint(dropLocation);
449: int column = DataTable.this
450: .columnAtPoint(dropLocation);
451:
452: if ((row != -1) && (column == 1)) {
453: // The point lies within the table and within the instantiation
454: // column ...
455:
456: try {
457: Transferable transferable = event
458: .getTransferable();
459:
460: // we accept only Strings
461: if (transferable
462: .isDataFlavorSupported(DataFlavor.stringFlavor)) {
463:
464: event
465: .acceptDrop(DnDConstants.ACTION_MOVE);
466: droppedString = (String) transferable
467: .getTransferData(DataFlavor.stringFlavor);
468: // now set the new entry in the table ...
469:
470: if (droppedString != null) {
471: String s = droppedString;
472:
473: DataTable.this .setValueAt(
474: s, row, column);
475: DataTable.this .repaint();
476: }
477: event.getDropTargetContext()
478: .dropComplete(true);
479: } else {
480: event.rejectDrop();
481: }
482: } catch (IOException exception) {
483: exception.printStackTrace();
484: event.rejectDrop();
485: } catch (UnsupportedFlavorException ufException) {
486: ufException.printStackTrace();
487: event.rejectDrop();
488: }
489: } else {
490: event.rejectDrop();
491: }
492: }
493:
494: public void dropActionChanged(
495: DropTargetDragEvent dtde) {
496: }
497: });
498:
499: this .setDropTarget(aDropTarget);
500:
501: } // end constructor
502:
503: /** Provide sane single-click editing in table */
504: public javax.swing.table.TableCellEditor getCellEditor(int row,
505: int col) {
506: return iEditor;
507: }
508:
509: public TableCellRenderer getCellRenderer(int row, int col) {
510: return iRenderer;
511: }
512:
513: public Object getValueAt(int x, int y) {
514: Object value = super .getValueAt(x, y);
515: if (value == null)
516: return "";
517: return value;
518: }
519:
520: private void setUpEditor() {
521: setDefaultEditor(String.class, iEditor);
522:
523: }
524:
525: /** sets the if selection panel */
526: private void setIfSelectionPanel(
527: TacletIfSelectionDialog ifSelectionPanel) {
528: this .ifSelectionPanel = ifSelectionPanel;
529: }
530:
531: /** returns the if selection panel
532: * @return the if selection panel, null if not available
533: */
534: private TacletIfSelectionDialog getIfSelectionPanel() {
535: return ifSelectionPanel;
536: }
537:
538: /** returns true the model has a non empty if sequent and
539: * the ifSelectionPanel has been created and set. So that the
540: * method getIfSelectionPanel will not return null
541: * @return true iff getIfSelectionPanel does not return null
542: */
543: private boolean hasIfSelectionPanel() {
544: return getIfSelectionPanel() != null;
545: }
546:
547: public void modelChanged(ModelEvent me) {
548: if (me.getSource() instanceof ApplyTacletDialogModel) {
549: setModel(((ApplyTacletDialogModel) me.getSource())
550: .tableModel());
551: repaint();
552: }
553: }
554:
555: public int getTotalColumnWidth() {
556: return getColumnModel().getTotalColumnWidth();
557: }
558:
559: // public int getRowHeight(int row) {
560: // if (rowHeights==null) return 48;
561: // return rowHeights[row]*16;
562: // }
563:
564: public void editingStopped(ChangeEvent e) {
565: if (modelNr == owner.current()) {
566: super .editingStopped(e);
567: owner.pushAllInputToModel(modelNr);
568: if (owner.checkAfterEachInput()) {
569: owner.setStatus(owner.model[modelNr]
570: .getStatusString());
571: }
572: }
573: }
574:
575: class InputEditor extends DefaultCellEditor implements
576: PositionSettable {
577:
578: JPanel editPanel;
579: JTextArea textarea;
580:
581: public InputEditor(JTextArea ta) {
582: super (new JCheckBox()); //Unfortunately, the constructor
583: //expects a check box, combo box,
584: //or text field.
585: textarea = ta;
586: editPanel = new JPanel();
587: editPanel.setLayout(new BoxLayout(editPanel,
588: BoxLayout.X_AXIS));
589: editPanel.add(new JScrollPane(textarea,
590: JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
591: JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
592: JPanel buttonPanel = new JPanel(new BorderLayout());
593: Insets zeroIn = new Insets(0, 0, 0, 0);
594: JButton less = new JButton("-");
595: less.setMargin(zeroIn);
596: JButton more = new JButton("+");
597: more.setMargin(zeroIn);
598: Dimension small = new Dimension(20, 9999);
599: buttonPanel.setMaximumSize(small);
600: buttonPanel.setPreferredSize(small);
601: Dimension smallSq = new Dimension(20, 20);
602: less.setMaximumSize(smallSq);
603: less.setMinimumSize(smallSq);
604: less.setPreferredSize(smallSq);
605: more.setMaximumSize(smallSq);
606: more.setMinimumSize(smallSq);
607: more.setPreferredSize(smallSq);
608: less.addActionListener(new ActionListener() {
609: public void actionPerformed(ActionEvent e) {
610: if (textarea.getRows() > 3) {
611: textarea.setRows(textarea.getRows() - 1);
612: setRowHeight(getSelectedRow(),
613: getRowHeight(getSelectedRow()) - 16);
614: setValueAt(textarea.getText(),
615: getSelectedRow(),
616: getSelectedColumn());
617: }
618: }
619: });
620: more.addActionListener(new ActionListener() {
621: public void actionPerformed(ActionEvent e) {
622: textarea.setRows(textarea.getRows() + 1);
623: setRowHeight(getSelectedRow(),
624: getRowHeight(getSelectedRow()) + 16);
625: setValueAt(textarea.getText(),
626: getSelectedRow(), getSelectedColumn());
627: }
628: });
629: buttonPanel.add(less, BorderLayout.NORTH);
630: buttonPanel.add(more, BorderLayout.SOUTH);
631: editPanel.add(buttonPanel);
632: editorComponent = editPanel;
633: setClickCountToStart(1);
634: DropTarget aDropTarget = new DropTarget(ta,
635: new DropTargetListener() {
636: public void dragEnter(
637: DropTargetDragEvent event) {
638: }
639:
640: public void dragExit(DropTargetEvent event) {
641: }
642:
643: public void dragOver(
644: DropTargetDragEvent event) {
645: }
646:
647: public void drop(DropTargetDropEvent event) {
648: Transferable transferable = event
649: .getTransferable();
650: if (transferable
651: .isDataFlavorSupported(DataFlavor.stringFlavor)) {
652: event
653: .acceptDrop(DnDConstants.ACTION_MOVE);
654: try {
655: String droppedString = (String) transferable
656: .getTransferData(DataFlavor.stringFlavor);
657: int pos = textarea
658: .viewToModel(event
659: .getLocation());
660: textarea.insert(droppedString,
661: pos);
662: event.getDropTargetContext()
663: .dropComplete(true);
664: } catch (UnsupportedFlavorException e) {
665: e.printStackTrace();
666: event.rejectDrop();
667: } catch (java.io.IOException e) {
668: e.printStackTrace();
669: event.rejectDrop();
670: }
671: } else {
672: event.rejectDrop();
673: }
674:
675: }
676:
677: public void dropActionChanged(
678: DropTargetDragEvent dtde) {
679: }
680: });
681: ta.setDropTarget(aDropTarget);
682: }
683:
684: protected void fireEditingStopped() {
685: super .fireEditingStopped();
686: }
687:
688: public Object getCellEditorValue() {
689: return textarea.getText();
690: }
691:
692: public void setCaretPosition(int i) {
693: textarea.setCaretPosition(i);
694: }
695:
696: public void setVisible(boolean b) {
697: textarea.setVisible(b);
698: }
699:
700: public void validate() {
701: textarea.validate();
702: }
703:
704: public void requestFocus() {
705: textarea.requestFocus();
706: }
707:
708: public Component getTableCellEditorComponent(JTable table,
709: Object value, boolean isSelected, int row,
710: int column) {
711: if (value == null)
712: value = "";
713: textarea.setText(value.toString());
714: textarea.setRows(getRowHeight(row) / 16);
715: return editorComponent;
716: }
717:
718: }
719:
720: class InputCellRenderer extends DefaultTableCellRenderer {
721:
722: JTextArea ta = new JTextArea("nothing");
723:
724: public Component getTableCellRendererComponent(
725: JTable table, Object obj, boolean isSelected,
726: boolean hasFocus, int row, int column) {
727: if (obj == null)
728: obj = "";
729: ta.setRows(getRowHeight(row) / 16);
730: ta.setText(obj.toString());
731: if (table.isCellEditable(row, 1)) {
732: // ta.setBackground(Color.yellow.brighter());
733: ta.setForeground(Color.black);
734: } else {
735: ta.setBackground(Color.white);
736: ta.setForeground(Color.gray);
737: }
738: return ta;
739: }
740: }
741: }
742:
743: interface PositionSettable {
744: void setCaretPosition(int i);
745:
746: void setVisible(boolean b);
747:
748: void validate();
749:
750: void requestFocus();
751: }
752:
753: private static class InstantiationFileHandler {
754: private static final String INSTANTIATION_DIR = PathConfig.KEY_CONFIG_DIR
755: + File.separator + "instantiations";
756:
757: private static final String SEPARATOR1 = "<<<<<<";
758:
759: private static final String SEPARATOR2 = ">>>>>>";
760:
761: private static final String LINE_END = System
762: .getProperty("line.separator");
763:
764: private static final int SAVE_COUNT = 5;
765:
766: private static HashMap hm;
767:
768: private static boolean hasInstantiationListsFor(Taclet taclet) {
769: if (hm == null) {
770: createHashMap();
771: }
772: return hm.containsKey(taclet.name().toString());
773: }
774:
775: private static java.util.List getInstantiationListsFor(
776: Taclet taclet) {
777: if (hasInstantiationListsFor(taclet)) {
778: if (hm.get(taclet.name().toString()) == null) {
779: createListFor(taclet);
780: }
781: return (java.util.List) hm
782: .get(taclet.name().toString());
783: }
784: return null;
785: }
786:
787: private static void createHashMap() {
788: File dir = new File(INSTANTIATION_DIR);
789: if (!dir.exists()) {
790: dir.mkdirs();
791: }
792: String[] instFiles = dir.list();
793: if (instFiles == null) {
794: hm = new HashMap(0);
795: } else {
796: // Avoid resizing of HashMap
797: hm = new HashMap(instFiles.length + 1, 1);
798: for (int i = 0; i < instFiles.length; i++) {
799: hm.put(instFiles[i], null);
800: }
801: }
802: }
803:
804: private static void createListFor(Taclet taclet) {
805: java.util.List instList = new LinkedList();
806: java.util.List instantiations = new LinkedList();
807: try {
808: BufferedReader br = new BufferedReader(new FileReader(
809: INSTANTIATION_DIR + File.separator
810: + taclet.name().toString()));
811: String line = br.readLine();
812: StringBuffer sb = new StringBuffer();
813: while (line != null) {
814: if (line.equals(SEPARATOR1)) {
815: if (sb.length() > 0) {
816: instantiations.add(sb.toString());
817: }
818: sb = new StringBuffer();
819: if (instantiations.size() > 0) {
820: instList.add(instantiations);
821: }
822: instantiations = new LinkedList();
823: } else if (line.equals(SEPARATOR2)) {
824: if (sb.length() > 0) {
825: instantiations.add(sb.toString());
826: }
827: sb = new StringBuffer();
828: } else {
829: if (sb.length() > 0) {
830: sb.append(LINE_END);
831: }
832: sb.append(line);
833: }
834: line = br.readLine();
835: }
836: if (sb.length() > 0) {
837: instantiations.add(sb.toString());
838: }
839: br.close();
840: } catch (IOException e) {
841: }
842: if (instantiations.size() > 0) {
843: instList.add(instantiations);
844: }
845: hm.put(taclet.name().toString(), instList);
846: }
847:
848: private static void saveListFor(ApplyTacletDialogModel model) {
849: Taclet taclet = model.taclet();
850: TacletInstantiationsTableModel tableModel = model
851: .tableModel();
852: int start = model.tacletApp().instantiations().size();
853: java.util.List instList = getInstantiationListsFor(taclet);
854: try {
855: BufferedWriter bw = new BufferedWriter(new FileWriter(
856: INSTANTIATION_DIR + File.separator
857: + taclet.name().toString()));
858: StringBuffer sb = new StringBuffer();
859: for (int i = start; i < tableModel.getRowCount(); i++) {
860: if (i > start) {
861: sb.append(SEPARATOR2).append(LINE_END);
862: }
863: sb.append(tableModel.getValueAt(i, 1)).append(
864: LINE_END);
865: }
866: String newInst = sb.toString();
867: bw.write(newInst);
868: if (instList != null) {
869: ListIterator instListIt = instList.listIterator();
870: int count = 1;
871: while (instListIt.hasNext() && count < SAVE_COUNT) {
872: ListIterator instIt = ((java.util.List) instListIt
873: .next()).listIterator();
874: sb = new StringBuffer();
875: for (int i = 0; instIt.hasNext(); i++) {
876: if (i > 0) {
877: sb.append(SEPARATOR2).append(LINE_END);
878: }
879: sb.append(instIt.next()).append(LINE_END);
880: }
881: String oldInst = sb.toString();
882: if (!oldInst.equals(newInst)) {
883: bw.write(SEPARATOR1 + LINE_END + oldInst);
884: count++;
885: }
886: }
887: }
888: bw.close();
889: } catch (IOException e) {
890: }
891: hm.put(taclet.name().toString(), null);
892: }
893:
894: }
895:
896: }
|