public boolean preloadCategories() {
   try {
     logger.log(Level.INFO, "Preloading categories");
     ServerLoader loader = new ServerLoader();
     ServerLoader.Response r = loader.read("CategoriesAPI", "getAll");
     if (r.getStatus().equals(ServerLoader.Response.STATUS_OK)) {
       JSONArray a = r.getArrayContent();
       List<CategoryInfo> categories = new ArrayList<CategoryInfo>();
       for (int i = 0; i < a.length(); i++) {
         JSONObject o = a.getJSONObject(i);
         CategoryInfo cat = new CategoryInfo(o);
         categories.add(cat);
         try {
           if (o.getBoolean("hasImage")) {
             byte[] img = this.loadImage(TYPE_CAT, cat.getID());
             CatalogCache.storeCategoryImage(cat.getID(), img);
           }
         } catch (BasicException e) {
           logger.log(Level.WARNING, "Unable to get category image for " + cat.getID(), e);
         }
       }
       CatalogCache.refreshCategories(categories);
       return true;
     } else {
       return false;
     }
   } catch (Exception e) {
     e.printStackTrace();
     return false;
   }
 }
 public boolean preloadProducts() {
   try {
     logger.log(Level.INFO, "Preloading products");
     ServerLoader loader = new ServerLoader();
     ServerLoader.Response r = loader.read("ProductsAPI", "getAll");
     if (r.getStatus().equals(ServerLoader.Response.STATUS_OK)) {
       JSONArray a = r.getArrayContent();
       List<ProductInfoExt> products = new ArrayList<ProductInfoExt>();
       for (int i = 0; i < a.length(); i++) {
         JSONObject o = a.getJSONObject(i);
         if (!o.getBoolean("visible")) {
           // Don't add products not sold
           continue;
         }
         ProductInfoExt prd = new ProductInfoExt(o);
         products.add(prd);
         try {
           if (o.getBoolean("hasImage")) {
             byte[] img = this.loadImage(TYPE_PRD, prd.getID());
             CatalogCache.storeProductImage(prd.getID(), img);
           }
         } catch (BasicException e) {
           logger.log(Level.WARNING, "Unable to get product image for " + prd.getID(), e);
         }
       }
       CatalogCache.refreshProducts(products);
       return true;
     } else {
       return false;
     }
   } catch (Exception e) {
     e.printStackTrace();
     return false;
   }
 }
 public boolean preloadCompositions() {
   try {
     logger.log(Level.INFO, "Preloading compositions");
     ServerLoader loader = new ServerLoader();
     ServerLoader.Response r = loader.read("CompositionsAPI", "getAll");
     if (r.getStatus().equals(ServerLoader.Response.STATUS_OK)) {
       JSONArray a = r.getArrayContent();
       Map<String, List<SubgroupInfo>> compos = new HashMap<String, List<SubgroupInfo>>();
       Map<Integer, List<String>> groups = new HashMap<Integer, List<String>>();
       for (int i = 0; i < a.length(); i++) {
         JSONObject o = a.getJSONObject(i);
         String prdId = o.getString("id");
         compos.put(prdId, new ArrayList<SubgroupInfo>());
         JSONArray grps = o.getJSONArray("groups");
         for (int j = 0; j < grps.length(); j++) {
           JSONObject oGrp = grps.getJSONObject(j);
           SubgroupInfo subgrp = new SubgroupInfo(oGrp);
           compos.get(prdId).add(subgrp);
           groups.put(subgrp.getID(), new ArrayList<String>());
           JSONArray choices = oGrp.getJSONArray("choices");
           for (int k = 0; k < choices.length(); k++) {
             JSONObject oPrd = choices.getJSONObject(k);
             groups.get(subgrp.getID()).add(oPrd.getString("productId"));
           }
         }
       }
       CatalogCache.refreshSubgroups(compos);
       CatalogCache.refreshSubgroupProds(groups);
       return true;
     } else {
       return false;
     }
   } catch (Exception e) {
     e.printStackTrace();
     return false;
   }
 }
 /** Get products from a category ID. Products must be preloaded. */
 public List<ProductInfoExt> getProductCatalog(String category) throws BasicException {
   return CatalogCache.getProductsByCategory(category);
 }
 public final List<ProductInfoExt> getSubgroupCatalog(Integer subgroup) throws BasicException {
   return CatalogCache.getSubgroupProducts(subgroup);
 }
 public final List<SubgroupInfo> getSubgroups(String composition) throws BasicException {
   return CatalogCache.getSubgroups(composition);
 }
 public final List<CategoryInfo> getCategories() throws BasicException {
   return CatalogCache.getCategories();
 }
 /** Get subcategories from parent ID. Categories must be preloaded. */
 public final List<CategoryInfo> getSubcategories(String category) throws BasicException {
   return CatalogCache.getSubcategories(category);
 }
 public final CategoryInfo getCategory(String id) throws BasicException {
   return CatalogCache.getCategory(id);
 }
 public List<ProductInfoExt> searchProducts(String label, String reference) throws BasicException {
   return CatalogCache.searchProducts(label, reference);
 }
 /** Get a product by code */
 public final ProductInfoExt getProductInfoByCode(String sCode) throws BasicException {
   return CatalogCache.getProductByCode(sCode);
 }
 /** Get a product by ID */
 public final ProductInfoExt getProductInfo(String id) throws BasicException {
   return CatalogCache.getProduct(id);
 }