1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package vogar;
18
19import java.io.File;
20import java.io.IOException;
21import java.util.Map;
22
23/**
24 * Handles finding actions to perform, given files and classes.
25 */
26public final class ActionFinder {
27    private final Log log;
28    private final Map<String, Action> actions;
29    private final Map<String, Outcome> outcomes;
30
31    public ActionFinder(Log log, Map<String, Action> actions, Map<String, Outcome> outcomes) {
32        this.log = log;
33        this.actions = actions;
34        this.outcomes = outcomes;
35    }
36
37    public void findActions(File file) {
38        findActionsRecursive(file, 0);
39    }
40
41    private void findActionsRecursive(File file, int depth) {
42        if (file.isDirectory()) {
43            int size = actions.size();
44            for (File child : file.listFiles()) {
45                findActionsRecursive(child, depth + 1);
46            }
47            if (depth < 3) {
48                log.verbose("found " + (actions.size() - size) + " actions in " + file);
49            }
50            return;
51        }
52
53        // Don't try to treat this file as a class unless it resembles a .java file
54        if (!matches(file)) {
55            return;
56        }
57
58        try {
59            Action action = fileToAction(file);
60            actions.put(action.getName(), action);
61        } catch (IllegalArgumentException e) {
62            String actionName = Action.nameForJavaFile(file);
63            Action action = new Action(actionName, null, null, null, file);
64            actions.put(actionName, action);
65            outcomes.put(actionName, new Outcome(actionName, Result.UNSUPPORTED, e));
66        }
67    }
68
69    private boolean matches(File file) {
70        return !file.getName().startsWith(".") && file.getName().endsWith(".java");
71    }
72
73    /**
74     * Returns an action for the given .java file.
75     */
76    private Action fileToAction(File javaFile) {
77        try {
78            DotJavaFile dotJavaFile = DotJavaFile.parse(javaFile);
79            File resourcesDir = dotJavaFile.isJtreg() ? javaFile.getParentFile() : null;
80            return new Action(dotJavaFile.getActionName(), dotJavaFile.getClassName(), resourcesDir,
81                    getSourcePath(javaFile, dotJavaFile.getClassName()), javaFile);
82        } catch (IOException e) {
83            throw new RuntimeException(e);
84        }
85    }
86
87    /**
88     * Returns the source path of {@code file}.
89     */
90    private File getSourcePath(File file, String className) {
91        String path = file.getPath();
92        String relativePath = className.replace('.', File.separatorChar) + ".java";
93        if (!path.endsWith(relativePath)) {
94            throw new IllegalArgumentException("Expected a file ending in " + relativePath + " but found " + path);
95        }
96        return new File(path.substring(0, path.length() - relativePath.length()));
97    }
98}
99