summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/DirectiveExtractor.java
blob: 0614fcf4306eb45f2eaca0f8c98ed5c5ab9bf354 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/**
 * \cond LICENSE
 * Arara -- the cool TeX automation tool
 * Copyright (c) 2012, Paulo Roberto Massa Cereda
 * All rights reserved.
 *
 * Redistribution and  use in source  and binary forms, with  or without
 * modification, are  permitted provided  that the  following conditions
 * are met:
 *
 * 1. Redistributions  of source  code must  retain the  above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form  must reproduce the above copyright
 * notice, this list  of conditions and the following  disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * 3. Neither  the name  of the  project's author nor  the names  of its
 * contributors may be used to  endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS  PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS
 * "AS IS"  AND ANY  EXPRESS OR IMPLIED  WARRANTIES, INCLUDING,  BUT NOT
 * LIMITED  TO, THE  IMPLIED WARRANTIES  OF MERCHANTABILITY  AND FITNESS
 * FOR  A PARTICULAR  PURPOSE  ARE  DISCLAIMED. IN  NO  EVENT SHALL  THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE  LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY,  OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT  NOT LIMITED  TO, PROCUREMENT  OF SUBSTITUTE  GOODS OR  SERVICES;
 * LOSS  OF USE,  DATA, OR  PROFITS; OR  BUSINESS INTERRUPTION)  HOWEVER
 * CAUSED AND  ON ANY THEORY  OF LIABILITY, WHETHER IN  CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 * WAY  OUT  OF  THE USE  OF  THIS  SOFTWARE,  EVEN  IF ADVISED  OF  THE
 * POSSIBILITY OF SUCH DAMAGE.
 * \endcond
 * 
 * DirectiveExtractor: This class reads the file and extracts all the directives
 * it could find.
 */
// package definition
package com.github.arara.utils;

// needed imports
import com.github.arara.exception.AraraException;
import com.github.arara.model.AraraDirective;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.error.MarkedYAMLException;
import org.yaml.snakeyaml.representer.Representer;

/**
 * Reads the file and extracts all the directives it could find.
 *
 * @author Paulo Roberto Massa Cereda
 * @version 3.0a
 * @since 1.0
 */
public class DirectiveExtractor {

    // the logger
    final static Logger logger = LoggerFactory.getLogger(DirectiveExtractor.class);
    // the list of directives
    private List<AraraDirective> directives;
    // the file
    private File file;
    // the current line number
    private int currentLineNumber;
    // the configuration object
    private ConfigurationLoader configuration;
    // the localization class
    final static AraraLocalization localization = AraraLocalization.getInstance();

    /**
     * Constructor.
     */
    public DirectiveExtractor() {

        // create new list
        directives = new ArrayList<AraraDirective>();

        // set file to null
        file = null;
    }

    /**
     * Constructor.
     *
     * @param file The file.
     */
    public DirectiveExtractor(File file, ConfigurationLoader configuration) {

        // create a new list
        directives = new ArrayList<AraraDirective>();

        this.configuration = configuration;

        // set file
        this.file = file;
    }

    /**
     * Setter for file.
     *
     * @param file The file.
     */
    public void setFile(File file) {

        // set the file
        this.file = file;
    }

    /**
     * Getter for Arara directives.
     *
     * @return A list containing all Arara directives.
     */
    public List<AraraDirective> getDirectives() {

        // return the list
        return directives;
    }

    /**
     * Extracts the directives from the file.
     *
     * @throws FileNotFoundException Raised when file not found.
     * @throws IOException Raised when an IO error happened.
     * @throws AraraException Raised when there's a problem with the directive.
     */
    public void extract() throws FileNotFoundException, IOException, AraraException {
        
        // create a new file reader
        FileReader fileReader = new FileReader(file);

        // create a new buffer
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        
        // variable to hold the current line
        String currentLine;

        // the line count
        currentLineNumber = 0;

        // log directives
        logger.info("Reading directives from {}.", file.getName());

        // while not EOF
        while ((currentLine = bufferedReader.readLine()) != null) {

            // increment the current line number
            currentLineNumber++;
            
            // extract directive
            extractDirective(currentLine);
        }
        
        // close the buffer
        bufferedReader.close();

        // close the reader
        fileReader.close();

    }

    /**
     * Extracts the Arara directives from the current line.
     *
     * @param currentLine The current line.
     * @throws AraraException Raised when there is a problem with the directive.
     */
    private void extractDirective(String currentLine) throws AraraException {
        
        // get the pattern for the chosen filetype
        Pattern linePattern = Pattern.compile(configuration.getChosenFilePattern().getPattern());
        
        // create the matcher according to the pattern
        Matcher matcher = linePattern.matcher(currentLine);
        
        // if the pattern is found
        if (matcher.find()) {

            // get the substring
            currentLine = (currentLine.substring(matcher.end(), currentLine.length())).trim();
            
            // there is actually something after the keyword
            if (!"".equals(currentLine)) {

                // log directive
                logger.trace(localization.getMessage("Log_DirectiveFound", currentLineNumber, currentLine));

                // look for a full directive
                if (AraraUtils.checkForFullDirective(currentLine)) {
                    
                    // add it
                    addAraraDirective(currentLine);
                }
                else {
                    
                    // look for an empty directive
                    if (AraraUtils.checkForEmptyDirective(currentLine)) {
                        
                        // add it
                        addEmptyAraraDirective(currentLine.trim());
                    }
                    else {
                        
                        // an invalid directive was found, throw error
                        throw new AraraException(localization.getMessage("Error_InvalidDirective", currentLineNumber));
                    }
                }
                
            }
        }
    }

    /**
     * Extracts an empty Arara directive.
     *
     * @param currentLine The current line.
     */
    private void addEmptyAraraDirective(String currentLine) {

        // create a new directive
        AraraDirective araraDirective = new AraraDirective();

        // set the name
        araraDirective.setName(currentLine);

        // set the config
        araraDirective.setConfig(new HashMap());

        // set the line number, in case of error
        araraDirective.setLineNumber(currentLineNumber);

        // add the directive to the list
        directives.add(araraDirective);

    }

    /**
     * Extracts am Arara directive.
     *
     * @param currentLine The current line.
     * @throws AraraException Raised when there is a problem with the directive.
     */
    private void addAraraDirective(String currentLine) throws AraraException {

        // lets try
        try {

            // create a new YAML parser
            Yaml yaml = new Yaml(new Constructor(), new Representer(), new DumperOptions(), new AraraResolver());

            // create a new map and load the current line
            Map config = (Map) yaml.load(currentLine);

            // create a new directive
            AraraDirective ad = new AraraDirective();

            // set the name
            ad.setName(currentLine);

            // set the config
            ad.setConfig(config);

            // set line number. in case of error
            ad.setLineNumber(currentLineNumber);

            // add the directive to the list
            directives.add(ad);

        } catch (MarkedYAMLException yamlException) {

            // malformed directive, throw exception
            throw new AraraException(localization.getMessage("Error_InvalidYAMLDirective", currentLineNumber).concat("\n\n").concat(AraraUtils.extractInformationFromYAMLException(yamlException)));
        }
    }
}