1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 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           * @param descr description
64           */
65          ParseMode(String descr) {
66              description = descr;
67          }
68  
69          @Override
70          public String toString() {
71              return description;
72          }
73  
74      }
75  
76      /** Parse tree model. */
77      private final ParseTreeTableModel parseTreeTableModel;
78  
79      /** Lines to position map. */
80      private List<Integer> linesToPosition = new ArrayList<>();
81  
82      /** Current mode. */
83      private ParseMode parseMode = ParseMode.PLAIN_JAVA;
84  
85      /** The file which is being parsed. */
86      private File currentFile;
87  
88      /** Text for a frame's text area. */
89      private String text;
90  
91      /** Title for the main frame. */
92      private String title = "Checkstyle GUI";
93  
94      /** Whether the reload action is enabled. */
95      private boolean reloadActionEnabled;
96  
97      /** Instantiate the model. */
98      public MainFrameModel() {
99          parseTreeTableModel = new ParseTreeTableModel(null);
100     }
101 
102     /**
103      * Set current parse mode.
104      * @param mode ParseMode enum.
105      */
106     public void setParseMode(ParseMode mode) {
107         parseMode = mode;
108     }
109 
110     /**
111      * Get parse tree table model.
112      * @return parse tree table model.
113      */
114     public ParseTreeTableModel getParseTreeTableModel() {
115         return parseTreeTableModel;
116     }
117 
118     /**
119      * Get text to display in a text area.
120      * @return text to display in a text area.
121      */
122     public String getText() {
123         return text;
124     }
125 
126     /**
127      * Returns title for the main frame.
128      * @return title for the main frame.
129      */
130     public String getTitle() {
131         return title;
132     }
133 
134     /**
135      * Returns true if the reload action is enabled, false otherwise.
136      * @return true if the reload action is enabled.
137      */
138     public boolean isReloadActionEnabled() {
139         return reloadActionEnabled;
140     }
141 
142     /**
143      * Whether a file chooser should accept the file as a source file.
144      * @param file the file to check.
145      * @return true if the file should be accepted.
146      */
147     public static boolean shouldAcceptFile(File file) {
148         return file.isDirectory() || file.getName().endsWith(".java");
149     }
150 
151     /**
152      * Get the directory of the last loaded file.
153      * @return directory of the last loaded file.
154      */
155     public File getLastDirectory() {
156         File lastDirectory = null;
157         if (currentFile != null) {
158             lastDirectory = new File(currentFile.getParent());
159         }
160         return lastDirectory;
161     }
162 
163     /**
164      * Get current file.
165      * @return current file.
166      */
167     public File getCurrentFile() {
168         return currentFile;
169     }
170 
171     /**
172      * Get lines to position map.
173      * It returns unmodifiable collection to
174      * prevent additional overhead of copying
175      * and possible state modifications.
176      * @return lines to position map.
177      */
178     public List<Integer> getLinesToPosition() {
179         return new ArrayList<>(linesToPosition);
180     }
181 
182     /**
183      * Open file and load the file.
184      * @param file the file to open.
185      * @throws CheckstyleException if the file can not be parsed.
186      */
187     public void openFile(File file) throws CheckstyleException {
188         if (file != null) {
189             try {
190                 currentFile = file;
191                 title = "Checkstyle GUI : " + file.getName();
192                 reloadActionEnabled = true;
193                 final DetailAST parseTree;
194 
195                 switch (parseMode) {
196                     case PLAIN_JAVA:
197                         parseTree = JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS);
198                         break;
199                     case JAVA_WITH_COMMENTS:
200                     case JAVA_WITH_JAVADOC_AND_COMMENTS:
201                         parseTree = JavaParser.parseFile(file, JavaParser.Options.WITH_COMMENTS);
202                         break;
203                     default:
204                         throw new IllegalArgumentException("Unknown mode: " + parseMode);
205                 }
206 
207                 parseTreeTableModel.setParseTree(parseTree);
208                 parseTreeTableModel.setParseMode(parseMode);
209                 final String[] sourceLines = getFileText(file).toLinesArray();
210 
211                 final List<Integer> linesToPositionTemp = new ArrayList<>();
212                 // starts line counting at 1
213                 linesToPositionTemp.add(0);
214 
215                 final StringBuilder sb = new StringBuilder(1024);
216                 // insert the contents of the file to the text area
217                 for (final String element : sourceLines) {
218                     linesToPositionTemp.add(sb.length());
219                     sb.append(element).append(System.lineSeparator());
220                 }
221                 linesToPosition = linesToPositionTemp;
222                 text = sb.toString();
223             }
224             catch (IOException ex) {
225                 final String exceptionMsg = String.format(Locale.ROOT,
226                     "%s occurred while opening file %s.",
227                     ex.getClass().getSimpleName(), file.getPath());
228                 throw new CheckstyleException(exceptionMsg, ex);
229             }
230         }
231     }
232 
233     /**
234      * Get FileText from a file.
235      * @param file the file to get the FileText from.
236      * @return the FileText.
237      * @throws IOException if the file could not be read.
238      */
239     private static FileText getFileText(File file) throws IOException {
240         return new FileText(file.getAbsoluteFile(),
241                 System.getProperty("file.encoding", StandardCharsets.UTF_8.name()));
242     }
243 
244 }