3
\$\begingroup\$

I have a small program in Java with GUI, which is showing NBP currency data in specified tabs. It downloads data from www.nbp.pl using XML format and saving it into Apache Derby database using hibernate. I am posting my code here because I want to correct myself in style and, eventually, in efficiency of writing code. I think this code isn't flexible and I can do a lot of things faster and better ( for example i sometime have to repeat myself which DRY principle tells not to do ) but now I'm stuck and don't have idea what to improve.

  • Is WindowCreator class good for handling tabs in one place?
  • Should i remove tab and create new for every update or should i reload the data?
  • In TableCreator when I'm accesing database i have to create for every function entityManagerFactory and entityManager and do everything in transaction. Is it correct or it should be in different way? For example when application is staring create the objects and when closing just close it, but how could i do it? With Spring?

On Win7 & Eclipse IDE program look like this:

Main tab

I have 4 Files:

NbpCurrencyMainWindow.java

package com.dominik.main;

import javax.swing.SwingUtilities;

public class NbpCurrencyMainWindow {

    public static void main(String[] args) {

        SwingUtilities.invokeLater(() -> {
            new WindowCreator();
        });

    }

}

WindowCreator.java

package com.dominik.main;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;

import com.dominik.database.entity.domain.NbpDocument;

public class WindowCreator {
    private JFrame frame;
    private JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.LEFT);
    private JPanel actualCurrencyListTab;
    private List<NbpDocument> documentList = new TableCreator().getAllNbpDocuments();

    final String FRAME_TITLE = "NBP Currency app";

    public WindowCreator() {
        createWindow();
    }

    public void createWindow() {

        frame = new JFrame(FRAME_TITLE);

        TableCreator tableCreator = new TableCreator();
        JPanel currentCurrencyWindow = tableCreator.getCurrencyWindow();
        JPanel currencyCurrencyChart = tableCreator.getChartPanel();

        tabbedPane.add(currentCurrencyWindow);
        tabbedPane.add(currencyCurrencyChart);

        actualCurrencyListTab = getButtonPanel();
        tabbedPane.add(actualCurrencyListTab);

        // setting the size and content of frame
        frame.getContentPane().add(tabbedPane, BorderLayout.CENTER);
        frame.setVisible(true);
        frame.setSize(500, 600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // centering the Jframe
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        frame.setLocation(dim.width / 2 - frame.getSize().width / 2, dim.height / 2 - frame.getSize().height / 2);

        frame.setVisible(true);
    }

    private JPanel getButtonPanel() {
        actualCurrencyListTab = new JPanel();
        actualCurrencyListTab.setName("Przeglądaj kursy");

        // pobieranie daty
        JButton button = new JButton("Pobierz datę");
        JLabel namelabel = new JLabel("Data w formacie yyyy-MM-dd: ", JLabel.LEFT);
        final JTextField userText = new JTextField(6);
        button.addActionListener((e) -> {
            String data = userText.getText();

            // if the data is validate update currencies list tab
            // else just show info
            if (replaceCurrencyTab(data)) {
                replaceCurrenciesListTab();
                tabbedPane.setSelectedIndex(0);
            }
        });

        actualCurrencyListTab.add(namelabel);
        actualCurrencyListTab.add(userText);
        actualCurrencyListTab.add(button, BorderLayout.CENTER);

        // Currencies that are in the db
        JButton showButton = new JButton("Pokaż dla wybranej daty");

        final DefaultListModel<Date> currencyDateList = new DefaultListModel<Date>();

        for (NbpDocument item : documentList) {
            currencyDateList.addElement(item.getNBP_CURRENCY_DATE());
        }

        final JList<Date> currencyList = new JList<Date>(currencyDateList);
        JScrollPane currencyListScrollPane = new JScrollPane(currencyList);

        currencyList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        currencyList.setSelectedIndex(0);
        currencyList.setVisibleRowCount(6);
        // setter for field width
        // currencyList.setFixedCellWidth(350);

        showButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Date data = (Date) currencyList.getSelectedValue();

                replaceCurrencyTab(data.toString());
                tabbedPane.setSelectedIndex(0);
            }
        });

        JSeparator horizonalLine = new JSeparator(SwingConstants.HORIZONTAL);
        horizonalLine.setPreferredSize(new Dimension(500, 3));

        actualCurrencyListTab.add(horizonalLine);
        actualCurrencyListTab.add(currencyListScrollPane);
        actualCurrencyListTab.add(showButton);

        return actualCurrencyListTab;

    }



    /*
     * dowloading currency and replacing first tab (Table of currency values)
     */
    private boolean replaceCurrencyTab(String date) {

        boolean isExist = TableCreator.checkIfDocExists(date);
        if (isExist) {
            TableCreator tableCreator = new TableCreator(date);

            JPanel currentCurrencyWindow = tableCreator.getCurrencyWindow();
            tabbedPane.remove(0);
            tabbedPane.insertTab(currentCurrencyWindow.getName(), null, currentCurrencyWindow, null, 0);


            JPanel currentCharWindow = tableCreator.getChartPanel();
            tabbedPane.remove(1);
            tabbedPane.insertTab(currentCharWindow.getName(), null, currentCharWindow, null, 1);

        } else {
            JOptionPane.showMessageDialog(frame, "Nie znaleziono kursu na podaną datę!");
        }
        return isExist;
    }

    /*
     * re-drawing currencies list tab
     */
    private void replaceCurrenciesListTab() {
        tabbedPane.remove(2);
        actualCurrencyListTab = getButtonPanel();
        tabbedPane.insertTab(actualCurrencyListTab.getName(), null, actualCurrencyListTab, null, 2);
    }
}

TableCreator.java

package com.dominik.main;

import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import com.dominik.database.entity.domain.NbpDocument;
import com.dominik.database.entity.domain.NbpDocumentItem;

/**
 * Creates the Jtable and fills with the input data
 * 
 * @author Dominik
 */
public class TableCreator {
    private Object[][] data;
    private String currencyDate;
    private Document doc;
    private static EntityManagerFactory entityManagerFactory;
    private static EntityManager entityManager;
    private JPanel panel;

    public TableCreator() {
        this.currencyDate = lastCurrencyDay();
        List<NbpDocumentItem> items = new ArrayList<NbpDocumentItem>();
        items = getDocForSelectedDatainDatabase();
        if (items == null) {
            this.doc = init(this.currencyDate);
            parseXml();
        } else {
            getItemsFromDatabaseToDataModel(items);
        }
    }

    public TableCreator(String selectedCurrencyDate) {

        this.currencyDate = selectedCurrencyDate;

        // if doesnt exist download the currency of selected date
        List<NbpDocumentItem> items = new ArrayList<NbpDocumentItem>();
        items = getDocForSelectedDatainDatabase();
        if (items == null) {
            this.doc = init(selectedCurrencyDate);
            parseXml();
        } else {
            getItemsFromDatabaseToDataModel(items);
        }
    }

    private List<NbpDocumentItem> getDocForSelectedDatainDatabase() {
        List<NbpDocument> resultList = new ArrayList<NbpDocument>();
        entityManagerFactory = Persistence.createEntityManagerFactory("myDatabase");
        entityManager = entityManagerFactory.createEntityManager();

        entityManager.getTransaction().begin();

        TypedQuery<NbpDocument> query = entityManager.createQuery(
                "select n from NbpDocument n where n.NBP_CURRENCY_DATE = :currencyDate", NbpDocument.class);

        Date date = parseDateFromString(this.currencyDate);
        query.setParameter("currencyDate", date);
        resultList = query.getResultList();

        entityManager.getTransaction().commit();
        entityManager.close();
        entityManagerFactory.close();

        if (resultList.isEmpty()) {
            return null;
        } else {
            NbpDocument document = resultList.get(0);
            List<NbpDocumentItem> items = document.getNbpDocumentItems();
            return items;
        }
    }

    public List<NbpDocument> getAllNbpDocuments() {
        List<NbpDocument> tempArray = new ArrayList<NbpDocument>();
        entityManagerFactory = Persistence.createEntityManagerFactory("myDatabase");
        entityManager = entityManagerFactory.createEntityManager();

        entityManager.getTransaction().begin();
        TypedQuery<NbpDocument> query = entityManager.createQuery("select n from NbpDocument n", NbpDocument.class);

        tempArray = query.getResultList();
        entityManager.getTransaction().commit();

        entityManager.close();
        entityManagerFactory.close();

        return tempArray;
    }

    private String lastCurrencyDay() {
        String nbpCurrencyUrl = "http://api.nbp.pl/api/exchangerates/tables/a/?format=xml";

        String currencyXml = getURLContent(nbpCurrencyUrl);
        Document tempDoc = null;
        try {
            tempDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
                    .parse(new InputSource(new StringReader(currencyXml)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        String currencyDate = tempDoc.getElementsByTagName("EffectiveDate").item(0).getTextContent();

        return currencyDate;
    }

    private Document init(String selectedCurrencyDate) {
        String nbpCurrencyUrl = "http://api.nbp.pl/api/exchangerates/tables/a/" + selectedCurrencyDate + "/?format=xml";
        String currencyXml = getURLContent(nbpCurrencyUrl);
        Document doc = null;

        try {
            doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
                    .parse(new InputSource(new StringReader(currencyXml)));

        } catch (Exception e) {
            e.printStackTrace();

        }

        return doc;
    }

    public static boolean checkIfDocExists(String date) {
        return getURLContent("http://api.nbp.pl/api/exchangerates/tables/a/" + date + "/?format=xml") == null ? false
                : true;
    }

    private static String getURLContent(String p_sURL) {
        URL oURL;
        URLConnection oConnection;
        BufferedReader oReader;
        String sLine;
        StringBuilder sbResponse;
        String sResponse = null;

        try {
            oURL = new URL(p_sURL);
            oConnection = oURL.openConnection();
            oReader = new BufferedReader(new InputStreamReader(oConnection.getInputStream(), StandardCharsets.UTF_8));
            sbResponse = new StringBuilder();

            while ((sLine = oReader.readLine()) != null) {
                sbResponse.append(sLine);
            }

            sResponse = sbResponse.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return sResponse;
    }

    public void parseXml() {

        int currencyLength = this.doc.getElementsByTagName("Currency").getLength();
        this.data = new Object[currencyLength][3];
        for (int index = 0; index < currencyLength; index++) {
            this.data[index][0] = doc.getElementsByTagName("Currency").item(index).getTextContent();
            this.data[index][1] = doc.getElementsByTagName("Code").item(index).getTextContent();
            this.data[index][2] = doc.getElementsByTagName("Mid").item(index).getTextContent();
        }
        addItemstoDatabase();
    }

    public void getItemsFromDatabaseToDataModel(List<NbpDocumentItem> items) {

        int length = items.size();

        this.data = new Object[length][3];
        for (int index = 0; index < length; index++) {
            this.data[index][0] = items.get(index).getCurrencyName();
            this.data[index][1] = items.get(index).getCurrencyCode();
            this.data[index][2] = items.get(index).getCurrencyValue();
        }

    }

    private void addItemstoDatabase() {
        List<NbpDocumentItem> itemData = new ArrayList<NbpDocumentItem>();

        Date currencyDate = parseDateFromString(this.currencyDate);

        entityManagerFactory = Persistence.createEntityManagerFactory("myDatabase");
        entityManager = entityManagerFactory.createEntityManager();
        NbpDocument nbpDocument = new NbpDocument();
        nbpDocument.setNBP_CURRENCY_DATE(currencyDate);

        itemData = getItemList();
        nbpDocument.setNbpDocumentItems(itemData);

        entityManager.getTransaction().begin();
        entityManager.persist(nbpDocument);
        entityManager.getTransaction().commit();

        entityManager.close();
        entityManagerFactory.close();
    }

    private ArrayList<NbpDocumentItem> getItemList() {
        ArrayList<NbpDocumentItem> ids = new ArrayList<NbpDocumentItem>();

        int currencyLength = doc.getElementsByTagName("Currency").getLength();
        for (int index = 0; index < currencyLength; index++) {
            String nazwaWaluty = doc.getElementsByTagName("Currency").item(index).getTextContent();
            String kodWaluty = doc.getElementsByTagName("Code").item(index).getTextContent();
            BigDecimal kurs = new BigDecimal(
                    doc.getElementsByTagName("Mid").item(index).getTextContent().replaceAll(",", "."));

            NbpDocumentItem nbpDocumentItem = new NbpDocumentItem();
            nbpDocumentItem.setCurrencyCode(kodWaluty);
            nbpDocumentItem.setCurrencyName(nazwaWaluty);
            nbpDocumentItem.setCurrencyValue(kurs);

            ids.add(nbpDocumentItem);
        }

        return ids;
    }

    public JPanel getCurrencyWindow() {
        if (data.equals(null)) {
            return null;
        }

        panel = new JPanel();
        panel.setName("<html>Kurs walut<br> " + currencyDate + "</html>");
        panel.setLayout(new BorderLayout());

        String[] columns = new String[] { "Waluta", "Kod waluty", "Kurs" };

        DefaultTableModel model = new DefaultTableModel(data, columns) {
            private static final long serialVersionUID = 2731697622531071294L;

            // Currency data shouldn't be editable
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        JTable table = new JTable(model);
        JScrollPane tableContainer = new JScrollPane(table);

        panel.add(tableContainer, BorderLayout.CENTER);

        return panel;
    }

    private Date parseDateFromString(String date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date convertedCurrentDate = null;
        try {
            convertedCurrentDate = sdf.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return convertedCurrentDate;
    }

    public String getCurrencyDate() {
        return currencyDate;
    }

    public JPanel getChartPanel() {
        return new ChartPanelCreator(data).getChartPanel();
    }

}

ChartPanelCreator.java

package com.dominik.main;

import java.awt.BorderLayout;
import java.awt.Font;
import java.math.BigDecimal;

import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;

public class ChartPanelCreator {

    /**
     * 
     */
    private String CHART_TITLE = "Wykres waluty";
    private Font font3 = new Font("Dialog", Font.PLAIN, 65);

    private Object[][] data;

    public ChartPanelCreator(Object[][] data) {
        this.data = data;
    }

    public JPanel getChartPanel() {
        JFreeChart lineChart = ChartFactory.createLineChart(CHART_TITLE, "Wartość", "Kod waluty", createDataset(),
                PlotOrientation.VERTICAL, true, true, false);

        ChartPanel chartPanel = new ChartPanel(lineChart);
        chartPanel.setName(CHART_TITLE);
        chartPanel.setFont(font3);
        chartPanel.setMouseZoomable(true);
        chartPanel.setLayout(new BorderLayout());

        // avioding axis label and legend scaling
        // http://www.jfree.org/forum/viewtopic.php?f=3&t=117097
        chartPanel.setMinimumDrawHeight(50);
        chartPanel.setMaximumDrawHeight(5000);

        chartPanel.setMinimumDrawWidth(50);
        chartPanel.setMaximumDrawWidth(5000);

        return chartPanel;
    }

    private DefaultCategoryDataset createDataset() {
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        BigDecimal value = new BigDecimal(0);
        String code = null;
        Object objValue = null;

        for (Object[] item : data) {
            code = ((String) item[1]).toLowerCase();

            objValue = item[2];
            if (objValue instanceof BigDecimal) {
                value = (BigDecimal) item[2];
            } else {
                value = new BigDecimal((String) item[2]);
            }

            dataset.addValue(value.doubleValue(), "wartość", code);
        }

        return dataset;
    }

}
\$\endgroup\$
  • \$\begingroup\$ There is Java NBP API available: Java NBP API \$\endgroup\$ – Peter Dec 2 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.