/**
* Copyright (C) Gadglet .
*
* This file is part of Gadglet
*
* Gadglet is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gadglet is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Gadglet. If not, see <http://www.gnu.org/licenses/>.
*/
package com.gadglet.data.utils;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import com.gadglet.core.GadgletRequestWrapper;
import com.gadglet.core.RequestException;
import com.gadglet.data.PersonalShareableContentItem;
import com.gadglet.data.SharedItemReff;
import com.gadglet.params.ReqErrorTypes;
import com.gadglet.params.ReqParamNames;
import com.gadglet.params.SharingType;
/**
* A utility class to enable Google App Engine JDO DataStore methods
* with Gadglet simple content item "PersonalShareableContentItem"
* <p>
* Note:
* Make sure that the property<br>
* property name="datanucleus.appengine.storageVersion" value="WRITE_OWNED_CHILD_KEYS_TO_PARENTS"<br>
* is defined in your jdoconfig.xml
*
*/
public class ContentItemHelper {
private Logger log = Logger.getLogger(this.getClass().getName());
/**
* @param item
* @param request
* @return true if the content item is shared with the curent user
*/
public boolean isSharedWithMe(PersonalShareableContentItem item,
GadgletRequestWrapper request) {
List<SharedItemReff> sharedUsers = item.getSharedItemReff();
if (sharedUsers != null)
for (SharedItemReff ref : sharedUsers) {
if (ref.getSharedWithId().equals(request.getCurrentUserId()))
return true;
}
return false;
}
/**
* @param item
* @param request
* @return true id the current user can update this item
*/
public boolean canUserModifyItem(PersonalShareableContentItem item,
GadgletRequestWrapper request) {
List<SharedItemReff> sharedUsers = item.getSharedItemReff();
if (sharedUsers != null)
for (SharedItemReff ref : sharedUsers) {
if (ref.getSharedWithId().equals(request.getCurrentUserId())
&& !ref.getSharingType().equals(SharingType.READ_ONLY))
return true;
}
return false;
}
/**
* @param item
* @param request
* @return true if the current user is the owner of the item
*/
public boolean isItemOwner(PersonalShareableContentItem item,
GadgletRequestWrapper request) {
if (item == null || request == null)
return false;
else if (item.getOwnerId().equals(request.getCurrentUserId()))
return true;
else
return false;
}
public void queryParameters(GadgletRequestWrapper request,
java.util.Map<String, Object> params) {
params.put("ownerIdParam", request.getCurrentUserId());
}
/**
* Delete an item from the DataStore
* @param request
* @param className
* @return
* @throws RequestException
*/
public boolean delete(GadgletRequestWrapper request, Class<?> className)
throws RequestException {
PersonalShareableContentItem item = null;
PersistenceManager pm = null;
try {
pm = PMF.get().getPersistenceManager();
item = getSingleItemByKeyForAction(pm, request, className);
if (!isItemOwner(item, request))
throw new RequestException(ReqErrorTypes.UNAUTHORIZED_OPERATION);
} catch (RequestException e) {
throw new RequestException(e.getErrorType());
} catch (Exception e) {
log.warning(e.getMessage());
throw new RequestException(ReqErrorTypes.REQUEST_FAILED);
}
try {
pm.deletePersistent(item);
} catch (Exception e) {
log.warning(e.getMessage());
throw new RequestException(ReqErrorTypes.REQUEST_FAILED);
} finally {
pm.close();
}
return true;
}
/**
* Share item with a friend
* @param request
* @param className
* @throws RequestException
*/
public void shareItem(GadgletRequestWrapper request, Class<?> className)
throws RequestException {
PersistenceManager pm = PMF.get().getPersistenceManager();
PersonalShareableContentItem item = (PersonalShareableContentItem) getSingleItemByKeyForAction(
pm, request, className);
String shareWith = request.getParameter(ReqParamNames.SHARE_WITH
.getParamName());
SharingType sharingType = request.getSharingType();
SharedItemReff newShare = null;
boolean shareExists = false;
int remove = -1;
List<SharedItemReff> sharings = null;
// missing shareWith
if (shareWith == null) {
pm.close();
throw new RequestException(ReqErrorTypes.MISSING_ARGUMENT);
}
// not owner
if (!item.getOwnerId().equals(request.getCurrentUserId())) {
pm.close();
throw new RequestException(ReqErrorTypes.UNAUTHORIZED_OPERATION);
}
// can't change owner settings
if (item.getOwnerId().equals(shareWith)) {
pm.close();
throw new RequestException(ReqErrorTypes.UNAUTHORIZED_OPERATION);
}
try {
sharings = item.getSharedItemReff();
int index = 0;
for (SharedItemReff share : sharings) {
if (share.getSharedWithId().equals(shareWith)
&& !share.getSharingType().equals(SharingType.OWNER)) {
shareExists = true;
if (sharingType == null)
remove = index;
else
share.setSharingType(sharingType);
}
index++;
}
// add
if (remove > -1)
item.getSharedItemReff().remove(remove);
// add new sharing
if (!shareExists && request.getSharingType() != null
&& !request.getSharingType().equals(SharingType.OWNER)) {
newShare = new SharedItemReff();
newShare.setSharedWithId(request
.getParameter(ReqParamNames.SHARE_WITH.getParamName()));
newShare.setSharingType(request.getSharingType());
item.addSharedItemReff(newShare);
}
updated(pm, item, request);
} catch (RequestException e) {
throw e;
} catch (Exception e) {
log.warning(e.getMessage());
throw new RequestException(ReqErrorTypes.REQUEST_FAILED);
}
}
/**
* Retrieve an item from the DataStore with a given PersistenceManager
* @param pm
* @param request
* @param className
* @return
* @throws RequestException
*/
public PersonalShareableContentItem getSingleItemByKeyForAction(
PersistenceManager pm, GadgletRequestWrapper request,
Class<?> className) throws RequestException {
PersonalShareableContentItem item = null;
String key = request.getItemKeyField();
if (key == null)
throw new RequestException(ReqErrorTypes.ITEM_NOT_FOUND);
try {
item = (PersonalShareableContentItem) pm.getObjectById(className,
key);
// access all fields before pm is closed to ensure fields are
// available
if (item != null && item.getSharedItemReff() != null)
for (SharedItemReff ref : item.getSharedItemReff())
ref.getSharingType();
} catch (Exception e) {
log.warning(e.getMessage());
throw new RequestException(ReqErrorTypes.ITEM_NOT_FOUND);
}
if (item == null)
throw new RequestException(ReqErrorTypes.ITEM_NOT_FOUND);
return item;
}
/**
* Retrieve a single item from the DataStore
* @param request
* @param className
* @return
* @throws RequestException
*/
public PersonalShareableContentItem getSingleItemByKey(
GadgletRequestWrapper request, Class<?> className)
throws RequestException {
PersonalShareableContentItem item = null;
String key = request.getItemKeyField();
if (key == null)
throw new RequestException(ReqErrorTypes.ITEM_NOT_FOUND);
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
item = (PersonalShareableContentItem) pm.getObjectById(className,
key);
// access all fields before pm is closed to ensure fields are
// available
if (item != null && item.getSharedItemReff() != null)
for (SharedItemReff ref : item.getSharedItemReff())
ref.getSharingType();
} catch (Exception e) {
log.warning(e.getMessage());
throw new RequestException(ReqErrorTypes.ITEM_NOT_FOUND);
} finally {
pm.close();
}
if (item == null)
throw new RequestException(ReqErrorTypes.ITEM_NOT_FOUND);
return item;
}
/**
* Update an item in the DataStore
* @param pm
* @param item
* @param request
* @return
* @throws RequestException
*/
public boolean updated(PersistenceManager pm,
PersonalShareableContentItem item, GadgletRequestWrapper request)
throws RequestException {
if (!canUserModifyItem(item, request)) {
if (pm != null)
pm.close();
throw new RequestException(ReqErrorTypes.UNAUTHORIZED_OPERATION);
}
item.setUpdate();
if (pm == null)
pm = PMF.get().getPersistenceManager();
pm.currentTransaction().begin();
try {
pm.makePersistent(item);
pm.currentTransaction().commit();
} catch (Exception e) {
log.warning(e.getMessage());
throw new RequestException(ReqErrorTypes.REQUEST_FAILED);
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
return true;
}
/**
* Create a new item in the DataStore
* @param item
* @return
* @throws RequestException
*/
public String saveNew(PersonalShareableContentItem item)
throws RequestException {
SharedItemReff reff = new SharedItemReff(SharingType.OWNER,
item.getOwnerId());
item.addSharedItemReff(reff);
PersonalShareableContentItem savedItem = null;
PersistenceManager pm = PMF.get().getPersistenceManager();
pm.currentTransaction().begin();
try {
savedItem = pm.makePersistent(item);
pm.currentTransaction().commit();
} catch (Exception e) {
log.warning(e.getMessage());
throw new RequestException(ReqErrorTypes.REQUEST_FAILED);
} finally {
if (pm.currentTransaction().isActive())
pm.currentTransaction().rollback();
pm.close();
}
if (savedItem == null)
return null;
else
return savedItem.getContentItemKey();
}
/**
* A list of items "owned" by the current user
*
* @param request
* @param contentClass - items class name
* @param filterBy - filter By expression: "fieldX==fieldXParam && fieldY==fieldYParam"
* @param filterByParamDeclaration - a list of parameters used in filterBy: "String fieldXParam, String fieldYParam"
* @param qParams - a list of parameters values used by filterBy
* @param orderBy - orderby expression :"fieldX ascending"
* @param startFrom - first item index
* @param itemNum - number of item requested
* @param hasMore - object that will
* @return A list of items "owned" by the current user
* @throws RequestException
*/
public List<?> getOwnerItems(GadgletRequestWrapper request,
Class<?> contentClass, String filterBy,
String filterByParamDeclaration,
java.util.Map<String, Object> qParams, String orderBy,
long startFrom, long itemNum, HasMoreItems hasMore)
throws RequestException {
List<?> items = null;
Query query = null;
PersistenceManager pm = null;
java.util.Map<String, Object> params = null;
if (qParams != null)
params = qParams;
else
params = new HashMap<String, Object>();
queryParameters(request, params);
try {
pm = PMF.get().getPersistenceManager();
query = ownerItemsQuery(pm, contentClass, filterBy,
filterByParamDeclaration, orderBy, startFrom, itemNum);
items = (List<?>) query.executeWithMap(params);
// the +1 is done do be able to know if has more results ==
// true/false
if (items.size() > itemNum)
hasMore.setTrue();
else
hasMore.setFalse();
} catch (Exception e) {
log.warning(e.toString());
throw new RequestException(ReqErrorTypes.REQUEST_FAILED);
} finally {
query.closeAll();
pm.close();
}
return items;
}
/**
* A Query for list of items "owned" by the current user
*
* @param request
* @param contentClass - items class name
* @param filterBy - filter By expression: "fieldX==fieldXParam && fieldY==fieldYParam"
* @param filterByParamDeclaration - a list of parameters used in filterBy: "String fieldXParam, String fieldYParam"
* @param qParams - a list of parameters values used by filterBy
* @param orderBy - orderby expression :"fieldX ascending"
* @param startFrom - first item index
* @param itemNum - number of item requested
* @param hasMore - object that will
* @return A Query for list of items "owned" by the current user
* @throws RequestException
*/
public Query ownerItemsQuery(PersistenceManager pm, Class<?> contentClass,
String filerBy, String filterByParamDeclaration, String orderBy,
long startFrom, long itemNum) {
Query query = null;
query = pm.newQuery(contentClass);
StringBuffer filter = new StringBuffer();
StringBuffer filterParameters = new StringBuffer();
filterParameters.append("String ownerIdParam");
filter.append("(ownerId==ownerIdParam)");
if (filterByParamDeclaration != null)
filterParameters.append("," + filterByParamDeclaration);
if (filerBy != null)
filter.append(" && " + filerBy);
if (orderBy == null || orderBy.isEmpty())
query.setOrdering("creation desc");
else {
query.setOrdering(orderBy);
}
query.declareParameters(filterParameters.toString());
query.setFilter(filter.toString());
// if number of items is not defined bring all
if (itemNum > 0)
query.setRange(startFrom, startFrom + itemNum + 1);
return query;
}
/**
* A list of items "owned" by, or "shared" with the current user
*
* @param request
* @param contentClass - items class name
* @param filterBy - filter By expression: "fieldX==fieldXParam && fieldY==fieldYParam"
* @param filterByParamDeclaration - a list of parameters used in filterBy: "String fieldXParam, String fieldYParam"
* @param qParams - a list of parameters values used by filterBy
* @param orderBy - orderby expression :"fieldX ascending"
* @param startFrom - first item index
* @param itemNum - number of item requested
* @param hasMore - object that will
* @return A list of items "owned" by, or "shared" with the current user
* @throws RequestException
*/
public List<?> getSharedItems(GadgletRequestWrapper request,
Class<?> contentClass, String filerBy,
String filterByParamDecleration,
java.util.Map<String, Object> qParams, String orderBy,
long startFrom, long itemNum, HasMoreItems hasMore)
throws RequestException {
List<?> items = null;
Query query = null;
PersistenceManager pm = null;
java.util.Map<String, Object> params = null;
if (qParams != null)
params = qParams;
else
params = new HashMap<String, Object>();
queryParameters(request, params);
try {
pm = PMF.get().getPersistenceManager();
query = sharedItemsQuery(pm, contentClass, filerBy,
filterByParamDecleration, orderBy, startFrom, itemNum);
items = (List<?>) query.executeWithMap(params);
// load all reff items
List<PersonalShareableContentItem> loop = (List<PersonalShareableContentItem>) items;
for (int index = 0; index < loop.size(); index++) {
List<SharedItemReff> shares = loop.get(index)
.getSharedItemReff();
if (shares != null)
for (SharedItemReff reff : shares)
;
}
if (items.size() > itemNum)
hasMore.setTrue();
else
hasMore.setFalse();
} catch (Exception e) {
log.warning(e.getMessage());
throw new RequestException(ReqErrorTypes.REQUEST_FAILED);
} finally {
query.closeAll();
pm.close();
}
return items;
}
/**
* A Query for a list of items "owned" by, or "shared" with the current user
*
* <p>
* NOTE:
* Due to limitation in the JDO/DataStore implementation <br>
*
* 1. Orderby is not supported <br>
* 2. FilterBy only supports "&&"
*
* </p>
*
* @param request
* @param contentClass - items class name
* @param filterBy - filter By expression: "fieldX==fieldXParam && fieldY==fieldYParam"
* @param filterByParamDeclaration - a list of parameters used in filterBy: "String fieldXParam, String fieldYParam"
* @param qParams - a list of parameters values used by filterBy
* @param orderBy - orderby expression :"fieldX ascending"
* @param startFrom - first item index
* @param itemNum - number of item requested
* @param hasMore - object that will
* @return A Query for a list of items "owned" by, or "shared" with the current user
* @throws RequestException
*/
public Query sharedItemsQuery(PersistenceManager pm, Class<?> contentClass,
String filterBy, String filterByParamDecleration, String orderBy,
long startFrom, long itemNum) {
StringBuffer filter = new StringBuffer();
StringBuffer filterParameters = new StringBuffer();
if (filterBy != null)
filter.append(" && " + filterBy );
Query query = pm
.newQuery("select from "
+ contentClass.getName()
+ " where "
+ " sharedItemReff.contains(c) && c.sharedWithId == ownerIdParam"
+ filter.toString());
query.declareVariables(SharedItemReff.class.getName() + " c");
filterParameters.append("String ownerIdParam");
if (filterByParamDecleration != null)
filterParameters.append("," + filterByParamDecleration);
//TODO:Sorry, Not supported at this point by Google App Engine JDO
//query.setOrdering(orderBy);
query.declareParameters(filterParameters.toString());
if (itemNum > 0)
query.setRange(startFrom, startFrom + itemNum + 1);
return query;
}
}