001: /* ====================================================================
002: * The JRefactory License, Version 1.0
003: *
004: * Copyright (c) 2001 JRefactory. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by the
021: * JRefactory (http://www.sourceforge.org/projects/jrefactory)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. The names "JRefactory" must not be used to endorse or promote
026: * products derived from this software without prior written
027: * permission. For written permission, please contact seguin@acm.org.
028: *
029: * 5. Products derived from this software may not be called "JRefactory",
030: * nor may "JRefactory" appear in their name, without prior written
031: * permission of Chris Seguin.
032: *
033: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
034: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
035: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036: * DISCLAIMED. IN NO EVENT SHALL THE CHRIS SEGUIN OR
037: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
038: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
039: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
040: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
041: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
042: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
043: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
044: * SUCH DAMAGE.
045: * ====================================================================
046: *
047: * This software consists of voluntary contributions made by many
048: * individuals on behalf of JRefactory. For more information on
049: * JRefactory, please see
050: * <http://www.sourceforge.org/projects/jrefactory>.
051: */
052: package org.acm.seguin.ide.common.action;
053:
054: import java.io.StringReader;
055: import java.io.File;
056: import java.io.IOException;
057: import java.util.Iterator;
058: import javax.swing.event.DocumentEvent;
059: import javax.swing.event.DocumentListener;
060: import org.acm.seguin.summary.FieldSummary;
061: import org.acm.seguin.summary.FileSummary;
062: import org.acm.seguin.summary.MethodSummary;
063: import org.acm.seguin.summary.Summary;
064: import org.acm.seguin.summary.TypeSummary;
065: import org.acm.seguin.ide.common.MultipleDirClassDiagramReloader;
066: import org.acm.seguin.ide.common.IDEPlugin;
067:
068: /**
069: * Determines what the current summary is based on the information from the
070: * IDE.
071: *
072: *@author Chris Seguin
073: *@author <a href="JRefactory@ladyshot.demon.co.uk">Mike Atkinson</a>
074: *@version $Id: CurrentSummary.java,v 1.5 2003/11/19 20:36:24 mikeatkinson Exp $
075: *@created October 18, 2001
076: */
077: public abstract class CurrentSummary extends Object implements
078: DocumentListener {
079: private FileSummary fileSummary;
080: public int lineNo = -1;
081:
082: private static CurrentSummary singleton = null;
083: private Summary summary;
084: /**
085: * Has this file changed since the last time this was invoked
086: */
087: protected boolean upToDate;
088:
089: /**
090: * Constructor for the CurrentSummary object
091: */
092: protected CurrentSummary() {
093: summary = null;
094: fileSummary = null;
095: upToDate = false;
096: }
097:
098: /**
099: * Method to get the singleton object
100: *
101: *@return the current summary
102: */
103: public static CurrentSummary get() {
104: System.out.println("CurrentSummary.get()");
105: return singleton;
106: }
107:
108: /**
109: * Gets the ActiveFile attribute of the CurrentSummary object
110: *
111: *@return The ActiveFile value
112: */
113: protected File getActiveFile() {
114: java.awt.Frame view = IDEPlugin.getEditorFrame();
115: Object buffer = IDEPlugin.getCurrentBuffer(view);
116: System.out.println("CurrentSummary.getActiveFile() -> "
117: + IDEPlugin.getFile(view, buffer));
118: return IDEPlugin.getFile(view, buffer);
119: }
120:
121: /**
122: * Gets the CurrentSummary attribute of the CurrentSummary object
123: *
124: *@return The CurrentSummary value
125: */
126: public Summary getCurrentSummary() {
127: System.out.println("CurrentSummary.getCurrentSummary()");
128: System.out.flush();
129: if ((summary == null) || upToDate || !isSameFile()
130: || !isInSameSummary()) {
131: System.out.println(" - lockAccess()");
132: System.out.flush();
133: lockAccess();
134: }
135:
136: System.out.println("Summary is: " + summary + " from "
137: + getLineNumber());
138: return summary;
139: }
140:
141: /**
142: * Gets the InType attribute of the CurrentSummary object
143: *
144: *@param fileSummary Description of Parameter
145: *@param lineNumber Description of Parameter
146: *@return The InType value
147: */
148: private Summary getInType(FileSummary fileSummary, int lineNumber) {
149: System.out.println("CurrentSummary.getInType()");
150: Iterator iter = fileSummary.getTypes();
151: if (iter == null) {
152: System.out.println(" -> null");
153: return null;
154: }
155:
156: System.out.println("Searching for: " + lineNumber);
157: while (iter.hasNext()) {
158: TypeSummary next = (TypeSummary) iter.next();
159: System.out.println("Type: " + next.toString() + " "
160: + next.getStartLine() + ", " + next.getEndLine());
161: if ((next.getStartLine() <= lineNumber)
162: && (next.getEndLine() >= lineNumber)) {
163: Summary s = findSummaryInType(next, lineNumber);
164: System.out.println(" -> " + s);
165: return s;
166: }
167: }
168:
169: System.out.println(" -> null");
170: return null;
171: }
172:
173: /**
174: * Returns the initial line number
175: *
176: *@return The LineNumber value
177: */
178: protected int getLineNumber() {
179: if (lineNo < 0) {
180: java.awt.Frame view = IDEPlugin.getEditorFrame();
181: Object buffer = IDEPlugin.getCurrentBuffer(view);
182: int ln = IDEPlugin.getLineNumber(view, buffer);
183: System.out.println("CurrentSummary.getLineNumber() -> "
184: + ln);
185: return ln;
186: }
187: System.out.println("CurrentSummary.getLineNumber() -> "
188: + lineNo);
189: return lineNo;
190: }
191:
192: /**
193: * Gets the reloader
194: *
195: *@return The MetadataReloader value
196: */
197: protected abstract MultipleDirClassDiagramReloader getMetadataReloader();
198:
199: /**
200: * Gets the InField attribute of the CurrentSummary object
201: *
202: *@param typeSummary Description of Parameter
203: *@param lineNumber Description of Parameter
204: *@return The InField value
205: */
206: private Summary isInField(TypeSummary typeSummary, int lineNumber) {
207: System.out.println("CurrentSummary.isInField()");
208: Iterator iter = typeSummary.getFields();
209: if (iter == null) {
210: System.out.println(" -> null");
211: return null;
212: }
213:
214: while (iter.hasNext()) {
215: FieldSummary next = (FieldSummary) iter.next();
216: System.out.println("Field: " + next.toString() + " "
217: + next.getStartLine() + ", " + next.getEndLine());
218: if ((next.getStartLine() <= lineNumber)
219: && (next.getEndLine() >= lineNumber)) {
220: return next;
221: }
222: }
223:
224: System.out.println(" -> null");
225: return null;
226: }
227:
228: /**
229: * Gets the InMethod attribute of the CurrentSummary object
230: *
231: *@param typeSummary Description of Parameter
232: *@param lineNumber Description of Parameter
233: *@return The InMethod value
234: */
235: private Summary isInMethod(TypeSummary typeSummary, int lineNumber) {
236: System.out.println("CurrentSummary.isInMethod()");
237: Iterator iter = typeSummary.getMethods();
238: if (iter == null) {
239: System.out.println(" -> null");
240: return null;
241: }
242:
243: while (iter.hasNext()) {
244: MethodSummary next = (MethodSummary) iter.next();
245:
246: System.out.println("Method: " + next.toString() + " "
247: + next.getStartLine() + ", " + next.getEndLine());
248: if ((next.getStartLine() <= lineNumber)
249: && (next.getEndLine() >= lineNumber)) {
250: return next;
251: }
252: }
253:
254: System.out.println(" -> null");
255: return null;
256: }
257:
258: /**
259: * Gets the InNestedClass attribute of the CurrentSummary object
260: *
261: *@param typeSummary Description of Parameter
262: *@param lineNumber Description of Parameter
263: *@return The InNestedClass value
264: */
265: private Summary isInNestedClass(TypeSummary typeSummary,
266: int lineNumber) {
267: System.out.println("CurrentSummary.isInNestedClass()");
268: Iterator iter = typeSummary.getTypes();
269: if (iter == null) {
270: System.out.println(" -> null");
271: return null;
272: }
273:
274: while (iter.hasNext()) {
275: TypeSummary next = (TypeSummary) iter.next();
276: System.out.println("Type: " + next.toString() + " "
277: + next.getStartLine() + ", " + next.getEndLine());
278: if ((next.getStartLine() <= lineNumber)
279: && (next.getEndLine() >= lineNumber)) {
280: return findSummaryInType(next, lineNumber);
281: }
282: }
283:
284: System.out.println(" -> null");
285: return null;
286: }
287:
288: /**
289: * Gets the InSameSummary attribute of the CurrentSummary object
290: *
291: *@return The InSameSummary value
292: */
293: private boolean isInSameSummary() {
294: int lineNumber = getLineNumber();
295: return ((summary.getStartLine() <= lineNumber) && (summary
296: .getEndLine() >= lineNumber));
297: }
298:
299: /**
300: * Gets the SameNode attribute of the CurrentSummary object
301: *
302: *@return The SameNode value
303: */
304: private boolean isSameFile() {
305: if (fileSummary == null) {
306: return false;
307: }
308:
309: boolean result = (fileSummary.getFile() == getActiveFile());
310: System.out.println("Node is the same: " + result);
311: return result;
312: }
313:
314: /**
315: * Method that receives notification when the editor changes
316: *
317: *@param evt Description of Parameter
318: */
319: public void changedUpdate(DocumentEvent evt) {
320: upToDate = false;
321: }
322:
323: /**
324: * Description of the Method
325: *
326: *@return Description of the Returned Value
327: */
328: private Summary find() {
329: System.out.println("CurrentSummary.find()");
330: try {
331: registerWithCurrentDocument();
332:
333: int lineNumber = getLineNumber();
334: if (lineNumber == -1) {
335: System.out.println("Unable to get the line number: "
336: + lineNumber);
337: return null;
338: }
339:
340: if (!upToDate || (fileSummary == null)) {
341: fileSummary = reloadNode();
342: }
343:
344: if (fileSummary == null) {
345: System.out.println("Unable to load a file summary");
346: return null;
347: }
348:
349: Summary summary = getInType(fileSummary, lineNumber);
350: if (summary != null) {
351: System.out.println("Found a summary: " + summary);
352: return summary;
353: }
354:
355: System.out.println("Just able to return the file summary");
356: return fileSummary;
357: } catch (IOException ioe) {
358: return null;
359: }
360: }
361:
362: /**
363: * Description of the Method
364: *
365: *@param next Description of Parameter
366: *@param lineNumber Description of Parameter
367: *@return Description of the Returned Value
368: */
369: private Summary findSummaryInType(TypeSummary next, int lineNumber) {
370: System.out.println("CurrentSummary.findSummaryInType()");
371: Summary result = isInMethod(next, lineNumber);
372: if (result != null) {
373: System.out.println("Found a method: " + summary);
374: return result;
375: }
376:
377: result = isInField(next, lineNumber);
378: if (result != null) {
379: System.out.println("Found a field: " + summary);
380: return result;
381: }
382:
383: result = isInNestedClass(next, lineNumber);
384: if (result != null) {
385: System.out.println("Found a class: " + summary);
386: return result;
387: }
388:
389: return next;
390: }
391:
392: /**
393: * Method that receives notification when the editor changes
394: *
395: *@param evt Description of Parameter
396: */
397: public void insertUpdate(DocumentEvent evt) {
398: upToDate = false;
399: }
400:
401: /**
402: * Only does one find at a time
403: */
404: private synchronized void lockAccess() {
405: if ((summary == null) || !upToDate || !isSameFile()
406: || !isInSameSummary()) {
407: System.out.println("About to find the summary");
408: summary = find();
409: upToDate = true;
410: System.out.println("Done");
411: }
412:
413: System.out.println("Finished lock access");
414: }
415:
416: /**
417: * Register the current summary
418: *
419: *@param value Description of Parameter
420: */
421: public static void register(CurrentSummary value) {
422: singleton = value;
423: }
424:
425: /**
426: * Register with the current document
427: */
428: protected abstract void registerWithCurrentDocument();
429:
430: /**
431: * Description of the Method
432: *
433: *@return Description of the Returned Value
434: *@exception IOException Description of Exception
435: */
436: private FileSummary reloadNode() throws IOException {
437: System.out.println("CurrentSummary.reloadNode()");
438: java.awt.Frame view = IDEPlugin.getEditorFrame();
439: Object buffer = IDEPlugin.getCurrentBuffer(view);
440: if (IDEPlugin.bufferContainsJavaSource(view, buffer)) {
441: String contents = IDEPlugin.getText(view, buffer);
442: StringReader reader = new StringReader(contents);
443:
444: System.out
445: .println("CurrentSummary.reloadNode() -> FileSummary");
446: return FileSummary.reloadFromBuffer(IDEPlugin.getFile(view,
447: buffer), reader);
448: }
449:
450: System.out.println("CurrentSummary.reloadNode() -> null");
451: return null;
452: }
453:
454: /**
455: * Method that receives notification when the editor changes
456: *
457: *@param evt Description of Parameter
458: */
459: public void removeUpdate(DocumentEvent evt) {
460: upToDate = false;
461: }
462:
463: /**
464: * Description of the Method
465: */
466: public void reset() {
467: System.out.println("CurrentSummary.reset()");
468: upToDate = false;
469: }
470:
471: /**
472: * Reloads all the metadata before attempting to perform a refactoring.
473: */
474: public void updateMetaData() {
475: System.out.println("CurrentSummary.updateMetaData()");
476: System.out.flush();
477: MultipleDirClassDiagramReloader reloader = getMetadataReloader();
478:
479: reloader.setNecessary(true);
480: reloader.reload();
481: System.out.println("CurrentSummary.updateMetaData() - end");
482: }
483: }
|