Java tutorial
/* * 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; } }