001////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code for adherence to a set of rules.
003// Copyright (C) 2001-2016 the original author or authors.
004//
005// This library is free software; you can redistribute it and/or
006// modify it under the terms of the GNU Lesser General Public
007// License as published by the Free Software Foundation; either
008// version 2.1 of the License, or (at your option) any later version.
009//
010// This library is distributed in the hope that it will be useful,
011// but WITHOUT ANY WARRANTY; without even the implied warranty of
012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013// Lesser General Public License for more details.
014//
015// You should have received a copy of the GNU Lesser General Public
016// License along with this library; if not, write to the Free Software
017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
018////////////////////////////////////////////////////////////////////////////////
019
020package com.puppycrawl.tools.checkstyle.gui;
021
022import java.io.File;
023import java.io.IOException;
024import java.util.ArrayList;
025import java.util.List;
026import java.util.Locale;
027
028import antlr.ANTLRException;
029
030import com.google.common.collect.ImmutableList;
031import com.puppycrawl.tools.checkstyle.TreeWalker;
032import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
033import com.puppycrawl.tools.checkstyle.api.DetailAST;
034import com.puppycrawl.tools.checkstyle.api.FileContents;
035import com.puppycrawl.tools.checkstyle.api.FileText;
036
037/**
038 * Model for checkstyle frame.
039 * @author Vladislav Lisetskiy
040 */
041public class MainFrameModel {
042
043    /** Lines to position map. */
044    private final List<Integer> linesToPosition = new ArrayList<>();
045
046    /** Parse tree model. */
047    private final ParseTreeTableModel parseTreeTableModel;
048
049    /** The file which is being parsed. */
050    private File currentFile;
051
052    /** Text for a frame's text area. */
053    private String text;
054
055    /** Title for the main frame. */
056    private String title = "Checkstyle GUI";
057
058    /** Whether the reload action is enabled. */
059    private boolean reloadActionEnabled;
060
061    /** Instantiate the model. */
062    public MainFrameModel() {
063        parseTreeTableModel = new ParseTreeTableModel(null);
064    }
065
066    /**
067     * Get parse tree table model.
068     * @return parse tree table model.
069     */
070    public ParseTreeTableModel getParseTreeTableModel() {
071        return parseTreeTableModel;
072    }
073
074    /**
075     * Get text to display in a text area.
076     * @return text to display in a text area.
077     */
078    public String getText() {
079        return text;
080    }
081
082    /**
083     * @return title for the main frame.
084     */
085    public String getTitle() {
086        return title;
087    }
088
089    /**
090     * @return true if the reload action is enabled.
091     */
092    public boolean isReloadActionEnabled() {
093        return reloadActionEnabled;
094    }
095
096    /**
097     * Whether a file chooser should accept the file as a source file.
098     * @param file the file to check.
099     * @return true if the file should be accepted.
100     */
101    public static boolean shouldAcceptFile(File file) {
102        return file.isDirectory() || file.getName().endsWith(".java");
103    }
104
105    /**
106     * Get the directory of the last loaded file.
107     * @return directory of the last loaded file.
108     */
109    public File getLastDirectory() {
110        File lastDirectory = null;
111        if (currentFile != null) {
112            lastDirectory = new File(currentFile.getParent());
113        }
114        return lastDirectory;
115    }
116
117    /**
118     * Get current file.
119     * @return current file.
120     */
121    public File getCurrentFile() {
122        return currentFile;
123    }
124
125    /**
126     * Get lines to position map.
127     * @return lines to position map.
128     */
129    public List<Integer> getLinesToPosition() {
130        return ImmutableList.copyOf(linesToPosition);
131    }
132
133    /**
134     * Open file and load the file.
135     * @param file the file to open.
136     * @throws CheckstyleException if the file can not be parsed.
137     */
138    public void openFile(File file) throws CheckstyleException {
139        if (file != null) {
140            try {
141                currentFile = file;
142                title = "Checkstyle GUI : " + file.getName();
143                reloadActionEnabled = true;
144                final DetailAST parseTree = parseFile(file);
145                parseTreeTableModel.setParseTree(parseTree);
146                final String[] sourceLines = getFileText(file).toLinesArray();
147
148                // clear for each new file
149                linesToPosition.clear();
150                // starts line counting at 1
151                linesToPosition.add(0);
152
153                final StringBuilder sb = new StringBuilder();
154                // insert the contents of the file to the text area
155                for (final String element : sourceLines) {
156                    linesToPosition.add(sb.length());
157                    sb.append(element).append(System.lineSeparator());
158                }
159                text = sb.toString();
160            }
161            catch (IOException | ANTLRException ex) {
162                final String exceptionMsg = String.format(Locale.ROOT,
163                    "%s occurred while opening file %s.",
164                    ex.getClass().getSimpleName(), file.getPath());
165                throw new CheckstyleException(exceptionMsg, ex);
166            }
167        }
168    }
169
170    /**
171     * Parse a file and return the parse tree.
172     * @param file the file to parse.
173     * @return the root node of the parse tree.
174     * @throws IOException if the file could not be read.
175     * @throws ANTLRException if the file is not a Java source.
176     */
177    public DetailAST parseFile(File file) throws IOException, ANTLRException {
178        final FileText fileText = getFileText(file);
179        final FileContents contents = new FileContents(fileText);
180        return TreeWalker.parse(contents);
181    }
182
183    /**
184     * Get FileText from a file.
185     * @param file the file to get the FileText from.
186     * @return the FileText.
187     * @throws IOException if the file could not be read.
188     */
189    public FileText getFileText(File file) throws IOException {
190        return new FileText(file.getAbsoluteFile(),
191                System.getProperty("file.encoding", "UTF-8"));
192    }
193}