/* Copyright (c) 2006 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.gbase.recipe;
import com.google.api.gbase.client.GoogleBaseEntry;
import com.google.api.gbase.client.NumberUnit;
import com.google.gdata.data.Content;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.OtherContent;
import com.google.gdata.data.Person;
import com.google.gdata.data.TextConstruct;
import com.google.gdata.data.TextContent;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* One recipe, ready to be displayed.
* Just a data holding object.
*/
public class Recipe {
public final static String RECIPE_ITEMTYPE = "recipes";
public final static String MAIN_INGREDIENT_ATTRIBUTE = "main ingredient";
public final static String CUISINE_ATTRIBUTE = "cuisine";
public final static String COOKING_TIME_ATTRIBUTE = "cooking time";
public final static String AUTHOR_UNKNOWN = "";
private final String id;
private final DateTime postedOn;
private final String postedBy;
private final NumberUnit<Integer> cookingTime;
private final String url;
private final String title;
private final String description;
/** A never-null list that contains the main ingredients. */
private final Set<String> mainIngredient;
/** A never-null list that contains the cuisines. */
private final Set<String> cuisine;
/**
* Creates a recipe. The parameters can be null.
*
* @param id id generated by the GoogleBase server
* @param title
* @param url alternate url of the recipe;
* if null, when the recipe is used to insert or to update
* it is generated by the GoogleBase server
* @param description
* @param mainIngredient
* @param cuisine
* @param cookingTime
*/
public Recipe(String id, String title, String url,
String description, Set<String> mainIngredient, Set<String> cuisine,
NumberUnit<Integer> cookingTime) {
if (mainIngredient == null) {
mainIngredient = new HashSet<String>();
}
if (cuisine == null) {
cuisine = new HashSet<String>();
}
this.id = id;
this.title = title;
this.url = url;
this.description = description;
this.mainIngredient = mainIngredient;
this.cuisine = cuisine;
this.cookingTime = cookingTime;
this.postedOn = null;
this.postedBy = null;
}
/**
* Creates a recipe out of a GoogleBaseEntry.
*
* @param entry an entry that represents a recipe
*/
public Recipe(GoogleBaseEntry entry) {
id = extractIdFromUrl(entry.getId());
title = entry.getTitle().getPlainText();
url = entry.getHtmlLink().getHref();
String description = null;
if (entry.getContent() != null) {
Content content = entry.getContent();
if (content instanceof TextContent) {
description = ((TextContent)content).getContent().getPlainText();
} else if (content instanceof OtherContent) {
description = ((OtherContent)content).getText();
}
}
this.description = description;
mainIngredient = new HashSet<String>(entry.getGoogleBaseAttributes().
getTextAttributeValues(MAIN_INGREDIENT_ATTRIBUTE));
cuisine = new HashSet<String>(entry.getGoogleBaseAttributes().
getTextAttributeValues(CUISINE_ATTRIBUTE));
cookingTime = entry.getGoogleBaseAttributes().
getIntUnitAttribute(COOKING_TIME_ATTRIBUTE);
postedOn = entry.getPublished();
// if an entry has no author specified, will set it to empty string
List<Person> authors = entry.getAuthors();
postedBy = (authors.isEmpty() ? AUTHOR_UNKNOWN : authors.get(0).getName());
}
/**
* Creates an empty recipe, the values are null or empty Sets.
*/
public Recipe() {
this(null, null, null, null, null, null, null);
}
public GoogleBaseEntry toGoogleBaseEntry(String idUrl)
{
GoogleBaseEntry entry = new GoogleBaseEntry();
entry.getGoogleBaseAttributes().setItemType(RECIPE_ITEMTYPE);
if (idUrl != null) {
entry.setId(idUrl);
}
entry.setTitle(TextConstruct.create(TextConstruct.Type.TEXT, title, null));
if (url != null) {
entry.addHtmlLink(url, null, null);
}
if (description != null) {
// If the original content was not TEXT, the formatting is lost
entry.setContent(
TextConstruct.create(TextConstruct.Type.TEXT, description, null));
}
for (String ingredient : mainIngredient) {
entry.getGoogleBaseAttributes().addTextAttribute(
MAIN_INGREDIENT_ATTRIBUTE, ingredient);
}
for (String cuisineItem : cuisine) {
entry.getGoogleBaseAttributes().addTextAttribute(
CUISINE_ATTRIBUTE, cuisineItem);
}
if (cookingTime != null) {
entry.getGoogleBaseAttributes().addIntUnitAttribute(
COOKING_TIME_ATTRIBUTE, cookingTime);
}
return entry;
}
/**
* Extracts the id of the item from the given url.
*
* The id found in GoogleBaseEntry is a URL that contains the real, numerical
* id of the item in Google Base. Parsing the URL is unfortunately the
* only way of getting a numerical id given a GoogleBaseEntry.
*
* @param url a URL that ends with "/" [N] number
*/
private static String extractIdFromUrl(String url) {
int lastSlash = url.lastIndexOf('/');
if (lastSlash == -1 || lastSlash == (url.length()-1)) {
throw new IllegalArgumentException("Id is in a strange format. " + url);
}
String oid = url.substring(lastSlash + 1);
return oid;
}
/** Checks whether there is a description for the recipe. */
public boolean hasDescription() {
return description != null;
}
/** Checks whether there is a cooking time for the recipe. */
public boolean hasCookingTime() {
return cookingTime != null;
}
/** Checks whether there are some cuisines for the recipe. */
public boolean hasCuisine() {
return cuisine.size() > 0;
}
/** Checks whether there are some main ingredients for the recipe. */
public boolean hasMainIngredient() {
return mainIngredient.size() > 0;
}
/**
* Gets the date at which the recipe was posted, as a string.
*
* @param detailed set to true to get a full date and time
*/
public String getPostedOnAsString(boolean detailed) {
Date date = new Date(postedOn.getValue());
String template = detailed ? "MMMMM d, yyyy HH:mm z" : "MMM d";
DateFormat format = new SimpleDateFormat(template);
return format.format(date);
}
/** Gets the host and protocol from the recipe URL. */
public String getHostAndProtocol() throws MalformedURLException {
URL urlObject = new URL(getUrl());
return urlObject.getProtocol() + "://" + urlObject.getHost();
}
/**
* Returns true when the title, description, mainIngredient and cuisine
* attributes are not null nor empty.
*/
public boolean isComplete() {
return title != null &&
description != null &&
mainIngredient.size() > 0 &&
cuisine.size() > 0;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("Recipe[");
appendNamedParameter(sb, "title", title);
appendNamedParameter(sb, "id", id);
appendNamedParameter(sb, "url", url);
appendNamedParameter(sb, "description", description);
appendNamedParameter(sb, "cookingTime", cookingTime);
appendNamedParameter(sb, "postedOn", postedOn);
appendNamedParameter(sb, "postedBy", postedBy);
appendNamedCollection(sb, "mainIngredient", mainIngredient);
appendNamedCollection(sb, "cuisine", cuisine);
sb.append("]");
return sb.toString();
}
/**
* Appends the name and the value of an Object to a StringBuffer.
*
* @param sb
* @param name
* @param value
*/
private static void appendNamedParameter(StringBuffer sb,
String name,
Object value) {
if (value != null) {
sb.append(name).append("=\"").append(value).append("\" ");
}
}
/**
* Appends the name and the elements of a Collection to a StringBuffer.
*
* @param sb
* @param name
* @param collection
*/
private static void appendNamedCollection(
StringBuffer sb,
String name,
Collection<String> collection) {
if (collection.size() > 0) {
sb.append(name).append("=(");
for (String value : collection) {
sb.append("\"").append(value).append("\", ");
}
sb.append(") ");
}
}
/** Gets the id generated by the server. */
public String getId() {
return id;
}
/** Gets the user assigned title. */
public String getTitle() {
return title;
}
/**
* Gets the url of the recipe, as set by the customer.
* If the customer sets no url, the server will generate one.
*/
public String getUrl() {
return url;
}
/** Gets the user assigned description. */
public String getDescription() {
return description;
}
/** Returns a never-null Set with the main ingredients of the recipe. */
public Set<String> getMainIngredient() {
return mainIngredient;
}
/** Returns a never-null Set with the cuisines the recipe belongs to. */
public Set<String> getCuisine() {
return cuisine;
}
/** Gets the user assigned cooking time. */
public NumberUnit<Integer> getCookingTime() {
return cookingTime;
}
/** Gets the server generated owner attribute of the recipe. */
public String getPostedBy() {
return postedBy;
}
/** Gets the server generated date at which the recipe was posted. */
public DateTime getPostedOn() {
return postedOn;
}
/** Returns true when the Recipe doesn't have an id. */
public boolean isNew() {
return id == null;
}
}