001: /*
002: * SqlHistory.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.gui.sql;
013:
014: import java.io.BufferedReader;
015: import java.io.IOException;
016: import java.io.InputStream;
017: import java.io.OutputStream;
018: import java.io.StringReader;
019: import java.io.Writer;
020: import java.util.ArrayList;
021: import workbench.gui.actions.ClearStatementHistoryAction;
022: import workbench.gui.actions.WbAction;
023:
024: import workbench.log.LogMgr;
025: import workbench.util.EncodingUtil;
026: import workbench.util.StringUtil;
027: import workbench.gui.actions.FirstStatementAction;
028: import workbench.gui.actions.LastStatementAction;
029: import workbench.gui.actions.NextStatementAction;
030: import workbench.gui.actions.PrevStatementAction;
031: import workbench.resource.Settings;
032:
033: /**
034: * Stores the SQL scripts entered in the {@link SqlPanel} and manages
035: * a history of statements.
036: *
037: * @author support@sql-workbench.net
038: */
039: public class SqlHistory {
040: private static final String LIST_DELIMITER = "----------- WbStatement -----------";
041:
042: private ArrayList<SqlHistoryEntry> history;
043: private int currentEntry;
044: private int maxSize;
045: private boolean changed = false;
046: private EditorPanel editor;
047: private NextStatementAction nextStmtAction;
048: private PrevStatementAction prevStmtAction;
049: private FirstStatementAction firstStmtAction;
050: private LastStatementAction lastStmtAction;
051: private ClearStatementHistoryAction clearAction;
052:
053: public SqlHistory(EditorPanel ed, int maxSize) {
054: this .maxSize = maxSize;
055: this .history = new ArrayList<SqlHistoryEntry>(maxSize + 2);
056: this .editor = ed;
057: this .firstStmtAction = new FirstStatementAction(this );
058: this .firstStmtAction.setEnabled(false);
059:
060: this .prevStmtAction = new PrevStatementAction(this );
061: this .prevStmtAction.setEnabled(false);
062:
063: this .nextStmtAction = new NextStatementAction(this );
064: this .nextStmtAction.setEnabled(false);
065:
066: this .lastStmtAction = new LastStatementAction(this );
067: this .lastStmtAction.setEnabled(false);
068:
069: this .clearAction = new ClearStatementHistoryAction(this );
070: this .clearAction.setEnabled(false);
071: }
072:
073: public WbAction getShowFirstStatementAction() {
074: return this .firstStmtAction;
075: }
076:
077: public WbAction getShowLastStatementAction() {
078: return this .lastStmtAction;
079: }
080:
081: public WbAction getShowNextStatementAction() {
082: return this .nextStmtAction;
083: }
084:
085: public WbAction getShowPreviousStatementAction() {
086: return this .prevStmtAction;
087: }
088:
089: public WbAction getClearHistoryAction() {
090: return this .clearAction;
091: }
092:
093: public synchronized void addContent(EditorPanel editor) {
094: boolean includeFiles = Settings.getInstance()
095: .getStoreFilesInHistory();
096: if (!includeFiles && editor.hasFileLoaded())
097: return;
098:
099: int maxLength = Settings.getInstance()
100: .getIntProperty("workbench.sql.history.maxtextlength",
101: 1024 * 1024 * 10);
102: if (editor.getDocumentLength() > maxLength)
103: return;
104:
105: String text = editor.getText();
106: if (text == null || text.length() == 0)
107: return;
108:
109: try {
110: SqlHistoryEntry entry = null;
111: if (editor.currentSelectionIsTemporary()) {
112: entry = new SqlHistoryEntry(text, editor
113: .getCaretPosition(), 0, 0);
114: } else {
115: entry = new SqlHistoryEntry(text, editor
116: .getCaretPosition(),
117: editor.getSelectionStart(), editor
118: .getSelectionEnd());
119: }
120:
121: SqlHistoryEntry top = this .getTopEntry();
122: if (top != null && top.equals(entry))
123: return;
124: this .addEntry(entry);
125: } catch (Exception e) {
126: LogMgr.logError("SqlHistory.addContent(editor)",
127: "Could not add entry", e);
128: }
129: checkActions();
130: }
131:
132: public void addEntry(SqlHistoryEntry entry) {
133: this .history.add(entry);
134: if (this .history.size() > this .maxSize) {
135: this .history.remove(0);
136: }
137: this .currentEntry = this .history.size() - 1;
138: this .changed = true;
139: }
140:
141: public boolean hasNext() {
142: return (this .currentEntry < (this .history.size() - 1));
143: }
144:
145: public boolean hasPrevious() {
146: return (this .currentEntry > 0);
147: }
148:
149: public void clear() {
150: this .currentEntry = 0;
151: this .history.clear();
152: this .changed = false;
153: this .checkActions();
154: }
155:
156: public void showLastStatement() {
157: if (this .history.size() == 0)
158: return;
159: this .currentEntry = this .history.size() - 1;
160: SqlHistoryEntry entry = this .history.get(this .currentEntry);
161: entry.applyTo(editor);
162: checkActions();
163: }
164:
165: public void showFirstStatement() {
166: if (this .history.size() == 0)
167: return;
168: this .currentEntry = 0;
169: SqlHistoryEntry entry = this .history.get(this .currentEntry);
170: entry.applyTo(editor);
171: checkActions();
172: }
173:
174: public void showCurrent() {
175: if (this .currentEntry >= this .history.size())
176: return;
177: SqlHistoryEntry entry = this .history.get(this .currentEntry);
178: entry.applyTo(editor);
179: checkActions();
180: }
181:
182: public void showPreviousStatement() {
183: if (!this .hasPrevious())
184: return;
185: SqlHistoryEntry entry = this .getPreviousEntry();
186: entry.applyTo(editor);
187: checkActions();
188: }
189:
190: public void showNextStatement() {
191: if (!this .hasNext())
192: return;
193: SqlHistoryEntry entry = this .getNextEntry();
194: entry.applyTo(editor);
195: checkActions();
196: }
197:
198: public SqlHistoryEntry getTopEntry() {
199: if (this .history.size() < 1)
200: return null;
201: SqlHistoryEntry entry = this .history
202: .get(this .history.size() - 1);
203: return entry;
204: }
205:
206: private SqlHistoryEntry getPreviousEntry() {
207: if (this .currentEntry <= 0)
208: return null;
209: this .currentEntry--;
210: SqlHistoryEntry entry = this .history.get(this .currentEntry);
211: return entry;
212: }
213:
214: private SqlHistoryEntry getNextEntry() {
215: if (this .currentEntry >= this .history.size() - 1)
216: return null;
217: this .currentEntry++;
218: SqlHistoryEntry entry = this .history.get(this .currentEntry);
219: return entry;
220: }
221:
222: private static final String KEY_POS = "##sqlwb.pos=";
223: private static final String KEY_START = "##sqlwb.selStart=";
224: private static final String KEY_END = "##sqlwb.selEnd=";
225:
226: public void writeToStream(OutputStream out) {
227:
228: String lineEnding = "\n";
229: try {
230: Writer writer = EncodingUtil.createWriter(out, "UTF-8");
231:
232: int count = this .history.size();
233: for (int i = 0; i < count; i++) {
234: SqlHistoryEntry entry = this .history.get(i);
235: writer.write(KEY_POS);
236: writer.write(Integer
237: .toString(entry.getCursorPosition()));
238: writer.write(lineEnding);
239:
240: writer.write(KEY_START);
241: writer.write(Integer
242: .toString(entry.getSelectionStart()));
243: writer.write(lineEnding);
244:
245: writer.write(KEY_END);
246: writer.write(Integer.toString(entry.getSelectionEnd()));
247: writer.write(lineEnding);
248:
249: // Make sure the editor text is converted to the correct line ending
250: BufferedReader reader = new BufferedReader(
251: new StringReader(entry.getText()));
252: String line = reader.readLine();
253: while (line != null) {
254: int len = StringUtil.getRealLineLength(line);
255: if (len > 0) {
256: writer.write(line.substring(0, len));
257: }
258: writer.write(lineEnding);
259: line = reader.readLine();
260: }
261:
262: //writer.write(lineEnding);
263: writer.write(LIST_DELIMITER);
264: writer.write(lineEnding);
265: }
266: writer.flush();
267: this .changed = false;
268: } catch (IOException e) {
269: LogMgr.logError("SqlHistory.writeToStream()",
270: "Could not write history!", e);
271: }
272: }
273:
274: public boolean isChanged() {
275: return this .changed;
276: }
277:
278: public void readFromStream(InputStream in) {
279: StringBuilder content = new StringBuilder(500);
280: int pos = 0;
281: int start = -1;
282: int end = -1;
283:
284: String lineEnding = "\n";
285: BufferedReader reader = null;
286: try {
287: reader = new BufferedReader(EncodingUtil.createReader(in,
288: "UTF-8"));
289: String line = reader.readLine();
290: while (line != null) {
291: if (line.equals(LIST_DELIMITER)) {
292: try {
293: SqlHistoryEntry entry = new SqlHistoryEntry(
294: content.toString(), pos, start, end);
295: this .addEntry(entry);
296: pos = 0;
297: start = -1;
298: end = -1;
299: content = new StringBuilder(500);
300: } catch (Exception e) {
301: LogMgr.logError("SqlHistory.readFromStream()",
302: "Error when creating SqlHistoryEntry",
303: e);
304: }
305: } else if (line.startsWith(KEY_POS)) {
306: pos = StringUtil.getIntValue(line.substring(KEY_POS
307: .length()), -1);
308: } else if (line.startsWith(KEY_START)) {
309: start = StringUtil.getIntValue(line
310: .substring(KEY_START.length()), -1);
311: } else if (line.startsWith(KEY_END)) {
312: end = StringUtil.getIntValue(line.substring(KEY_END
313: .length()), -1);
314: } else {
315: int len = StringUtil.getRealLineLength(line);
316: if (len > 0) {
317: content.append(line, 0, len);
318: }
319: content.append(lineEnding);
320: }
321: line = reader.readLine();
322: }
323: this .changed = false;
324: } catch (IOException e) {
325: LogMgr.logError("SqlHistory.readFromStream()",
326: "Could not read history!", e);
327: } finally {
328: try {
329: reader.close();
330: } catch (Throwable th) {
331: }
332: }
333:
334: if (content.length() > 0) {
335: SqlHistoryEntry entry = new SqlHistoryEntry(content
336: .toString(), pos, start, end);
337: this .addEntry(entry);
338: }
339: }
340:
341: private void checkActions() {
342: this .nextStmtAction.setEnabled(this .hasNext());
343: this .lastStmtAction.setEnabled(this .hasNext());
344: this .prevStmtAction.setEnabled(this .hasPrevious());
345: this .firstStmtAction.setEnabled(this .hasPrevious());
346: this .clearAction.setEnabled(this .history.size() > 0);
347: }
348: }
|