summaryrefslogtreecommitdiff
path: root/src/main/TweetShell.java
blob: c1391ac3f127865bdd1c3ac69cac3b012d163982 (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
package main;

import io.DataWriter;
import io.OAuthRequester;
import io.StreamImpl;
import java.io.IOException;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.Scanner;
import mining.Stream;
import mining.TwitterApi;
import org.json.JSONObject;
import provider.ExceptionListener;
import provider.ResultListener;
import utils.Configuration;

/**
 * Provides an interactive shell where requests can be made and displayed.
 */
public class TweetShell implements TwitterApi.PinSupplier {

    private final Scanner scanner = new Scanner(System.in);

    private TwitterApi api_cached;
    private Stream stream_cached;

    private TwitterApi getApi() throws IOException {
        if (api_cached == null) {
            api_cached = TwitterApi.getOAuth(this);
        }
        return api_cached;
    }

    private Stream getStream() throws IOException {
        if (stream_cached == null) {
            OAuthRequester requester = (OAuthRequester) getApi().getRequester();
            StreamHandler handler = new StreamHandler();
            stream_cached = new StreamImpl(requester);
            StreamImpl streamObserver = (StreamImpl) stream_cached;
            streamObserver.setExceptionListener(handler);
            streamObserver.setResultListener(new StreamHandler());
        }
        return stream_cached;
    }

    private class StreamHandler implements ResultListener, ExceptionListener {

        @Override
        public void exceptionGenerated(Exception ex) {
            System.err.println("Stream closed due to " + ex);
        }

        @Override
        public void tweetGenerated(JSONObject obj) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }

        @Override
        public void profileGenerated(JSONObject obj) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }
    }

    @Override
    public String requestPin(String url) throws IOException {
        System.err.println(url);
        System.err.println("Please open the above URL and enter PIN:");
        return scanner.nextLine();
    }

    private void printPrompt() {
        if (stream_cached == null) {
            System.out.print("$ ");
        } else {
            System.out.print("€ ");
        }
    }

    /**
     * Processes commands from stdin until the exit command is received or EOF.
     */
    public void process_forever() {
        System.err.println("Entering interactive shell, type 'help' for help "
                + "or 'exit' to leave.");
        // print prompt for reading first command
        printPrompt();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            String[] args = line.split("\\s+", 2);
            if (!args[0].isEmpty()) {
                // non-empty command, let's see whether it makes sense?
                if (!execute(args)) {
                    // requested to terminate
                    break;
                }
            }
            // print prompt for reading next line
            printPrompt();
        }
    }

    /**
     * Executes a command with optional parameters.
     *
     * @param args An array with the first argument containing the command with
     * optional parameters in following arguments.
     * @return true if more commands are allowed to be executed, false
     * otherwise.
     */
    public boolean execute(String[] args) {
        try {
            Command command = Command.fromString(args[0]);
            String[] params = Arrays.copyOfRange(args, 1, args.length);
            execute(command, params);
        } catch (IllegalArgumentException ex) {
            System.err.println(ex.getMessage());
        } catch (IOException ex) {
            System.err.println("Command " + args[0] + " failed with " + ex);
            ex.printStackTrace();
        } catch (NoSuchElementException ex) {
            // thrown by the "exit" command to signal exit
            return false;
        }
        // another satisfied customer, next!
        return true;
    }

    enum Command {

        add("Adds a keyword to search", 1),
        del("Deletes a keyword from search", 1),
        commit("Activate the stream or apply the stream keyword changes"),
        close("Close the stream"),
        exit("Returns to shell"),
        help("Get help"),
        target("Set output target: {file, shell}.");

        private final String description;
        private final int paramCount;

        Command(String description) {
            this.description = description;
            this.paramCount = 0;
        }

        Command(String description, int paramCount) {
            this.description = description;
            this.paramCount = paramCount;
        }

        public String getDescription() {
            return description;
        }

        public int getParamCount() {
            return paramCount;
        }

        public static Command fromString(String command) {
            for (Command cmd : values()) {
                if (cmd.name().equals(command)) {
                    return cmd;
                }
            }
            throw new IllegalArgumentException("Unrecognized command. Hint: help");
        }
    };

    private final String[] HELP = new String[]{
        "Interactive TweetShell",
        "",
        "Available commands:"
    };

    private void execute(Command command, String[] params) throws IOException {
        if (params.length < command.getParamCount()) {
            throw new IllegalArgumentException("Expected "
                    + command.getParamCount() + " parameters, got only "
                    + params.length);
        }
        switch (command) {
            case add:
                getStream().watchKeyword(params[0]);
                break;
            case del:
                getStream().unwatchKeyword(params[0]);
                break;
            case commit:
                getStream().commit();
                break;
            case close:
                getStream().close();
                break;
            case help:
                for (String line : HELP) {
                    System.out.println(line);
                }
                for (Command cmd : Command.values()) {
                    System.out.printf("  %-10s", cmd.name());
                    if (!cmd.getDescription().isEmpty()) {
                        System.out.print(" " + cmd.getDescription());
                    }
                    if (cmd.getParamCount() == 1) {
                        System.out.print(" (1 arg)");
                    } else if (cmd.getParamCount() > 1) {
                        System.out.printf(" (%d args)", cmd.getParamCount());
                    }
                    System.out.println();
                }
                break;
            case exit:
                throw new NoSuchElementException();
            case target:
                StreamImpl stream = (StreamImpl) getStream();
                ResultListener oldListener = stream.getResultListener();
                switch (params[0]) {
                    case "file":
                        if (!(oldListener instanceof DataWriter)) {
                            Configuration config = Configuration.getConfig();

                            String profilesFilename = config.getProperty(DataWriter.CFG_PROFILE_FILENAME);
                            String tweetsFilename = config.getProperty(DataWriter.CFG_TWEETS_FILENAME);

                            stream.setResultListener(new DataWriter(profilesFilename, tweetsFilename));

                            // save the changes to the config.
                            config.save();
                        }
                        break;
                    case "shell":
                        if (oldListener instanceof DataWriter) {
                            ((DataWriter) oldListener).close();
                        }
                        if (!(oldListener instanceof StreamHandler)) {
                            stream.setResultListener(new StreamHandler());
                        }
                        break;
                    default:
                        System.err.println("Unrecognized target " + params[0]);
                        break;
                }
                break;
            default:
                throw new AssertionError(command.name());
        }

    }
}