qic.Main.java Source code

Java tutorial

Introduction

Here is the source code for qic.Main.java

Source

/*
 * Copyright (C) 2015 thirdy
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package qic;

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.joining;
import static org.apache.commons.lang3.StringUtils.substringAfter;
import static qic.Command.Status.ERROR;

import java.awt.Window;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import qic.BlackmarketLanguage.ParseResult;
import qic.Command.Status;
import qic.SearchPageScraper.SearchResultItem;
import qic.ui.QicFrame;
import qic.util.CommandLine;
import qic.util.Config;
import qic.util.SessProp;
import qic.util.Util;

/**
 * TODO, REFACTOR!!!
 * 
 * @author thirdy
 *
 */
public class Main {

    private final static Logger logger = LoggerFactory.getLogger(Main.class.getName());

    public static BlackmarketLanguage language;
    BackendClient backendClient = new BackendClient();
    SessProp sessProp = new SessProp();
    Long searchDuration = null;
    List<String> invalidSearchTerms = null;

    public static void main(String[] args) throws Exception {
        try {
            reloadConfig();
            new Main(args);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "Error occured: " + e.getMessage());
            throw e;
        }
    }

    public static void reloadConfig() throws Exception, FileNotFoundException {
        language = new BlackmarketLanguage();
        Config.loadConfig();
    }

    public static void reloadLookAndFeel() {
        if (Config.getBooleanProperty(Config.LOOK_AND_FEEL_DECORATED, false)) {
            JFrame.setDefaultLookAndFeelDecorated(true);
            JDialog.setDefaultLookAndFeelDecorated(true);
            System.setProperty("sun.awt.noerasebackground", "true");
        }
        try {
            String lookAndFeel = Config.getPropety(Config.LOOK_AND_FEEL,
                    "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            if (lookAndFeel.startsWith("Substance")) {
                lookAndFeel = "org.pushingpixels.substance.api.skin." + lookAndFeel;
            }
            UIManager.setLookAndFeel(lookAndFeel);
        } catch (Exception e) {
            try {
                UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }

        for (Window window : Window.getWindows()) {
            SwingUtilities.updateComponentTreeUI(window);
        }
    }

    public Main(String[] args) throws Exception {
        CommandLine cmd = new CommandLine(args);
        boolean guiEnabled = cmd.hasFlag("-gui");
        guiEnabled = guiEnabled || cmd.getNumberOfArguments() == 0;

        logger.info("guiEnabled: " + guiEnabled);

        if (guiEnabled) {
            showGui(cmd.getArgument(0));
        } else {
            if (cmd.getNumberOfArguments() == 0) {
                throw new IllegalArgumentException(
                        "First arguement needed, and should be the query. e.g. 'search chest 100life 6s5L'. "
                                + "Enclosed in double quoutes if needed.");
            }
            String query = cmd.getArgument(0);
            logger.info("Query: " + query);

            Command command = processLine(query);
            String json = command.toJson();
            writeToFile(json);
        }
    }

    private void showGui(String query) {
        reloadLookAndFeel();
        SwingUtilities.invokeLater(() -> new QicFrame(Main.this, query));
    }

    public void writeToFile(String contents) throws IOException {
        Util.overwriteFile("results.json", contents);
    }

    public Command processLine(String line) throws Exception {
        Command command = new Command(line);
        searchDuration = null;
        invalidSearchTerms = new LinkedList<>();
        try {
            if (line.startsWith("sort") && !sessProp.getLocation().isEmpty()) {
                command.itemResults = runSearch(line, true);
                command.searchDuration = searchDuration;
            } else if (line.startsWith("s ")) {
                String terms = substringAfter(line, "s ").trim();
                if (!terms.isEmpty()) {
                    command.itemResults = runSearch(terms, false);
                    command.searchDuration = searchDuration;
                }
            }
            command.league = sessProp.getLeague();
            command.invalidSearchTerms = invalidSearchTerms;
            command.status = Status.SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            command.status = ERROR;
            command.errorMessage = e.getMessage();
            command.errorStackTrace = ExceptionUtils.getStackTrace(e);
            throw e;
        }
        return command;
    }

    private List<SearchResultItem> runSearch(String terms, boolean sortOnly) throws Exception {
        String html = downloadHtml(terms, sortOnly);
        if (html == null) {
            return Collections.emptyList();
        }
        SearchPageScraper scraper = new SearchPageScraper(html);
        List<SearchResultItem> items = scraper.parse();
        logger.info("items found: " + items.size());
        return items;
    }

    public String downloadHtml(String terms, boolean sortOnly) throws Exception {
        long start = System.currentTimeMillis();

        String regex = "([^\\s]*=\".*?\")";
        List<String> customHttpKeyVals = Util.regexMatches(regex, terms, 1);
        String customHttpKeyVal = customHttpKeyVals.stream().map(s -> StringUtils.remove(s, '"'))
                .collect(Collectors.joining("&"));
        String query = terms.replaceAll(regex, " ");

        ParseResult sortParseResult = language.parseSortToken(query);
        String sort = sortParseResult.result;
        sort = sort == null ? "price_in_chaos" : sort;
        invalidSearchTerms.addAll(sortParseResult.invalidSearchTerms);

        if (!sortOnly) {
            logger.info("Query: " + query);
            ParseResult queryParseResult = language.parse(query);
            String payload = queryParseResult.result;
            invalidSearchTerms.addAll(queryParseResult.invalidSearchTerms);
            if (invalidSearchTerms.isEmpty()) {
                payload = asList(payload, customHttpKeyVal, "capquality=x").stream().filter(StringUtils::isNotBlank)
                        .collect(joining("&"));
                logger.info("Unencoded payload: " + payload);
                payload = asList(payload.split("&")).stream().map(Util::encodeQueryParm).collect(joining("&"));
                String location = submitSearchForm(payload);
                String league = language.parseLeagueToken(query);
                sessProp.setLocation(location);
                sessProp.setLeague(league);
                sessProp.saveToFile();
            }
        }

        String searchPage = null;
        if (invalidSearchTerms.isEmpty()) {
            logger.info("sort: " + sort);
            searchPage = ajaxSort(sort);
        } else {
            logger.info("invalidSearchTerms: " + invalidSearchTerms.toString());
        }

        long end = System.currentTimeMillis();
        long duration = end - start;
        logger.info("Took " + duration + " ms");
        searchDuration = Long.valueOf(duration);
        return searchPage;
    }

    private String ajaxSort(String sort) throws Exception {
        String searchPage = "";
        sort = URLEncoder.encode(sort, "UTF-8");
        sort = "sort=" + sort + "&bare=true";
        searchPage = backendClient.postXMLHttpRequest(sessProp.getLocation(), sort);
        return searchPage;
    }

    private String submitSearchForm(String payload) throws Exception {
        String url = "http://poe.trade/search";
        String location = backendClient.post(url, payload);
        return location;
    }

}