/** * Copyright (c) 2015 Camil Staps * See the LICENSE file for copying permission. */ package com.camilstaps.shop; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; /** * The Shop database * @author Camil Staps, s4498062 */ public class Database { /** * This is a singleton */ private static Database instance; /** * Keep the database in working memory during runtime */ private Set users; private Set
articles; private Set categories; private Set orders; /** * Files to store the database * Considering backups, it's nicer to have different objects stored in * different files, so that if the Orders file breaks, we still have the * Users, etc. */ private final File FILE_DB = new File("./db"); private final File FILE_USERS = new File("./db/users.db"); private final File FILE_ARTICLES = new File("./db/articles.db"); private final File FILE_CATEGORIES = new File("./db/categories.db"); private final File FILE_ORDERS = new File("./db/orders.db"); /** * Don't use this constructor. This is a singleton: use getInstance() instead. * @see self#getInstance() */ public Database() { if (!FILE_DB.exists()) FILE_DB.mkdir(); readUsers(); readArticles(); readCategories(); readOrders(); } /** * Get an instance of the database. This is a singleton. * @return the database */ public static Database getInstance() { if (instance == null) { instance = new Database(); } return instance; } /** * Add an item to the database * @param item the item * @throws com.camilstaps.shop.DuplicateEntryException * @throws ClassCastException if the item to remove is not a DatabaseItem */ public void addItem(DatabaseItem item) throws DuplicateEntryException { if (item instanceof User) { if (isUserExists(((User) item).getNr())) { throw new DuplicateEntryException(); } users.add((User) item); } else if (item instanceof Article) { if (isArticleExists(((Article) item).getName())) { throw new DuplicateEntryException(); } articles.add((Article) item); } else if (item instanceof Category) { if (isCategoryExists(((Category) item).getName())) { throw new DuplicateEntryException(); } categories.add((Category) item); } else if (item instanceof Order) { orders.add((Order) item); } else { throw new ClassCastException(); } } /** * Remove an item from the database * @param item the item to remove * @throws ClassCastException if the item to remove is not a DatabaseItem */ public void removeItem(DatabaseItem item) { if (item instanceof User) { users.remove((User) item); } else if (item instanceof Article) { articles.remove((Article) item); } else if (item instanceof Category) { categories.remove((Category) item); } else if (item instanceof Order) { orders.remove((Order) item); } else { throw new ClassCastException(); } } /** * Save the database to the filesystem. * @return true on success, false on failure */ public boolean write() { return writeUsers() && writeArticles() && writeCategories() && writeOrders(); } /** * Check if there exists a user with a certain U/S-number * @param nr * @return */ public boolean isUserExists(String nr) { for (User user : users) { if (user.getNr().equals(nr)) { return true; } } return false; } /** * Check if an article with a name exists * @param name * @return */ public boolean isArticleExists(String name) { for (Article article : articles) { if (article.getName().equals(name)) { return true; } } return false; } /** * Check if a category with a name exists * @param name * @return */ public boolean isCategoryExists(String name) { for (Category category : categories) { if (category.getName().equals(name)) { return true; } } return false; } /** * Get the set of users * @return */ public Set getUsers() { return users; } /** * Get the set of articles * @return */ public Set
getArticles() { return articles; } /** * Get the set of categories * @return */ public Set getCategories() { return categories; } /** * Get an array of the names of the categories * @return */ public String[] getCategoryNames() { String[] categoryNames = new String[categories.size()]; int i = 0; for (Category c : categories) { categoryNames[i++] = c.getName(); } return categoryNames; } /** * Get the set of orders * @return */ public Set getOrders() { return orders; } /** * Get the set of articles of which the name or description matches a regular expression * @param p the regular expression * @return */ public Set
searchArticle(Pattern p) { Set
result = new HashSet<>(); for (Article a : articles) { if (p.matcher(a.getName()).find() || p.matcher(a.getDescription()).find()) { result.add(a); } } return result; } /** * Get a user by his number * @param number * @return * @throws com.camilstaps.shop.ItemNotFoundException */ public User getUser(String number) throws ItemNotFoundException { for (User u : users) { if (u.getNr().equals(number)) { return u; } } throw new ItemNotFoundException(); } /** * Get an article by its name * @param name * @return * @throws ItemNotFoundException */ public Article getArticle(String name) throws ItemNotFoundException { for (Article a : articles) { if (a.getName().equals(name)) { return a; } } throw new ItemNotFoundException(); } /** * Get a category by a name * @param name * @return */ public Category getCategory(String name) throws ItemNotFoundException { for (Category c : categories) { if (c.getName().equals(name)) { return c; } } throw new ItemNotFoundException(); } /** * Read the users from the database into RAM */ private void readUsers() { users = new HashSet<>(); try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(FILE_USERS))) { users = (Set) in.readObject(); in.close(); } catch (FileNotFoundException ex) { } catch (IOException | ClassNotFoundException ex) { } } /** * Read the articles from the database into RAM */ private void readArticles() { articles = new HashSet<>(); try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(FILE_ARTICLES))) { articles = (Set) in.readObject(); in.close(); } catch (FileNotFoundException ex) { } catch (IOException | ClassNotFoundException ex) { } } /** * Read the categories from the database into RAM */ private void readCategories() { categories = new HashSet<>(); try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(FILE_CATEGORIES))) { categories = (Set) in.readObject(); in.close(); } catch (FileNotFoundException ex) { } catch (IOException | ClassNotFoundException ex) { } } /** * Read the orders from the database into RAM */ private void readOrders() { orders = new HashSet<>(); try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(FILE_ORDERS))) { orders = (Set) in.readObject(); in.close(); } catch (FileNotFoundException ex) { } catch (IOException | ClassNotFoundException ex) { } } /** * Write the users from RAM to the database */ private boolean writeUsers() { System.err.println("Saving users..."); try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(FILE_USERS))) { out.writeObject(users); out.close(); return true; } catch (IOException ex) { ex.printStackTrace(); } return false; } /** * Write the articles from RAM to the database */ private boolean writeArticles() { System.err.println("Saving articles..."); try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(FILE_ARTICLES))) { out.writeObject(articles); out.close(); return true; } catch (IOException ex) { ex.printStackTrace(); } return false; } /** * Write the categories from RAM to the database */ private boolean writeCategories() { System.err.println("Saving categories..."); try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(FILE_CATEGORIES))) { out.writeObject(categories); out.close(); return true; } catch (IOException ex) { ex.printStackTrace(); } return false; } /** * Write the orders from RAM to the database */ private boolean writeOrders() { System.err.println("Saving orders..."); try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(FILE_ORDERS))) { out.writeObject(orders); out.close(); return true; } catch (IOException ex) { ex.printStackTrace(); } return false; } }