Trauma averted - beans migrated
This commit is contained in:
		
							parent
							
								
									851658a356
								
							
						
					
					
						commit
						4bcf8b911f
					
				
							
								
								
									
										208
									
								
								src/main/java/com/mousetech/gourmetj/AdminMainBean.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								src/main/java/com/mousetech/gourmetj/AdminMainBean.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,208 @@
 | 
				
			||||||
 | 
					package com.mousetech.gourmetj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.Serializable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.annotation.PostConstruct;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.faces.model.DataModel;
 | 
				
			||||||
 | 
					import javax.faces.model.ListDataModel;
 | 
				
			||||||
 | 
					import javax.faces.view.ViewScoped;
 | 
				
			||||||
 | 
					import javax.inject.Inject;
 | 
				
			||||||
 | 
					import javax.inject.Named;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
 | 
					import org.slf4j.LoggerFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.UserSession;
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.model.Category;
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.model.Recipe;
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.service.RecipeService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Main control panel backing bean.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @author timh
 | 
				
			||||||
 | 
					 * @since Jun 28, 2012
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Named
 | 
				
			||||||
 | 
					@ViewScoped
 | 
				
			||||||
 | 
					public class AdminMainBean implements Serializable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private static final long serialVersionUID = 2L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public AdminMainBean() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Logger */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  private static final Logger log = LoggerFactory.getLogger(AdminMainBean.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Persistency service for Recipes
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Inject
 | 
				
			||||||
 | 
						transient RecipeService recipeService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public void setRecipeService(RecipeService service) {
 | 
				
			||||||
 | 
							log.debug("INJECT RECIPESERVICE===" + service);
 | 
				
			||||||
 | 
							this.recipeService = service;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// **
 | 
				
			||||||
 | 
						@Inject
 | 
				
			||||||
 | 
						private UserSession userSession;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return the userSession
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public UserSession getUserSession() {
 | 
				
			||||||
 | 
							return userSession;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param userSession the userSession to set
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setUserSession(UserSession userSession) {
 | 
				
			||||||
 | 
							this.userSession = userSession;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// **
 | 
				
			||||||
 | 
						private String searchText;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return the searchText
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String getSearchText() {
 | 
				
			||||||
 | 
							if (this.searchResults == null) {
 | 
				
			||||||
 | 
								// Fake around broken @PostConstruct
 | 
				
			||||||
 | 
								this.setSearchText(userSession.getLastSearch());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return searchText;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param searchText the searchText to set
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setSearchText(String searchText) {
 | 
				
			||||||
 | 
							this.searchText = searchText;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**/
 | 
				
			||||||
 | 
						transient DataModel<Recipe> searchResults;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return the searchResults
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public DataModel<Recipe> getSearchResults() {
 | 
				
			||||||
 | 
							if (searchResults == null) {
 | 
				
			||||||
 | 
								searchResults = new ListDataModel<Recipe>();
 | 
				
			||||||
 | 
								init(); // @PostConstruct is broken
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return searchResults;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param searchResults the searchResults to set
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setSearchResults(
 | 
				
			||||||
 | 
								DataModel<Recipe> searchResults) {
 | 
				
			||||||
 | 
							this.searchResults = searchResults;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Return to last search, if any
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						@PostConstruct
 | 
				
			||||||
 | 
						void init() {
 | 
				
			||||||
 | 
							this.setSearchText(userSession.getLastSearch());
 | 
				
			||||||
 | 
							// Clean up from any previous operations.
 | 
				
			||||||
 | 
							this.userSession.setRecipe(null);
 | 
				
			||||||
 | 
							doFind();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Finder
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @return Navigation string
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String doFind() {
 | 
				
			||||||
 | 
							List<Recipe> recipes =
 | 
				
			||||||
 | 
									recipeService.findByTitle(searchText);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							getSearchResults().setWrappedData(recipes);
 | 
				
			||||||
 | 
							this.userSession.setLastSearch(this.getSearchText());
 | 
				
			||||||
 | 
							return null; // Stay on page
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Prep to create a new recipe
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @return navigation to detailEdit page
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String doNewRecipe() {
 | 
				
			||||||
 | 
							// Clear for new recipe
 | 
				
			||||||
 | 
							this.userSession.setLastEdit(null);
 | 
				
			||||||
 | 
							// Construct a blank recipe to be created.
 | 
				
			||||||
 | 
							this.userSession.setRecipe(new Recipe());
 | 
				
			||||||
 | 
							return "detailEdit?faces-redirect=true";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Show selected recipe
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String showRecipe() {
 | 
				
			||||||
 | 
							long recipeId = getSearchResults().getRowData().getId();
 | 
				
			||||||
 | 
							JSFUtils.flashScope().put("recipeID",
 | 
				
			||||||
 | 
								Long.valueOf(recipeId));
 | 
				
			||||||
 | 
							userSession.setLastEdit(recipeId);
 | 
				
			||||||
 | 
							userSession.setRecipe(null); // forces loading of line
 | 
				
			||||||
 | 
															// items.
 | 
				
			||||||
 | 
							return "recipeDetails?faces-redirect=true";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Get printable preptime. Database version is in seconds.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @return Formatted time. Called from EL on main page.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String formatPreptime(int timesec) {
 | 
				
			||||||
 | 
							StringBuffer sb = new StringBuffer(20);
 | 
				
			||||||
 | 
							int preptime = timesec / 60;
 | 
				
			||||||
 | 
							if (preptime > 60) {
 | 
				
			||||||
 | 
								int hours = preptime / 60;
 | 
				
			||||||
 | 
								sb.append(hours);
 | 
				
			||||||
 | 
								sb.append(" h. ");
 | 
				
			||||||
 | 
								preptime %= 60;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (preptime > 0) {
 | 
				
			||||||
 | 
								sb.append(preptime);
 | 
				
			||||||
 | 
								sb.append(" min.");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return sb.toString();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public String formatCategories(Recipe r) {
 | 
				
			||||||
 | 
							StringBuffer sb = new StringBuffer(30);
 | 
				
			||||||
 | 
							boolean first = true;
 | 
				
			||||||
 | 
							for (Category cat : r.getCategories()) {
 | 
				
			||||||
 | 
								if (first) {
 | 
				
			||||||
 | 
									first = false;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									sb.append(", ");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								sb.append(cat.getCategory());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return sb.toString();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										49
									
								
								src/main/java/com/mousetech/gourmetj/CuisineBean.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/main/java/com/mousetech/gourmetj/CuisineBean.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Copyright (C) 2021, Tim Holloway
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Date written: Dec 7, 2021
 | 
				
			||||||
 | 
					 * Author: Tim Holloway <timh@mousetech.com>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					package com.mousetech.gourmetj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.enterprise.context.ApplicationScoped;
 | 
				
			||||||
 | 
					import javax.inject.Inject;
 | 
				
			||||||
 | 
					import javax.inject.Named;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.service.RecipeService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @author timh
 | 
				
			||||||
 | 
					 * @since Dec 7, 2021
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Named
 | 
				
			||||||
 | 
					@ApplicationScoped
 | 
				
			||||||
 | 
					public class CuisineBean {
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						@Inject
 | 
				
			||||||
 | 
						private RecipeService recipeService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private List<String> cuisineList;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Return list of cuisines currently on file. Create it if
 | 
				
			||||||
 | 
						 * needed.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public List<String> getCuisineList() {
 | 
				
			||||||
 | 
							if (this.cuisineList == null ) {
 | 
				
			||||||
 | 
								this.cuisineList = loadCuisineList();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return this.cuisineList;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						private synchronized List<String> loadCuisineList() {
 | 
				
			||||||
 | 
							List<String> list = this.recipeService.findCuisines();
 | 
				
			||||||
 | 
							return list;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public synchronized void registerCuisine(String cuisineString) {
 | 
				
			||||||
 | 
							// search in-memory list. Add if needed.
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										332
									
								
								src/main/java/com/mousetech/gourmetj/IngredientDigester.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								src/main/java/com/mousetech/gourmetj/IngredientDigester.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,332 @@
 | 
				
			||||||
 | 
					package com.mousetech.gourmetj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.text.DecimalFormat;
 | 
				
			||||||
 | 
					import java.util.regex.Matcher;
 | 
				
			||||||
 | 
					import java.util.regex.Pattern;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.model.Ingredient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Service for taking an ingredients line, parsing it and
 | 
				
			||||||
 | 
					 * returning a populated Ingredients object. Understands fraction
 | 
				
			||||||
 | 
					 * characters in the amounts fields.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @author timh
 | 
				
			||||||
 | 
					 * @since Dec 1, 2021 TestedBy @see IngredientDigesterTest
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class IngredientDigester {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @author timh
 | 
				
			||||||
 | 
						 * @since Dec 5, 2021
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public enum IngredientAmountFormat {
 | 
				
			||||||
 | 
							IA_DECIMAL, // 5.75
 | 
				
			||||||
 | 
							IA_TEXT, // 5 3/4
 | 
				
			||||||
 | 
							IA_SYMBOLS, // 5¾
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						final static String amountPatternTxt =
 | 
				
			||||||
 | 
								"([0-9¼⅓½⅔¾⅛⅜⅝⅞][\\s\\-\\.]*[/0-9¼⅓½⅔¾⅛⅜⅝⅞]*)";
 | 
				
			||||||
 | 
						final static Pattern amountPattern =
 | 
				
			||||||
 | 
								Pattern.compile(amountPatternTxt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						final static Pattern fractionPattern =
 | 
				
			||||||
 | 
								Pattern.compile("(\\d*)[\\s\\-]*(\\d+)/(\\d+)");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Digest an ingredient text line and construct an Ingredient
 | 
				
			||||||
 | 
						 * object
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param inputText Input text line
 | 
				
			||||||
 | 
						 * @return Ingredient
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static Ingredient digest(String inputText) {
 | 
				
			||||||
 | 
							inputText = inputText.trim();
 | 
				
			||||||
 | 
							final boolean optional =
 | 
				
			||||||
 | 
									inputText.toLowerCase().contains("optional");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Ingredient ing = new Ingredient();
 | 
				
			||||||
 | 
							ing.setAmount(0.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Split for amount, unit and rest of string.
 | 
				
			||||||
 | 
							String[] pamt = parseFancyNumber(inputText);
 | 
				
			||||||
 | 
							if (pamt == null) {
 | 
				
			||||||
 | 
								// Can't parse
 | 
				
			||||||
 | 
								ing.setAmount(null);
 | 
				
			||||||
 | 
								ing.setUnit(null);
 | 
				
			||||||
 | 
								ing.setItem(inputText);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								final Double[] amount = digestAmount(pamt[0]);
 | 
				
			||||||
 | 
								ing.setAmount(amount[0]);
 | 
				
			||||||
 | 
								ing.setRangeamount(amount[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								String[] unext = pamt[1].split("\\s", 2);
 | 
				
			||||||
 | 
								switch (unext.length) {
 | 
				
			||||||
 | 
								case 1:
 | 
				
			||||||
 | 
									ing.setUnit(null);
 | 
				
			||||||
 | 
									ing.setItem(unext[0]);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case 2:
 | 
				
			||||||
 | 
									ing.setUnit(unext[0]);
 | 
				
			||||||
 | 
									ing.setItem(unext[1]);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ing.setPosition(null);
 | 
				
			||||||
 | 
							ing.setOptional(optional ? 1 : 0);
 | 
				
			||||||
 | 
							// Extract the item type from the item name
 | 
				
			||||||
 | 
							// Assume possible prep details ("parsley, chopped")
 | 
				
			||||||
 | 
							String istring = ing.getItem();
 | 
				
			||||||
 | 
							String iclass = istring.split("\\s*,",2)[0];
 | 
				
			||||||
 | 
							ing.setIngkey(iclass);
 | 
				
			||||||
 | 
							return ing;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Break down ingredients line into 2 parts. First part is
 | 
				
			||||||
 | 
						 * numeric text representing amount and optional range,
 | 
				
			||||||
 | 
						 * second part is text remainder, including units.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param instring String to parse
 | 
				
			||||||
 | 
						 * @return 2-dimensional String array with amount and
 | 
				
			||||||
 | 
						 *         remainder or <code>null</code> if instring does
 | 
				
			||||||
 | 
						 *         not parse.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						static String[] parseFancyNumber(String instring) {
 | 
				
			||||||
 | 
							Matcher m = amountPattern.matcher(instring);
 | 
				
			||||||
 | 
							if (m.find()) {
 | 
				
			||||||
 | 
								// System.out.println("GROUPS=" + m.groupCount());
 | 
				
			||||||
 | 
								String rs = m.group(1);
 | 
				
			||||||
 | 
								return new String[] { rs.trim(),
 | 
				
			||||||
 | 
										instring.substring(m.end()).trim() };
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: Remove "optional", if present, including
 | 
				
			||||||
 | 
						// brackets/parentheses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Convert instring into a number with optional fractions.
 | 
				
			||||||
 | 
						 * Can take decimals, unicode ratio characters, and n/m form
 | 
				
			||||||
 | 
						 * with embedded spaces and dashes.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param instring String to analyze
 | 
				
			||||||
 | 
						 * @return number equivalent pair. Note that thirds are not
 | 
				
			||||||
 | 
						 *         precise in binary floating-point! First element is
 | 
				
			||||||
 | 
						 *         low range amount. Second element is null unless a
 | 
				
			||||||
 | 
						 *         high range was given as well.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static Double[] digestAmount(String instring) {
 | 
				
			||||||
 | 
							String[] amtParts = instring.split("\\s*-\\s*");
 | 
				
			||||||
 | 
							Double[] result = new Double[2];
 | 
				
			||||||
 | 
							result[0] = parseSingleAmount(amtParts[0]);
 | 
				
			||||||
 | 
							if (amtParts.length == 1) {
 | 
				
			||||||
 | 
								return result;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// dash separates low, high values OR integer and a
 | 
				
			||||||
 | 
							// fraction.
 | 
				
			||||||
 | 
							result[1] = parseSingleAmount(amtParts[1]);
 | 
				
			||||||
 | 
							if (result[1] < result[0]) {
 | 
				
			||||||
 | 
								result[0] += result[1];
 | 
				
			||||||
 | 
								result[1] = 0.0d;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Parse a single amount. May be integer, decimal number,
 | 
				
			||||||
 | 
						 * integer + fraction character or [integer] integer /
 | 
				
			||||||
 | 
						 * integer.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param instring amount string to parse
 | 
				
			||||||
 | 
						 * @return parsed value.
 | 
				
			||||||
 | 
						 * @throws NumberFormatException if bad decimal value given.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						static Double parseSingleAmount(String instring) {
 | 
				
			||||||
 | 
							double value = 0;
 | 
				
			||||||
 | 
							double frac = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (instring.contains("/")) {
 | 
				
			||||||
 | 
								// Break down a/b fraction
 | 
				
			||||||
 | 
								frac = digestFraction(instring);
 | 
				
			||||||
 | 
								return frac;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (instring.contains(".")) {
 | 
				
			||||||
 | 
								frac = Double.valueOf(instring);
 | 
				
			||||||
 | 
								return frac;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Look for integer and possibly a symbol;
 | 
				
			||||||
 | 
							for (int i = 0; i < instring.length(); i++) {
 | 
				
			||||||
 | 
								final Character ch = instring.charAt(i);
 | 
				
			||||||
 | 
								switch (ch) {
 | 
				
			||||||
 | 
								case '⅛':
 | 
				
			||||||
 | 
									frac = 0.125d;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case '⅓':
 | 
				
			||||||
 | 
									frac = 1.0 / 3.0;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case '¼':
 | 
				
			||||||
 | 
									frac = 0.25d;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case '⅜':
 | 
				
			||||||
 | 
									frac = 3.0 * 0.125d;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case '½':
 | 
				
			||||||
 | 
									frac = 0.5d;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case '⅝':
 | 
				
			||||||
 | 
									frac = 5.0 * 0.125d;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case '⅔':
 | 
				
			||||||
 | 
									frac = 2.0 / 3.0;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case '⅞':
 | 
				
			||||||
 | 
									frac = 7.0 * 0.125d;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									if (Character.isDigit(ch)) {
 | 
				
			||||||
 | 
										value = value * 10.0 + (ch - '0');
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									// Ignore spaces, dashes, etc.
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							value += frac;
 | 
				
			||||||
 | 
							return value;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Pull fraction from tail-end of string and evaluate it.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param instring String in the form dddxxxddd/ddd, where d
 | 
				
			||||||
 | 
						 *                 is digit, x is dash or space (optional)
 | 
				
			||||||
 | 
						 * @return results of evaluation. May need to throw
 | 
				
			||||||
 | 
						 *         Exception???
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						static double digestFraction(String instring) {
 | 
				
			||||||
 | 
							Matcher m = fractionPattern.matcher(instring);
 | 
				
			||||||
 | 
							if (!m.find()) {
 | 
				
			||||||
 | 
								return 0.0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							String lead = m.group(1);
 | 
				
			||||||
 | 
							String snumerator = m.group(2);
 | 
				
			||||||
 | 
							String sdenominator = m.group(3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							double numerator;
 | 
				
			||||||
 | 
							double denominator;
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								numerator = Double.parseDouble(snumerator);
 | 
				
			||||||
 | 
								denominator = Double.parseDouble(sdenominator);
 | 
				
			||||||
 | 
							} catch (NumberFormatException e) {
 | 
				
			||||||
 | 
								// TODO Auto-generated catch block
 | 
				
			||||||
 | 
								e.printStackTrace();
 | 
				
			||||||
 | 
								return 0.0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (denominator == 0.0d) {
 | 
				
			||||||
 | 
								return 0.0d;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							double result = numerator / denominator;
 | 
				
			||||||
 | 
							if (!lead.isEmpty()) {
 | 
				
			||||||
 | 
								result += Double.valueOf(lead); // integral part
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Convert floating-point amounts to display-friendly form.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param format Amount formatting scheme
 | 
				
			||||||
 | 
						 * @param amt    Amount to display
 | 
				
			||||||
 | 
						 * @param ext    amount range high value (can be null)
 | 
				
			||||||
 | 
						 * @return Displayable String. Zero returns an empty string.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static String displayAmount(
 | 
				
			||||||
 | 
								IngredientAmountFormat format, Double amt,
 | 
				
			||||||
 | 
								Double ext) {
 | 
				
			||||||
 | 
							if (amt == 0.0d) {
 | 
				
			||||||
 | 
								return "";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							String amountRange = displayAmountPart(format, amt);
 | 
				
			||||||
 | 
							if (ext != null) {
 | 
				
			||||||
 | 
								amountRange += "-" + displayAmountPart(format, ext);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return amountRange;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param format
 | 
				
			||||||
 | 
						 * @param amt    Amount to format
 | 
				
			||||||
 | 
						 * @return Amount formatted in decimal, text, or text/symbol.
 | 
				
			||||||
 | 
						 *         Values that don't conform to the common fractions
 | 
				
			||||||
 | 
						 *         report as decimal values. Returns empty string for
 | 
				
			||||||
 | 
						 *         0.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						static String displayAmountPart(
 | 
				
			||||||
 | 
								IngredientAmountFormat format, Double amt) {
 | 
				
			||||||
 | 
							if (amt == 0.0d) {
 | 
				
			||||||
 | 
								return "";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							DecimalFormat df = new DecimalFormat("#.###");
 | 
				
			||||||
 | 
							String fnum = df.format(amt);
 | 
				
			||||||
 | 
							if (format == IngredientAmountFormat.IA_DECIMAL) {
 | 
				
			||||||
 | 
								return fnum;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							String part[] = fnum.split("\\.");
 | 
				
			||||||
 | 
							if (part.length == 1) {
 | 
				
			||||||
 | 
								return part[0]; // Integer
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							String p2 = part[1];
 | 
				
			||||||
 | 
							String fs = "";
 | 
				
			||||||
 | 
							if (format == IngredientAmountFormat.IA_TEXT) {
 | 
				
			||||||
 | 
								if (p2.equals("125")) {
 | 
				
			||||||
 | 
									fs = "1/8";
 | 
				
			||||||
 | 
								} else if (p2.equals("333")) {
 | 
				
			||||||
 | 
									fs = "1/3";
 | 
				
			||||||
 | 
								} else if (p2.equals("25")) {
 | 
				
			||||||
 | 
									fs = "1/4";
 | 
				
			||||||
 | 
								} else if (p2.equals("5")) {
 | 
				
			||||||
 | 
									fs = "1/2";
 | 
				
			||||||
 | 
								} else if (p2.equals("667")) {
 | 
				
			||||||
 | 
									fs = "2/3";
 | 
				
			||||||
 | 
								} else if (p2.equals("75")) {
 | 
				
			||||||
 | 
									fs = "3/4";
 | 
				
			||||||
 | 
								} else { // 3, 5, 7/8
 | 
				
			||||||
 | 
									return fnum;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (!"0".equals(part[0])) {
 | 
				
			||||||
 | 
									fs = ' ' + fs;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if (p2.equals("125")) {
 | 
				
			||||||
 | 
									fs = "⅛";
 | 
				
			||||||
 | 
								} else if (p2.equals("333")) {
 | 
				
			||||||
 | 
									fs = "⅓";
 | 
				
			||||||
 | 
								} else if (p2.equals("25")) {
 | 
				
			||||||
 | 
									fs = "¼";
 | 
				
			||||||
 | 
								} else if (p2.equals("5")) {
 | 
				
			||||||
 | 
									fs = "½";
 | 
				
			||||||
 | 
								} else if (p2.equals("667")) {
 | 
				
			||||||
 | 
									fs = "⅔";
 | 
				
			||||||
 | 
								} else if (p2.equals("75")) {
 | 
				
			||||||
 | 
									fs = "¾";
 | 
				
			||||||
 | 
								} else { // 3, 5, 7/8
 | 
				
			||||||
 | 
									return fnum;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ("0".equals(part[0])) {
 | 
				
			||||||
 | 
								part[0] = "";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return part[0] + fs;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										375
									
								
								src/main/java/com/mousetech/gourmetj/IngredientUI.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										375
									
								
								src/main/java/com/mousetech/gourmetj/IngredientUI.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,375 @@
 | 
				
			||||||
 | 
					package com.mousetech.gourmetj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.model.Ingredient;
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.model.IngredientIF;
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.model.Recipe;
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.IngredientDigester;
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.IngredientDigester.IngredientAmountFormat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * JSF-friendly decorator for @see Ingredient. Formats amount
 | 
				
			||||||
 | 
					 * with fractions and supports checkboxes. Primary use
 | 
				
			||||||
 | 
					 * is as a JSF TableModel wrapped content in @see RecipeDetailBean.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * TestedBy @see IngredientUITest
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @author timh
 | 
				
			||||||
 | 
					 * @since Dec 2, 2021
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class IngredientUI implements IngredientIF {
 | 
				
			||||||
 | 
						private Ingredient ingredient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Constructor.
 | 
				
			||||||
 | 
						 * @param ingredient
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public IngredientUI(Ingredient ingredient) {
 | 
				
			||||||
 | 
							this.ingredient = ingredient;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public Ingredient getIngredient() {
 | 
				
			||||||
 | 
							return this.ingredient;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						private boolean ingGroup;
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param ingGroup the ingGroup to set
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setIngGroup(boolean ingGroup) {
 | 
				
			||||||
 | 
							this.ingGroup = ingGroup;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Ingredient groups are rendered visually as synthetic
 | 
				
			||||||
 | 
						 * rows. Actual group IDs are part of line-item ingredients,
 | 
				
			||||||
 | 
						 * so when building the model, we create a group row when
 | 
				
			||||||
 | 
						 * the line item inggroup value changes.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @return <code>true</code> for an Ingredient Group
 | 
				
			||||||
 | 
						 * header row.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public boolean isIngGroup() {
 | 
				
			||||||
 | 
							return this.ingGroup;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Row selection checkbox (UI only)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						private boolean selected;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return the selected status
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public boolean isSelected() {
 | 
				
			||||||
 | 
							return selected;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param selected the selected to set
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setSelected(boolean selected) {
 | 
				
			||||||
 | 
							this.selected = selected;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getAmount()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Double getAmount() {
 | 
				
			||||||
 | 
							return ingredient.getAmount();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param amount
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setAmount(java.lang.Double)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setAmount(Double amount) {
 | 
				
			||||||
 | 
							ingredient.setAmount(amount);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Get amount display-friendly
 | 
				
			||||||
 | 
						 * @see #getAmount
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String getDisplayAmount() {
 | 
				
			||||||
 | 
							// TODO
 | 
				
			||||||
 | 
							Double amt = ingredient.getAmount();
 | 
				
			||||||
 | 
							if ( amt == null ) {
 | 
				
			||||||
 | 
								return "";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							String amt1 = IngredientDigester.displayAmount(
 | 
				
			||||||
 | 
								IngredientAmountFormat.IA_SYMBOLS, amt, ingredient.getRangeamount());
 | 
				
			||||||
 | 
							return amt1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Set amount display-friendly
 | 
				
			||||||
 | 
						 * @see #setAmount
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setDisplayAmount(String amount) {
 | 
				
			||||||
 | 
							if ( amount.isBlank() ) {
 | 
				
			||||||
 | 
								ingredient.setAmount(null);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							IngredientDigester digester = new IngredientDigester();
 | 
				
			||||||
 | 
							Double[] amt = digester.digestAmount(amount);
 | 
				
			||||||
 | 
							ingredient.setAmount(amt[0]);
 | 
				
			||||||
 | 
							ingredient.setRangeamount(amt[1]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getDeleted()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Integer getDeleted() {
 | 
				
			||||||
 | 
							return ingredient.getDeleted();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param deleted
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setDeleted(java.lang.Integer)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setDeleted(Integer deleted) {
 | 
				
			||||||
 | 
							ingredient.setDeleted(deleted);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getId()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Long getId() {
 | 
				
			||||||
 | 
							return ingredient.getId();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param id
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setId(long)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setId(Long id) {
 | 
				
			||||||
 | 
							ingredient.setId(id);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see java.lang.Object#hashCode()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public int hashCode() {
 | 
				
			||||||
 | 
							return ingredient.hashCode();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getInggroup()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String getInggroup() {
 | 
				
			||||||
 | 
							return ingredient.getInggroup();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param inggroup
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setInggroup(java.lang.String)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setInggroup(String inggroup) {
 | 
				
			||||||
 | 
							ingredient.setInggroup(inggroup);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getIngkey()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String getIngkey() {
 | 
				
			||||||
 | 
							return ingredient.getIngkey();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param ingkey
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setIngkey(java.lang.String)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setIngkey(String ingkey) {
 | 
				
			||||||
 | 
							ingredient.setIngkey(ingkey);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getItem()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String getItem() {
 | 
				
			||||||
 | 
							return ingredient.getItem();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param item
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setItem(java.lang.String)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setItem(String item) {
 | 
				
			||||||
 | 
							ingredient.setItem(item);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getOptional()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Integer getOptional() {
 | 
				
			||||||
 | 
							return ingredient.getOptional();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param optional
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setOptional(java.lang.Integer)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setOptional(Integer optional) {
 | 
				
			||||||
 | 
							ingredient.setOptional(optional);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Get optional value in boolean Checkbox friendly form
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public boolean getOptionalCB() {
 | 
				
			||||||
 | 
							return ingredient.getOptional() != 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public void setOptionalCB(boolean value) {
 | 
				
			||||||
 | 
							ingredient.setOptional(value ? 1 : 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getPosition()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Integer getPosition() {
 | 
				
			||||||
 | 
							return ingredient.getPosition();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param position
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setPosition(java.lang.Integer)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setPosition(Integer position) {
 | 
				
			||||||
 | 
							ingredient.setPosition(position);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getRangeamount()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Double getRangeamount() {
 | 
				
			||||||
 | 
							return ingredient.getRangeamount();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param rangeamount
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setRangeamount(java.lang.Double)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setRangeamount(Double rangeamount) {
 | 
				
			||||||
 | 
							ingredient.setRangeamount(rangeamount);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getRecipe()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Recipe getRecipe() {
 | 
				
			||||||
 | 
							return ingredient.getRecipe();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param recipe
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setRecipe(com.mousetech.gourmetj.persistence.model.Recipe)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setRecipe(Recipe recipe) {
 | 
				
			||||||
 | 
							ingredient.setRecipe(recipe);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getRefid()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Long getRefid() {
 | 
				
			||||||
 | 
							return ingredient.getRefid();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param refid
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setRefid(java.lang.Long)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setRefid(Long refid) {
 | 
				
			||||||
 | 
							ingredient.setRefid(refid);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getShopoptional()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Integer getShopoptional() {
 | 
				
			||||||
 | 
							return ingredient.getShopoptional();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param shopoptional
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setShopoptional(java.lang.Integer)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setShopoptional(Integer shopoptional) {
 | 
				
			||||||
 | 
							ingredient.setShopoptional(shopoptional);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getShopoptional()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public boolean getShopoptionalCB() {
 | 
				
			||||||
 | 
							return ingredient.getShopoptional() != 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param shopoptional
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setShopoptional(java.lang.Integer)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setShopoptionalCB(boolean shopoptional) {
 | 
				
			||||||
 | 
							ingredient.setShopoptional(shopoptional? 1:0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#getUnit()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String getUnit() {
 | 
				
			||||||
 | 
							return ingredient.getUnit();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param unit
 | 
				
			||||||
 | 
						 * @see com.mousetech.gourmetj.persistence.model.Ingredient#setUnit(java.lang.String)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setUnit(String unit) {
 | 
				
			||||||
 | 
							ingredient.setUnit(unit);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This goes to the shopCats table via ManyToOne at save time.
 | 
				
			||||||
 | 
						private String shopCat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return the shopCat
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String getShopCat() {
 | 
				
			||||||
 | 
							return shopCat;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param shopCat the shopCat to set
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setShopCat(String shopCat) {
 | 
				
			||||||
 | 
							this.shopCat = shopCat;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return
 | 
				
			||||||
 | 
						 * @see java.lang.Object#toString()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String toString() {
 | 
				
			||||||
 | 
							return ingredient.toString();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										86
									
								
								src/main/java/com/mousetech/gourmetj/JSFUtils.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/main/java/com/mousetech/gourmetj/JSFUtils.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,86 @@
 | 
				
			||||||
 | 
					package com.mousetech.gourmetj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.InputStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.faces.application.FacesMessage;
 | 
				
			||||||
 | 
					import javax.faces.context.ExternalContext;
 | 
				
			||||||
 | 
					import javax.faces.context.FacesContext;
 | 
				
			||||||
 | 
					import javax.faces.context.Flash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
 | 
					import org.slf4j.LoggerFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class JSFUtils {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Logger */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static final Logger log =
 | 
				
			||||||
 | 
								LoggerFactory.getLogger(JSFUtils.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static ExternalContext getExternalContext() {
 | 
				
			||||||
 | 
							FacesContext facesContext =
 | 
				
			||||||
 | 
									FacesContext.getCurrentInstance();
 | 
				
			||||||
 | 
							ExternalContext externalContext =
 | 
				
			||||||
 | 
									facesContext.getExternalContext();
 | 
				
			||||||
 | 
							return externalContext;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Obtain resource as Stream. The caller must close this
 | 
				
			||||||
 | 
						 * stream after use.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param pathName Path of the resource. For example,
 | 
				
			||||||
 | 
						 *                 "/WEB-INF/classes/xys.properties".
 | 
				
			||||||
 | 
						 * @return InputStream or <code>null</code>, if no such
 | 
				
			||||||
 | 
						 *         resource exists.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static InputStream getResourceStream(
 | 
				
			||||||
 | 
								String pathName) {
 | 
				
			||||||
 | 
							InputStream response = getExternalContext()
 | 
				
			||||||
 | 
								.getResourceAsStream(pathName);
 | 
				
			||||||
 | 
							return response;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ===
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Post an info-level message to the FacesContext where the
 | 
				
			||||||
 | 
						 * <h:messages> tag can display it.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param string Message text
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static void addInfoMessage(String string) {
 | 
				
			||||||
 | 
							FacesMessage message = new FacesMessage(
 | 
				
			||||||
 | 
									FacesMessage.SEVERITY_INFO, string, string);
 | 
				
			||||||
 | 
							FacesContext.getCurrentInstance().addMessage(null,
 | 
				
			||||||
 | 
								message);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Post an error-level message to the FacesContext where the
 | 
				
			||||||
 | 
						 * <h:messages> tag can display it.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param string Message text
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static void addErrorMessage(String string) {
 | 
				
			||||||
 | 
							FacesMessage message = new FacesMessage(
 | 
				
			||||||
 | 
									FacesMessage.SEVERITY_ERROR, string, string);
 | 
				
			||||||
 | 
							FacesContext.getCurrentInstance().addMessage(null,
 | 
				
			||||||
 | 
								message);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static void addErrorMessage(String string,
 | 
				
			||||||
 | 
								Exception e) {
 | 
				
			||||||
 | 
							if (e instanceof NullPointerException) {
 | 
				
			||||||
 | 
								addErrorMessage(
 | 
				
			||||||
 | 
									"Internal logic error (NullPointerException)");
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								addErrorMessage(string);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							log.error(string, e);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static Flash flashScope() {
 | 
				
			||||||
 | 
							return (FacesContext.getCurrentInstance()
 | 
				
			||||||
 | 
								.getExternalContext().getFlash());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										97
									
								
								src/main/java/com/mousetech/gourmetj/UserSession.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/main/java/com/mousetech/gourmetj/UserSession.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,97 @@
 | 
				
			||||||
 | 
					package com.mousetech.gourmetj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.Serializable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.enterprise.context.SessionScoped;
 | 
				
			||||||
 | 
					import javax.inject.Named;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.model.Recipe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Named
 | 
				
			||||||
 | 
					@SessionScoped
 | 
				
			||||||
 | 
					public class UserSession implements Serializable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Serial version for session save/restore 
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private static final long serialVersionUID =
 | 
				
			||||||
 | 
								7449440266704831598L;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						private String lastSearch = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return the lastSearch
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String getLastSearch() {
 | 
				
			||||||
 | 
							return lastSearch;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param lastSearch the lastSearch to set
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setLastSearch(String lastSearch) {
 | 
				
			||||||
 | 
							this.lastSearch = lastSearch;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						private Long lastEdit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return the lastEdit
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Long getLastEdit() {
 | 
				
			||||||
 | 
							return lastEdit;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param lastEdit the lastEdit to set
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setLastEdit(Long lastEdit) {
 | 
				
			||||||
 | 
							this.lastEdit = lastEdit;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						//***
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Tab index to select when presenting editDetails.
 | 
				
			||||||
 | 
						 * First tab is 0.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private int detailTab;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return the detailTab
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public int getDetailTab() {
 | 
				
			||||||
 | 
							return detailTab;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param detailTab the detailTab to set
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setDetailTab(int detailTab) {
 | 
				
			||||||
 | 
							this.detailTab = detailTab;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//***
 | 
				
			||||||
 | 
						private Recipe recipe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Recipe is set by the mainpage bean to a blank recipe
 | 
				
			||||||
 | 
						 * before dispatching to the detailEdit page (new recipe).
 | 
				
			||||||
 | 
						 * It is also set by the detail view page so that the
 | 
				
			||||||
 | 
						 * detail view can be edited.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * In addition to detail editing, it's also used by the
 | 
				
			||||||
 | 
						 * @see PictureController.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @return Recipe selected.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Recipe getRecipe() {
 | 
				
			||||||
 | 
							return recipe;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param recipe the recipe to set
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setRecipe(Recipe recipe) {
 | 
				
			||||||
 | 
							this.recipe = recipe;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,47 @@
 | 
				
			||||||
 | 
					package com.mousetech.gourmetj.persistence.service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.Serializable;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import javax.enterprise.context.ApplicationScoped;
 | 
				
			||||||
 | 
					import javax.inject.Inject;
 | 
				
			||||||
 | 
					import javax.inject.Named;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.transaction.annotation.Transactional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.dao.CategoryRepository;
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.dao.RecipeRepository;
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.model.Category;
 | 
				
			||||||
 | 
					import com.mousetech.gourmetj.persistence.model.Recipe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Named
 | 
				
			||||||
 | 
					@ApplicationScoped
 | 
				
			||||||
 | 
					@Transactional
 | 
				
			||||||
 | 
					public class RecipeService implements Serializable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static final long serialVersionUID = 1L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Inject
 | 
				
			||||||
 | 
						private RecipeRepository recipeRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public List<Recipe> findAll() {
 | 
				
			||||||
 | 
							return recipeRepository.findAll();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public List<String> findCuisines() {
 | 
				
			||||||
 | 
							// TODO Auto-generated method stub
 | 
				
			||||||
 | 
							return null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public List<Recipe> findByTitle(String searchText) {
 | 
				
			||||||
 | 
							// TODO Auto-generated method stub
 | 
				
			||||||
 | 
							return null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  /**
 | 
				
			||||||
 | 
					//   * 
 | 
				
			||||||
 | 
					//   * @return All Category names that are not null/blank, sorted.
 | 
				
			||||||
 | 
					//   */
 | 
				
			||||||
 | 
					//  public List<String> findCategoryNames() {
 | 
				
			||||||
 | 
					//	 return categoryRepository.findDistinctCategoryNative(); 
 | 
				
			||||||
 | 
					//  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										67
									
								
								src/main/resources/META-INF/resources/main.xhtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/main/resources/META-INF/resources/main.xhtml
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,67 @@
 | 
				
			||||||
 | 
					<?xml version="1.0"  encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<ui:composition template="/WEB-INF/layout/layout.xhtml"
 | 
				
			||||||
 | 
					    xmlns:f="http://xmlns.jcp.org/jsf/core"
 | 
				
			||||||
 | 
					    xmlns:ui="http://java.sun.com/jsf/facelets"
 | 
				
			||||||
 | 
					    xmlns:tc="http://myfaces.apache.org/tobago/component"
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
					    <ui:define name="title">Gourmet Recipe Manager</ui:define>
 | 
				
			||||||
 | 
					    <ui:define name="content">
 | 
				
			||||||
 | 
					        <tc:messages />
 | 
				
			||||||
 | 
					        <tc:form id="form1">
 | 
				
			||||||
 | 
					            <tc:section label="Find a Recipe" level="2">
 | 
				
			||||||
 | 
					                <tc:gridLayout id="gfinder"
 | 
				
			||||||
 | 
					                    columns="60em auto auto"
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                    <tc:in id="searchFor" focus="true"
 | 
				
			||||||
 | 
					                        placeholder="Recipe title (todo) cuisine, etc."
 | 
				
			||||||
 | 
					                        value="#{adminMainBean.searchText}"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                    <tc:button id="find" label="Find"
 | 
				
			||||||
 | 
					                        defaultCommand="true"
 | 
				
			||||||
 | 
					                        action="#{adminMainBean.doFind}"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                        <tc:style minWidth="58px" height="40px" />
 | 
				
			||||||
 | 
					                    </tc:button>
 | 
				
			||||||
 | 
					                    <tc:button label="New Recipe"
 | 
				
			||||||
 | 
					                        action="#{adminMainBean.doNewRecipe}"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                        <tc:style minWidth="58px" height="40px" />
 | 
				
			||||||
 | 
					                    </tc:button>
 | 
				
			||||||
 | 
					                </tc:gridLayout>
 | 
				
			||||||
 | 
					            </tc:section>
 | 
				
			||||||
 | 
					        </tc:form>
 | 
				
			||||||
 | 
					        <tc:sheet id="table1" rows="30"
 | 
				
			||||||
 | 
					            value="#{adminMainBean.searchResults}" var="row"
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					            <tc:column label="Icon">
 | 
				
			||||||
 | 
					                <tc:image width="64" height="64"
 | 
				
			||||||
 | 
					                    value="/gourmetj/img/thumb/#{row.id}"
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            </tc:column>
 | 
				
			||||||
 | 
					            <tc:column label="Recipe">
 | 
				
			||||||
 | 
					                <tc:link action="#{adminMainBean.showRecipe}"
 | 
				
			||||||
 | 
					                    label="#{row.title}"
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            </tc:column>
 | 
				
			||||||
 | 
					            <tc:column label="Category">
 | 
				
			||||||
 | 
					                <tc:out
 | 
				
			||||||
 | 
					                    value="#{adminMainBean.formatCategories(row)}"
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            </tc:column>
 | 
				
			||||||
 | 
					            <tc:column label="Cuisine">
 | 
				
			||||||
 | 
					                <tc:out value="#{row.cuisine}" />
 | 
				
			||||||
 | 
					            </tc:column>
 | 
				
			||||||
 | 
					            <tc:column label="Rating">
 | 
				
			||||||
 | 
					                <tc:stars value="#{row.rating}" readonly="true" />
 | 
				
			||||||
 | 
					            </tc:column>
 | 
				
			||||||
 | 
					            <tc:column label="Source">
 | 
				
			||||||
 | 
					                <tc:out value="#{row.source}" />
 | 
				
			||||||
 | 
					            </tc:column>
 | 
				
			||||||
 | 
					            <tc:column label="Prep Time">
 | 
				
			||||||
 | 
					                <tc:out
 | 
				
			||||||
 | 
					                    value="#{adminMainBean.formatPreptime(row.preptime)}"
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            </tc:column>
 | 
				
			||||||
 | 
					        </tc:sheet>
 | 
				
			||||||
 | 
					    </ui:define>
 | 
				
			||||||
 | 
					</ui:composition>
 | 
				
			||||||
							
								
								
									
										28
									
								
								src/main/resources/WEB-INF/layout/layout.xhtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/main/resources/WEB-INF/layout/layout.xhtml
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,28 @@
 | 
				
			||||||
 | 
					<?xml version="1.0"  encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<ui:composition xmlns:f="http://xmlns.jcp.org/jsf/core"
 | 
				
			||||||
 | 
					    xmlns:ui="http://java.sun.com/jsf/facelets"
 | 
				
			||||||
 | 
					    xmlns:h="http://java.sun.com/jsf/html"
 | 
				
			||||||
 | 
					    xmlns:tc="http://myfaces.apache.org/tobago/component"
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
					    <f:view>
 | 
				
			||||||
 | 
					        <tc:page id="page">
 | 
				
			||||||
 | 
					            <title><ui:insert name="title">Gourmet Recipe Manager (web version)</ui:insert></title>
 | 
				
			||||||
 | 
					            <link rel="icon" type="image/vnd.microsoft.icon"
 | 
				
			||||||
 | 
					                href="#{pageContext.contextPath}/favicon.ico"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <tc:style file="css/style.css" />
 | 
				
			||||||
 | 
					            <h1>
 | 
				
			||||||
 | 
					                <ui:insert name="title">Gourmet Recipe Manager (web version)</ui:insert>
 | 
				
			||||||
 | 
					            </h1>
 | 
				
			||||||
 | 
					            <ui:insert name="content">
 | 
				
			||||||
 | 
					                <ui:include src="content.xhtml" />
 | 
				
			||||||
 | 
					            </ui:insert>
 | 
				
			||||||
 | 
					            <tc:footer fixed="true">
 | 
				
			||||||
 | 
					        © 2021 Tim Holloway, Licensed under the <a
 | 
				
			||||||
 | 
					                    href="http://www.apache.org/licenses/LICENSE-2.0"
 | 
				
			||||||
 | 
					                >Apache License, Version 2.0</a>.
 | 
				
			||||||
 | 
					              <p>Based on Gourmet Recipe Manager by T. Hinkle</p>
 | 
				
			||||||
 | 
					            </tc:footer>
 | 
				
			||||||
 | 
					        </tc:page>
 | 
				
			||||||
 | 
					    </f:view>
 | 
				
			||||||
 | 
					</ui:composition>
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user