net.troja.eve.producersaid.utils.EveCentral.java Source code

Java tutorial

Introduction

Here is the source code for net.troja.eve.producersaid.utils.EveCentral.java

Source

package net.troja.eve.producersaid.utils;

/*
 * ========================================================================
 * Eve Producer's Aid
 * ------------------------------------------------------------------------
 * Copyright (C) 2015 Jens Oberender <j.obi@troja.net>
 * ------------------------------------------------------------------------
 * 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 3 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, see
 * <http://www.gnu.org/licenses/gpl-3.0.html>.
 * ========================================================================
 */

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import net.troja.eve.producersaid.data.EveCentralPrice;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class EveCentral {
    private static final Logger LOGGER = LoggerFactory.getLogger(EveCentral.class);
    private static final String USER_AGENT = "Producer's Aid Java tool - https://github.com/burberius/producersaid - ";
    private static final String BASE_URL = "http://api.eve-central.com/api/marketstat/json?usesystem=30000142";
    private static final String URL_TYPE = "&typeid=";
    // 1 hour
    private static final long CACHE_TIME = 1000L * 60 * 60;
    private static final String NODE_BUY = "buy";
    private static final String NODE_SELL = "sell";
    private static final String NODE_FORQUERY = "forQuery";
    private static final String NODE_MIN = "min";
    private static final String NODE_MAX = "max";
    private static final String NODE_5PERCENT = "fivePercent";
    private static final String NODE_VOLUME = "volume";
    private static final String NODE_GENERATED = "generated";
    private static final String NODE_TYPES = "types";

    private final Map<Integer, EveCentralPrice> priceCache;
    private final ObjectMapper objectMapper = new ObjectMapper();
    private String fileName;

    public EveCentral() {
        priceCache = new HashMap<>();
    }

    public EveCentralPrice getPrice(final int typeId) {
        final Map<Integer, EveCentralPrice> prices = getPrices(Arrays.asList(typeId));
        return prices.get(typeId);
    }

    public Map<Integer, EveCentralPrice> getPrices(final List<Integer> typeIds) {
        final Map<Integer, EveCentralPrice> allPresent = new HashMap<Integer, EveCentralPrice>();
        final List<Integer> downloadIds = new ArrayList<>();
        for (final int typeId : typeIds) {
            final EveCentralPrice price = priceCache.get(typeId);
            if ((price == null) || (price.getTime() < (System.currentTimeMillis() - CACHE_TIME))) {
                downloadIds.add(typeId);
                continue;
            }
            allPresent.put(typeId, price);
        }
        if (!downloadIds.isEmpty()) {
            allPresent.putAll(downloadPrices(downloadIds));
        }
        return allPresent;
    }

    private Map<Integer, EveCentralPrice> downloadPrices(final List<Integer> typeIds) {
        final String urlString = getUrl(typeIds);
        Map<Integer, EveCentralPrice> prices = null;
        try {
            prices = parsePrices(getData(urlString));
            priceCache.putAll(prices);
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("Downloaded " + prices.size() + " prices from Eve Central");
            }
        } catch (final IOException e) {
            if (LOGGER.isErrorEnabled()) {
                LOGGER.error("Could not download eve central prices: " + e.getMessage(), e);
            }
        }
        return prices;
    }

    private String getData(final String url) throws IOException {
        String result = null;
        if (fileName == null) {
            final CloseableHttpClient httpclient = HttpClients.createDefault();
            final HttpGet request = new HttpGet(url);
            try {
                request.setHeader("User-Agent", USER_AGENT);
                final HttpResponse response = httpclient.execute(request);
                final int status = response.getStatusLine().getStatusCode();
                if ((status >= HttpStatus.SC_OK) && (status < HttpStatus.SC_MULTIPLE_CHOICES)) {
                    final HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        result = EntityUtils.toString(entity);
                    }
                } else {
                    throw new IOException(
                            "Download error: " + status + " " + response.getStatusLine().getReasonPhrase());
                }
            } finally {
                request.reset();
                httpclient.close();
            }
        } else {
            result = new String(Files.readAllBytes(Paths.get(fileName)), "UTF-8");
        }
        return result;
    }

    private Map<Integer, EveCentralPrice> parsePrices(final String content) {
        final Map<Integer, EveCentralPrice> map = new ConcurrentHashMap<>();
        try {
            final JsonNode node = objectMapper.readTree(content);
            final Iterator<JsonNode> iter = node.elements();
            while (iter.hasNext()) {
                final EveCentralPrice price = convertToObject(iter.next());
                map.put(price.getTypeId(), price);
            }

        } catch (final IOException e) {
            if (LOGGER.isErrorEnabled()) {
                LOGGER.error("Could not parse data", e);
            }
        }
        return map;
    }

    private EveCentralPrice convertToObject(final JsonNode node) {
        final EveCentralPrice price = new EveCentralPrice();
        final JsonNode buy = node.path(NODE_BUY);
        price.setTypeId(buy.path(NODE_FORQUERY).path(NODE_TYPES).get(0).asInt());
        price.setTime(buy.path(NODE_GENERATED).asLong());
        price.setBuyMax((float) buy.path(NODE_MAX).asDouble());
        price.setBuy5Percent((float) buy.path(NODE_5PERCENT).asDouble());
        price.setBuyVolume(buy.path(NODE_VOLUME).asLong());
        final JsonNode sell = node.path(NODE_SELL);
        price.setSellMin((float) sell.path(NODE_MIN).asDouble());
        price.setSell5Percent((float) sell.path(NODE_5PERCENT).asDouble());
        price.setSellVolume(sell.path(NODE_VOLUME).asLong());
        return price;
    }

    private String getUrl(final List<Integer> typeIds) {
        final StringBuilder url = new StringBuilder(BASE_URL);
        for (final Integer value : typeIds) {
            url.append(URL_TYPE).append(value);
        }
        return url.toString();
    }

    public void setFilename(final String name) {
        fileName = name;
    }

}