es.baudlord.pcpartpicker.model.Build.java Source code

Java tutorial

Introduction

Here is the source code for es.baudlord.pcpartpicker.model.Build.java

Source

/*
 * Copyright (c) 2016 Jess "baudlord" Vlez Palacios, Carlos "kauron" Santiago Galindo Jimnez
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * If we meet some day, and you think this stuff is worth it, you can buy me a beer in return.
 */

package es.baudlord.pcpartpicker.model;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.sun.istack.NotNull;
import es.baudlord.pcpartpicker.util.Category;
import es.baudlord.pcpartpicker.util.Coin;
import es.upv.inf.Database;
import es.upv.inf.Product;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.util.*;

import static es.baudlord.pcpartpicker.App.GENERAL_BUNDLE;

/**
 * es.baudlord.pcpartpicker.model (UPV ETSINF)
 * Created by baudlord on 3/27/16.
 */
@XmlRootElement
public class Build implements Serializable {
    private EnumMap<Product.Category, Part.List> build;

    public Build() {
        build = new EnumMap<>(Product.Category.class);
        for (Product.Category category : Product.Category.values()) {
            build.put(category, new Part.List());
        }
    }

    /**
     * Saves the current configuration to the file specified in savePath
     *
     * @param file File to save the build to
     */
    public static void saveTo(@NotNull File file, Build build) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(Build.class, Part.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        jaxbMarshaller.marshal(build, file); // save to a file
    }

    public static Build loadFrom(InputStream is) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(Build.class, Part.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        return (Build) jaxbUnmarshaller.unmarshal(is);
    }

    /**
     * Generate a new Build object from the file specified
     *
     * @param file File to load the build from
     * @return The Build object generated from the file, null if there is any error
     */
    public static Build loadFrom(@NotNull File file) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(Build.class, Part.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        return (Build) jaxbUnmarshaller.unmarshal(file);
    }

    public static Build generate(boolean allParts, int partsPerCategory, boolean randomParts) {
        Build build = new Build();
        Random random = new Random();
        for (Product.Category category : Product.Category.values())
            if (allParts || Category.isMandatory(category)) {
                List list = Database.getProductByCategory(category);
                if (partsPerCategory < 1)
                    partsPerCategory = random.nextInt(list.size()) + 1;
                for (int i = 0; i < partsPerCategory; i++)
                    if (!build.add(new Part(Database.getProductByCategory(category)
                            .get(randomParts ? 0 : random.nextInt(list.size())))))
                        i--;
            }
        return build;
    }

    public static Build generateRandom() {
        return generate(true, 1, true);
    }

    public boolean add(Part part) {
        if (part == null)
            return true;
        ArrayList<Part> list = build.get(part.getCategory()).list;
        int index = list.indexOf(part);
        if (index != -1) {
            int a = part.getAmount();
            if (a == 0)
                a = 1;
            return list.get(index).addAmount(a);
        } else {
            list.add(part);
            return true;
        }
    }

    public void remove(Part part) {
        build.get(part.getCategory()).list.remove(part);
    }

    public void removeAll(Product.Category category) {
        build.get(category).list.clear();
    }

    public ArrayList<Part> getParts(Product.Category category) {
        return build.get(category).list;
    }

    public boolean hasStorage() {
        return !(this.getParts(Product.Category.HDD_SSD).isEmpty()
                && this.getParts(Product.Category.HDD).isEmpty());
    }

    public boolean isComplete() {
        Iterator<Product.Category> i = Category.mandatoryParts();
        while (i.hasNext())
            if (build.get(i.next()).list.isEmpty())
                return false;
        return hasStorage();
    }

    Product.Category nextNeeded() {
        if (isComplete())
            return null;
        Product.Category cat = null;
        for (int i = 0; i < 15; i++) {
            cat = Category.valueOf(i);
            if (build.get(cat).list.isEmpty())
                break;
        }
        return cat;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Build))
            return false;
        for (Product.Category category : Product.Category.values())
            if (!build.get(category).equals(((Build) object).build.get(category)))
                return false;
        return true;
    }

    public PdfPTable createPdfPTable(Font font) throws DocumentException {
        List<PdfPCell> cellList = new ArrayList<>();

        cellList.addAll(Arrays.asList(new PdfPCell(new Phrase(GENERAL_BUNDLE.getString("column.Name"), font)),
                new PdfPCell(new Phrase(GENERAL_BUNDLE.getString("column.UnitPrice"), font)),
                new PdfPCell(new Phrase(GENERAL_BUNDLE.getString("column.Amount"), font)),
                new PdfPCell(new Phrase(GENERAL_BUNDLE.getString("column.Price"), font))));

        for (Product.Category c : Product.Category.values()) {
            ArrayList<Part> parts = getParts(c);
            if (parts.isEmpty())
                continue;

            parts.forEach(product -> cellList
                    .addAll(Arrays.asList(new PdfPCell(new Phrase(product.getDescription(), font)),
                            new PdfPCell(new Phrase(Coin.formatNet(product.getPrice()), font)),
                            new PdfPCell(new Phrase(String.valueOf(product.getAmount()), font)),
                            new PdfPCell(new Phrase(Coin.formatNet(product.getTotalPrice()), font)))));
        }
        PdfPCell line = new PdfPCell(new Phrase(""));
        line.setColspan(4);
        cellList.add(line);

        double totalPrice = this.getTotalPrice();
        font.setSize(font.getSize() + 2);

        PdfPCell total = new PdfPCell(new Phrase(GENERAL_BUNDLE.getString("total.price").toUpperCase(), font));
        total.setColspan(3);
        cellList.addAll(Arrays.asList(total, new PdfPCell(new Phrase(Coin.formatNet(totalPrice), font))));

        PdfPCell totalTax = new PdfPCell(new Phrase(GENERAL_BUNDLE.getString("total.tax").toUpperCase(), font));
        totalTax.setColspan(3);
        cellList.addAll(Arrays.asList(totalTax, new PdfPCell(new Phrase(Coin.formatTax(totalPrice), font))));

        PdfPCell totalPvp = new PdfPCell(new Phrase(GENERAL_BUNDLE.getString("total.pvp").toUpperCase(), font));
        totalPvp.setColspan(3);
        cellList.addAll(Arrays.asList(totalPvp, new PdfPCell(new Phrase(Coin.formatGross(totalPrice), font))));

        PdfPTable table = new PdfPTable(4);
        table.setWidths(new int[] { 50, 10, 5, 10 });
        table.setHeaderRows(1);

        for (int i = 0; i < table.getNumberOfColumns(); i++) {
            cellList.get(i).setBorder(Rectangle.BOTTOM);
            table.addCell(cellList.get(i));
        }
        for (int i = table.getNumberOfColumns(); i < cellList.size() - 6; i++) {
            cellList.get(i).setBorder(0);
            table.addCell(cellList.get(i));
        }
        for (int i = cellList.size() - 6; i < cellList.size() - 4; i++) {
            cellList.get(i).setBorder(Rectangle.TOP);
            table.addCell(cellList.get(i));
        }
        for (int i = cellList.size() - 4; i < cellList.size(); i++) {
            cellList.get(i).setBorder(0);
            table.addCell(cellList.get(i));
        }

        return table;
    }

    public EnumMap<Product.Category, Part.List> getBuild() {
        return build;
    }

    public void setBuild(EnumMap<Product.Category, Part.List> build) {
        this.build = build;
    }

    public double getTotalPrice() {
        double total = 0.0;
        for (Product.Category category : Product.Category.values())
            for (Part part : build.get(category).list)
                total += part.getTotalPrice();
        return total;
    }

    public List<Product.Category> getMissingMandatoryParts() {
        ArrayList<Product.Category> list = new ArrayList<>();
        Category.mandatoryParts().forEachRemaining(category -> {
            if (build.get(category).list.isEmpty())
                list.add(category);
        });
        if (!hasStorage()) {
            list.add(Product.Category.HDD);
            list.add(Product.Category.HDD_SSD);
        }
        return list;
    }
}