001: package net.sf.jdec.format;
002:
003: import java.io.BufferedReader;
004: import java.io.File;
005: import java.io.FileInputStream;
006: import java.io.FileNotFoundException;
007: import java.io.InputStreamReader;
008:
009: import javax.swing.JOptionPane;
010:
011: import net.sf.jdec.main.ConsoleLauncher;
012:
013: /*
014: * Formatter.java Copyright (c) 2006,07 Swaroop Belur
015: *
016: * This program is free software; you can redistribute it and/or
017: * modify it under the terms of the GNU General Public License
018: * as published by the Free Software Foundation; either version 2
019: * of the License, or (at your option) any later version.
020:
021: * This program is distributed in the hope that it will be useful,
022: * but WITHOUT ANY WARRANTY; without even the implied warranty of
023: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
024: * GNU General Public License for more details.
025:
026: * You should have received a copy of the GNU General Public License
027: * along with this program; if not, write to the Free Software
028: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
029: *
030: */
031:
032: /*******************************************************************************
033: *
034: * TODO: Need to rewrite formatting
035: *
036: * Aim of this class is to evolve the formatting logic present in 1.2 version to
037: * an extent so that
038: *
039: * these 2 basic requirements are satisified.
040: *
041: * 1> No Hacks are required 2> No Mandatory newline characters at some
042: * particular slots like before '{' and after '}'
043: *
044: * If possible , allow the user to specify the positions of some key characters
045: * like
046: *
047: * 1> bracket { placement 2> space after if , while , switch 3> Ignoring { , }
048: * for case blocks.
049: *
050: *
051: *
052: *
053: * @author swaroop belur
054: *
055: */
056: public class Formatter {
057:
058: private String unformattedInput = null;
059:
060: private String output;
061:
062: private int indentSpaces = 2;
063:
064: private int currentSpaces = 0;
065:
066: public Formatter(String input) {
067: unformattedInput = input;
068: init();
069: applySettings();
070: output = format();
071: formatLicence();
072: }
073:
074: public Formatter(File input) {
075: BufferedReader reader;
076: try {
077: reader = new BufferedReader(new InputStreamReader(
078: new FileInputStream(input)));
079:
080: StringBuffer buffer = new StringBuffer("");
081: String temp = reader.readLine();
082: while (temp != null) {
083: buffer.append(temp);
084: temp = reader.readLine();
085: }
086: unformattedInput = buffer.toString();
087: init();
088: applySettings();
089: output = format();
090: formatLicence();
091: } catch (Exception e) {
092: JOptionPane.showMessageDialog(null,
093: "Could not read from input file");
094: e.printStackTrace();
095: }
096: }
097:
098: private void formatLicence() {
099: String licB = "// Decompiled by jdec";
100: String licE = "// See the File 'COPYING' For more details.";
101: int index = output.indexOf(licE);
102: if (index != -1) {
103: if ((index + licE.length()) < output.length()) {
104: String lic = output.substring(0, index + licE.length());
105: String rest = output.substring(index + licE.length());
106: output = ConsoleLauncher.getLicenceWarning() + rest;
107: }
108: }
109: }
110:
111: private boolean isNextCharCloseFlowerBracker(int pos, String input) {
112:
113: int k = pos + 1;
114: if (k < input.length()) {
115: for (int temp = k; temp < input.length(); temp++) {
116: char ch = input.charAt(temp);
117: if (ch == ' ') {
118: continue;
119: }
120: if (ch == '}') {
121: return true;
122: } else {
123: return false;
124: }
125: }
126:
127: }
128: return false;
129: }
130:
131: private boolean isNextSeqCLASSMarker(int pos, String input) {
132: int k = pos + 1;
133: if (k < input.length()) {
134: for (int temp = k; temp < input.length(); temp++) {
135: char ch = input.charAt(temp);
136: if (ch == ' ') {
137: continue;
138: }
139: if (ch == '\n') {
140: continue;
141: }
142: if (ch == '/') {
143: int k1 = temp + 1;
144: if (k1 < input.length()) {
145: char ch1 = input.charAt(k1);
146: if (ch1 == '/') {
147: k1 = k1 + 1;
148: if (k1 < input.length()) {
149: ch1 = input.charAt(k1);
150: if (ch1 == ' ') {
151: k1 = k1 + 1;
152: if (k1 < input.length()) {
153: ch1 = input.charAt(k1);
154: if (ch1 == ' ') {
155: boolean b = checkForClASSString(
156: k1, input);
157: if (b)
158: return b;
159: } else {
160: boolean b = checkForClASSString(
161: k1 - 1, input);
162: if (b)
163: return b;
164: }
165: }
166:
167: }
168: }
169: }
170: }
171:
172: } else {
173: return false;
174: }
175: }
176:
177: }
178: return false;
179: }
180:
181: private boolean checkForClASSString(int k1, String input) {
182: k1 = k1 + 1;
183: char ch1;
184: if (k1 < input.length()) {
185: ch1 = input.charAt(k1);
186: if (ch1 == 'C') {
187: k1 = k1 + 1;
188: if (k1 < input.length()) {
189: ch1 = input.charAt(k1);
190: if (ch1 == 'L') {
191: k1 = k1 + 1;
192: if (k1 < input.length()) {
193: ch1 = input.charAt(k1);
194: if (ch1 == 'A') {
195: k1 = k1 + 1;
196: if (k1 < input.length()) {
197: ch1 = input.charAt(k1);
198: if (ch1 == 'S') {
199: k1 = k1 + 1;
200: if (k1 < input.length()) {
201: ch1 = input.charAt(k1);
202: if (ch1 == 'S') {
203: k1 = k1 + 1;
204: if (k1 < input.length()) {
205: ch1 = input
206: .charAt(k1);
207: if (ch1 == ':') {
208: return true;
209: }
210: }
211: }
212: }
213: }
214: }
215: }
216: }
217: }
218: }
219: }
220: }
221: return false;
222: }
223:
224: private String format() {
225:
226: StringBuffer temp = new StringBuffer("");
227: boolean addSpace = false;
228: forloop: for (int i = 0; i < unformattedInput.length(); i++) {
229: String clazzString = "";
230: char ch = unformattedInput.charAt(i);
231: if (ch == '{') {
232: if (!Settings.flowerBracketAtSameLine) {
233: for (int j = 1; j <= currentSpaces; j++) {
234: temp.append(" ");
235: }
236: temp.append(" ");
237: }
238:
239: temp.append(ch);
240: temp.append("\n");
241: boolean reduceSpace = isNextCharCloseFlowerBracker(i,
242: unformattedInput);
243: if (!reduceSpace) {
244: currentSpaces = currentSpaces + indentSpaces;
245: }
246: addSpace = true;
247:
248: } else if (ch == '}') {
249: boolean addLine = checkToAddNewLineForCLoseBracket(i,
250: temp);
251: if (addLine) {
252: temp.append("\n");
253: if (currentSpaces > 0) {
254: int curCurrentSpaces = currentSpaces;
255: currentSpaces = currentSpaces - indentSpaces;
256: if (currentSpaces <= 0) {
257: currentSpaces = curCurrentSpaces;
258: }
259: }
260: for (int j = 1; j <= currentSpaces; j++) {
261: temp.append(" ");
262: }
263: temp.append(ch);
264: } else {
265: temp.append(ch);
266: }
267: temp.append("\n\n");
268: addSpace = true;
269: boolean reduceSpace = isNextCharCloseFlowerBracker(i,
270: unformattedInput);
271: if (reduceSpace) {
272: if (currentSpaces > 0)
273: currentSpaces = currentSpaces - indentSpaces;
274: }
275:
276: } else if (ch == ';') {
277: temp.append(ch);
278: temp.append("\n");
279: addSpace = true;
280: boolean reduceSpace = isNextCharCloseFlowerBracker(i,
281: unformattedInput);
282: if (reduceSpace) {
283: if (currentSpaces > 0)
284: currentSpaces = currentSpaces - indentSpaces;
285: }
286: boolean isabstract = isNextSeqCLASSMarker(i,
287: unformattedInput);
288: if (isabstract) {
289: temp.append("\n");
290: }
291: } else {
292: if (addSpace) {
293: for (int j = 1; j <= currentSpaces; j++) {
294: temp.append(" ");
295: }
296: addSpace = false;
297: clazzString = "";
298:
299: }
300: clazzString += ch;
301: if ((i + 5) < unformattedInput.length()) {
302: if (ch == 'C'
303: && unformattedInput.charAt((i + 1)) == 'L'
304: && unformattedInput.charAt((i + 2)) == 'A'
305: && unformattedInput.charAt((i + 3)) == 'S'
306: && unformattedInput.charAt((i + 4)) == 'S'
307: && unformattedInput.charAt((i + 5)) == ':') {
308: i = i + 6;
309: if (i < unformattedInput.length()) {
310: temp.append("CLASS:");
311: for (int u = i; u < unformattedInput
312: .length(); u++) {
313: if (unformattedInput.charAt(u) == ':') {
314: temp.append(unformattedInput
315: .charAt(u));
316: temp.append("\n");
317: i = u;
318: addSpace = true;
319: continue forloop;
320: } else {
321: temp.append(unformattedInput
322: .charAt(u));
323: }
324: }
325: }
326: }
327: }
328: temp.append(ch);
329: }
330:
331: }
332:
333: return temp.toString();
334: }
335:
336: private boolean checkToAddNewLineForCLoseBracket(int i,
337: StringBuffer temp) {
338: String tempString = temp.toString();
339: int from = temp.length() - 1;
340: for (int j = from; j >= 0; j--) {
341: char ch = tempString.charAt(j);
342: if (ch == ' ') {
343: continue;
344: }
345: if (ch == '\n') {
346: return false;
347: }
348: return true;
349: }
350: return false;
351: }
352:
353: private void init() {
354: unformattedInput = unformattedInput.replaceAll("\n", "");
355: unformattedInput = unformattedInput.replaceAll("\\s+", " ");
356: unformattedInput = unformattedInput.replaceAll("End of Import",
357: "End of Import\n\n");
358: unformattedInput = unformattedInput.replaceAll(
359: "/\\*\\*\\* \\*\\*Class Fields \\*\\*\\*/",
360: "/*** **Class Fields ***/\n");
361: unformattedInput = unformattedInput
362: .replaceAll(
363: "/\\*\\*\\*\\* List of All Imported Classes \\*\\*\\*/",
364: "\n/**** List of All Imported Classes ***/\n\n");
365: unformattedInput = unformattedInput.replaceFirst(
366: "See the File 'COPYING' For more details\\.",
367: "See the File 'COPYING' For more details.\n\n\n");
368: unformattedInput = unformattedInput.replaceAll(
369: "//Beginning of Inner Class Content\\.\\.\\.",
370: "//Beginning of Inner Class Content...\n");
371: unformattedInput = unformattedInput.replaceAll(
372: "//End Of a Inner Class File Content\\.\\.\\.",
373: "//End Of a Inner Class File Content...\n");
374:
375: }
376:
377: private void applySettings() {
378: if (Settings.flowerBracketAtSameLine) {
379: unformattedInput = unformattedInput.replaceAll("\\{", "{");
380: } else {
381: unformattedInput = unformattedInput
382: .replaceAll("\\{", "\n{");
383: }
384: }
385:
386: public static void main(String[] args) {
387: new Formatter(new File(
388: "c:/out/org/apache/log4j/AsyncAppender.jdec"));
389: }
390:
391: public String getOutput() {
392: return output;
393: }
394:
395: public void setOutput(String output) {
396: this.output = output;
397: }
398:
399: }
|