View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2024 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ///////////////////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.gui;
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.nio.charset.StandardCharsets;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.Locale;
28  
29  import com.puppycrawl.tools.checkstyle.JavaParser;
30  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
31  import com.puppycrawl.tools.checkstyle.api.DetailAST;
32  import com.puppycrawl.tools.checkstyle.api.FileText;
33  
34  /**
35   * Model for checkstyle frame.
36   */
37  public class MainFrameModel {
38  
39      /**
40       * Parsing modes which available in GUI.
41       */
42      public enum ParseMode {
43  
44          /** Only Java tokens without comments. */
45          PLAIN_JAVA("Plain Java"),
46  
47          /** Java tokens and comment nodes (singleline comments and block comments). */
48          JAVA_WITH_COMMENTS("Java with comments"),
49  
50          /**
51           * Java tokens, comments and Javadoc comments nodes
52           * (which are parsed from block comments).
53           */
54          JAVA_WITH_JAVADOC_AND_COMMENTS("Java with comments and Javadocs");
55  
56          /**
57           * Mode's short description.
58           */
59          private final String description;
60  
61          /**
62           * Provides description.
63           *
64           * @param descr description
65           */
66          ParseMode(String descr) {
67              description = descr;
68          }
69  
70          @Override
71          public String toString() {
72              return description;
73          }
74  
75      }
76  
77      /** Parse tree model. */
78      private final ParseTreeTableModel parseTreeTableModel;
79  
80      /** Lines to position map. */
81      private List<Integer> linesToPosition = new ArrayList<>();
82  
83      /** Current mode. */
84      private ParseMode parseMode = ParseMode.PLAIN_JAVA;
85  
86      /** The file which is being parsed. */
87      private File currentFile;
88  
89      /** Text for a frame's text area. */
90      private String text;
91  
92      /** Title for the main frame. */
93      private String title = "Checkstyle GUI";
94  
95      /** Whether the reload action is enabled. */
96      private boolean reloadActionEnabled;
97  
98      /** Instantiate the model. */
99      public MainFrameModel() {
100         parseTreeTableModel = new ParseTreeTableModel(null);
101     }
102 
103     /**
104      * Set current parse mode.
105      *
106      * @param mode ParseMode enum.
107      */
108     public void setParseMode(ParseMode mode) {
109         parseMode = mode;
110     }
111 
112     /**
113      * Get parse tree table model.
114      *
115      * @return parse tree table model.
116      */
117     public ParseTreeTableModel getParseTreeTableModel() {
118         return parseTreeTableModel;
119     }
120 
121     /**
122      * Get text to display in a text area.
123      *
124      * @return text to display in a text area.
125      */
126     public String getText() {
127         return text;
128     }
129 
130     /**
131      * Returns title for the main frame.
132      *
133      * @return title for the main frame.
134      */
135     public String getTitle() {
136         return title;
137     }
138 
139     /**
140      * Returns true if the reload action is enabled, false otherwise.
141      *
142      * @return true if the reload action is enabled.
143      */
144     public boolean isReloadActionEnabled() {
145         return reloadActionEnabled;
146     }
147 
148     /**
149      * Whether a file chooser should accept the file as a source file.
150      *
151      * @param file the file to check.
152      * @return true if the file should be accepted.
153      */
154     public static boolean shouldAcceptFile(File file) {
155         return file.isDirectory() || file.getName().endsWith(".java");
156     }
157 
158     /**
159      * Get the directory of the last loaded file.
160      *
161      * @return directory of the last loaded file.
162      */
163     public File getLastDirectory() {
164         File lastDirectory = null;
165         if (currentFile != null) {
166             lastDirectory = currentFile.getParentFile();
167         }
168         return lastDirectory;
169     }
170 
171     /**
172      * Get current file.
173      *
174      * @return current file.
175      */
176     public File getCurrentFile() {
177         return currentFile;
178     }
179 
180     /**
181      * Get lines to position map.
182      * It returns unmodifiable collection to
183      * prevent additional overhead of copying
184      * and possible state modifications.
185      *
186      * @return lines to position map.
187      */
188     public List<Integer> getLinesToPosition() {
189         return new ArrayList<>(linesToPosition);
190     }
191 
192     /**
193      * Open file and load the file.
194      *
195      * @param file the file to open.
196      * @throws CheckstyleException if the file can not be parsed.
197      * @throws IllegalArgumentException if parseMode is unknown
198      */
199     public void openFile(File file) throws CheckstyleException {
200         if (file != null) {
201             try {
202                 currentFile = file;
203                 title = "Checkstyle GUI : " + file.getName();
204                 reloadActionEnabled = true;
205                 final DetailAST parseTree;
206 
207                 if (parseMode == ParseMode.PLAIN_JAVA) {
208                     parseTree = JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS);
209                 }
210                 else if (parseMode == ParseMode.JAVA_WITH_COMMENTS
211                         || parseMode == ParseMode.JAVA_WITH_JAVADOC_AND_COMMENTS) {
212                     parseTree = JavaParser.parseFile(file, JavaParser.Options.WITH_COMMENTS);
213                 }
214                 else {
215                     throw new IllegalArgumentException("Unknown mode: " + parseMode);
216                 }
217 
218                 parseTreeTableModel.setParseTree(parseTree);
219                 parseTreeTableModel.setParseMode(parseMode);
220                 final String[] sourceLines = getFileText(file).toLinesArray();
221 
222                 final List<Integer> linesToPositionTemp = new ArrayList<>(sourceLines.length + 1);
223                 // starts line counting at 1
224                 linesToPositionTemp.add(0);
225 
226                 final StringBuilder sb = new StringBuilder(1024);
227                 // insert the contents of the file to the text area
228                 for (final String element : sourceLines) {
229                     linesToPositionTemp.add(sb.length());
230                     sb.append(element).append(System.lineSeparator());
231                 }
232                 linesToPosition = linesToPositionTemp;
233                 text = sb.toString();
234             }
235             catch (IOException ex) {
236                 final String exceptionMsg = String.format(Locale.ROOT,
237                     "%s occurred while opening file %s.",
238                     ex.getClass().getSimpleName(), file.getPath());
239                 throw new CheckstyleException(exceptionMsg, ex);
240             }
241         }
242     }
243 
244     /**
245      * Get FileText from a file.
246      *
247      * @param file the file to get the FileText from.
248      * @return the FileText.
249      * @throws IOException if the file could not be read.
250      */
251     private static FileText getFileText(File file) throws IOException {
252         return new FileText(file.getAbsoluteFile(),
253                 System.getProperty("file.encoding", StandardCharsets.UTF_8.name()));
254     }
255 
256 }