/**Copyright 2010 Research Studios Austria Forschungsgesellschaft mBH
*
* This file is part of easyrec.
*
* easyrec is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* easyrec 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with easyrec. If not, see <http://www.gnu.org/licenses/>.
*/
package org.easyrec.rest;
import com.google.common.base.CharMatcher;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.jamonapi.Monitor;
import com.jamonapi.MonitorFactory;
import com.sun.jersey.api.json.JSONWithPadding;
import com.sun.jersey.spi.resource.Singleton;
import org.easyrec.exception.core.ClusterException;
import org.easyrec.model.core.ClusterVO;
import org.easyrec.model.core.transfer.TimeConstraintVO;
import org.easyrec.model.core.web.*;
import org.easyrec.model.web.Recommendation;
import org.easyrec.rest.nodomain.exception.EasyRecRestException;
import org.easyrec.service.core.ClusterService;
import org.easyrec.service.core.ProfileService;
import org.easyrec.service.core.TenantService;
import org.easyrec.service.domain.TypeMappingService;
import org.easyrec.service.web.RemoteAssocService;
import org.easyrec.service.web.nodomain.ShopRecommenderService;
import org.easyrec.store.dao.IDMappingDAO;
import org.easyrec.store.dao.core.ItemDAO;
import org.easyrec.store.dao.core.types.AssocTypeDAO;
import org.easyrec.store.dao.web.OperatorDAO;
import org.easyrec.store.dao.web.RemoteTenantDAO;
import org.easyrec.utils.MyUtils;
import org.easyrec.vocabulary.MSG;
import org.easyrec.vocabulary.WS;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* @author szavrel
*/
@Path("{type: (1.0(?:/json)?)}")
@Produces({"application/xml", "application/json"})
@Singleton
public class EasyRec {
@Context
public HttpServletRequest request;
private OperatorDAO operatorDAO;
private ItemDAO itemDAO;
private RemoteAssocService remoteAssocService;
private RemoteTenantDAO remoteTenantDAO;
private TenantService tenantService;
private ShopRecommenderService shopRecommenderService;
private TypeMappingService typeMappingService;
private String dateFormat;
private IDMappingDAO idMappingDAO;
//added by FK on 2012-12-18 to enable adding profile data to recommendations
private ProfileService profileService;
private ClusterService clusterService;
// Jamon Loggers
private final static String JAMON_REST_VIEW = "rest.view";
private final static String JAMON_REST_BUY = "rest.buy";
private final static String JAMON_REST_RATE = "rest.rate";
private final static String JAMON_REST_ACTION = "rest.action";
private final static String JAMON_REST_ALSO_VIEWED = "rest.alsoviewed";
private final static String JAMON_REST_ALSO_BOUGHT = "rest.alsobought";
private final static String JAMON_REST_ALSO_RATED = "rest.alsorated";
private final static String JAMON_REST_RECS_FOR_USER = "rest.recsforuser";
private final static String JAMON_REST_MOST_BOUGHT = "rest.mostbought";
private final static String JAMON_REST_MOST_VIEWED = "rest.mostviewed";
private final static String JAMON_REST_MOST_RATED = "rest.mostrated";
private final static String JAMON_REST_BEST_RATED = "rest.bestrated";
private final static String JAMON_REST_WORST_RATED = "rest.worstrated";
private final static String JAMON_REST_IMPORT_RULE = "rest.import.rule";
private final static String JAMON_REST_IMPORT_ITEM = "rest.import.item";
private final static String JAMON_REST_CREATE_CLUSTER = "rest.create.cluster";
private final static String JAMON_REST_ITEM_ACTIVE = "rest.item.active.rule";
private final static String JAMON_REST_RELATED_ITEMS = "rest.related.items";
private final static String JAMON_REST_ITEMTYPES = "rest.itemtypes";
private final static String JAMON_REST_CLUSTERS = "rest.clusters";
private final static String JAMON_REST_ITEMS_OF_CLUSTERS = "rest.items.from.clusters";
private final static String JAMON_REST_ACTIONHISTORY = "rest.history";
public EasyRec(OperatorDAO operatorDAO, RemoteTenantDAO remoteTenantDAO,
ShopRecommenderService shopRecommenderService, TenantService tenantService,
TypeMappingService typeMappingService, ItemDAO itemDAO, RemoteAssocService remoteAssocService,
IDMappingDAO idMappingDAO,
//added by FK on 2012-12-18 for enabling profile data in recommendations
ProfileService profileService,
ClusterService clusterService,
String dateFormatString) {
this.operatorDAO = operatorDAO;
this.remoteTenantDAO = remoteTenantDAO;
this.shopRecommenderService = shopRecommenderService;
this.tenantService = tenantService;
this.typeMappingService = typeMappingService;
this.itemDAO = itemDAO;
this.remoteAssocService = remoteAssocService;
this.dateFormat = dateFormatString;
this.profileService = profileService;
this.idMappingDAO = idMappingDAO;
this.clusterService = clusterService;
}
@GET
@Path("/view")
public Response view(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("userid") String userId,
@QueryParam("sessionid") String sessionId, @QueryParam("itemid") String itemId,
@QueryParam("itemdescription") String itemDescription, @QueryParam("itemurl") String itemUrl,
@QueryParam("itemimageurl") String itemImageUrl, @QueryParam("actiontime") String actionTime,
@QueryParam("itemtype") String itemType, @QueryParam("callback") String callback)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_VIEW);
// Collect a List of messages for the user to understand,
// what went wrong (e.g. Wrong API key).
List<Message> messages = new ArrayList<Message>();
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
// if (r.isMaxActionLimitExceeded()) {
// messages.add(Message.MAXIMUM_ACTIONS_EXCEEDED);
// }
checkParams(coreTenantId, itemId, itemDescription, itemUrl, sessionId, messages);
Date actionDate = null;
if (actionTime != null) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
actionDate = MyUtils.dateFormatCheck(actionTime, dateFormatter);
if (actionDate == null)
messages.add(MSG.DATE_PARSE);
}
if (messages.size() > 0) {
if ((WS.JSON_PATH.equals(type)))
throw new EasyRecException(messages, WS.ACTION_VIEW, WS.RESPONSE_TYPE_JSON, callback);
else
throw new EasyRecException(messages, WS.ACTION_VIEW);
}
itemType = checkItemType(itemType, type, coreTenantId, tenantId, WS.ACTION_VIEW, callback);
Session session = new Session(sessionId, request.getRemoteAddr());
Item item = shopRecommenderService.viewItem(r, userId, itemId, itemType, itemDescription,
itemUrl, itemImageUrl, actionDate, session);
ResponseItem respItem = new ResponseItem(tenantId, WS.ACTION_VIEW, userId, sessionId, null, item);
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(respItem, callback), WS.RESPONSE_TYPE_JSCRIPT)
.build();
else
return Response.ok(respItem, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(respItem, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/rate")
public Response rate(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("userid") String userId,
@QueryParam("sessionid") String sessionId, @QueryParam("itemid") String itemId,
@QueryParam("ratingvalue") String ratingValue,
@QueryParam("itemdescription") String itemDescription, @QueryParam("itemurl") String itemUrl,
@QueryParam("itemimageurl") String itemImageUrl, @QueryParam("actiontime") String actionTime,
@QueryParam("itemtype") String itemType, @QueryParam("callback") String callback)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_RATE);
// Collect a List of messages for the user to understand,
// what went wrong (e.g. Wrong API key).
List<Message> messages = new ArrayList<Message>();
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
// if (r.isMaxActionLimitExceeded()) {
// messages.add(Message.MAXIMUM_ACTIONS_EXCEEDED);
// }
checkParams(coreTenantId, itemId, itemDescription, itemUrl, sessionId, messages);
Date actionDate = null;
if (actionTime != null) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
actionDate = MyUtils.dateFormatCheck(actionTime, dateFormatter);
if (actionDate == null)
messages.add(MSG.DATE_PARSE);
}
Integer rateValue = -1;
try {
rateValue = Integer.valueOf(ratingValue);
if (coreTenantId != null && (rateValue < tenantService.getTenantById(coreTenantId).getRatingRangeMin() ||
rateValue > tenantService.getTenantById(coreTenantId).getRatingRangeMax()))
throw new Exception();
} catch (Exception e) {
messages.add(MSG.ITEM_INVALID_RATING_VALUE);
}
if (messages.size() > 0) {
if ((WS.JSON_PATH.equals(type)))
throw new EasyRecException(messages, WS.ACTION_RATE, WS.RESPONSE_TYPE_JSON, callback);
else
throw new EasyRecException(messages, WS.ACTION_RATE);
}
itemType = checkItemType(itemType, type, coreTenantId, tenantId, WS.ACTION_RATE, callback);
Session session = new Session(sessionId, request.getRemoteAddr());
Item item = shopRecommenderService.rateItem(r, userId, itemId, itemType, itemDescription,
itemUrl, itemImageUrl, rateValue, actionDate, session);
ResponseItem respItem = new ResponseItem(tenantId, WS.ACTION_RATE, userId, sessionId, ratingValue, item);
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(respItem, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(respItem, WS.RESPONSE_TYPE_JSON).build();
} else {
return Response.ok(respItem, WS.RESPONSE_TYPE_XML).build();
}
}
@GET
@Path("/buy")
public Response buy(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("userid") String userId,
@QueryParam("sessionid") String sessionId, @QueryParam("itemid") String itemId,
@QueryParam("itemdescription") String itemDescription, @QueryParam("itemurl") String itemUrl,
@QueryParam("itemimageurl") String itemImageUrl, @QueryParam("actiontime") String actionTime,
@QueryParam("itemtype") String itemType, @QueryParam("callback") String callback)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_BUY);
// Collect a List of messages for the user to understand,
// what went wrong (e.g. Wrong API key).
List<Message> messages = new ArrayList<Message>();
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
// if (r.isMaxActionLimitExceeded()) {
// messages.add(Message.MAXIMUM_ACTIONS_EXCEEDED);
// }
checkParams(coreTenantId, itemId, itemDescription, itemUrl, sessionId, messages);
Date actionDate = null;
if (actionTime != null) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
actionDate = MyUtils.dateFormatCheck(actionTime, dateFormatter);
if (actionDate == null)
messages.add(MSG.DATE_PARSE);
}
if (messages.size() > 0) {
if ((WS.JSON_PATH.equals(type)))
throw new EasyRecException(messages, WS.ACTION_BUY, WS.RESPONSE_TYPE_JSON, callback);
else
throw new EasyRecException(messages, WS.ACTION_BUY);
}
itemType = checkItemType(itemType, type, coreTenantId, tenantId, WS.ACTION_BUY, callback);
Session session = new Session(sessionId, request.getRemoteAddr());
Item item = shopRecommenderService.purchaseItem(r, userId, itemId, itemType, itemDescription,
itemUrl, itemImageUrl, actionDate, session);
ResponseItem respItem = new ResponseItem(tenantId, WS.ACTION_BUY, userId, sessionId, null, item);
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(respItem, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(respItem, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(respItem, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/sendaction")
public Response sendAction(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("userid") String userId,
@QueryParam("sessionid") String sessionId, @QueryParam("itemid") String itemId,
@QueryParam("actiontype") String actionType, @QueryParam("actionvalue") String actionValue,
@QueryParam("itemdescription") String itemDescription, @QueryParam("itemurl") String itemUrl,
@QueryParam("itemimageurl") String itemImageUrl, @QueryParam("actiontime") String actionTime,
@QueryParam("itemtype") String itemType, @QueryParam("callback") String callback)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_ACTION);
// Collect a List of messages for the user to understand,
// what went wrong (e.g. Wrong API key).
List<Message> messages = new ArrayList<Message>();
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
// if (r.isMaxActionLimitExceeded()) {
// messages.add(Message.MAXIMUM_ACTIONS_EXCEEDED);
// }
checkParams(coreTenantId, itemId, itemDescription, itemUrl, sessionId, messages);
Integer actValue = -1;
if (Strings.isNullOrEmpty(actionType)) {
messages.add(MSG.MISSING_ACTIONTYPE);
} else {
Boolean hasValue = tenantService.hasActionValue(coreTenantId, actionType);
if (hasValue == null) {
messages.add(MSG.INVALID_ACTIONTYPE);
} else {
if (hasValue) {
if (Strings.isNullOrEmpty(actionValue)) {
messages.add(MSG.MISSING_ACTION_VALUE);
} else {
try {
actValue = Integer.valueOf(actionValue);
} catch (Exception e) {
messages.add(MSG.ITEM_INVALID_RATING_VALUE);
}
}
}
}
}
Date actionDate = null;
if (actionTime != null) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
actionDate = MyUtils.dateFormatCheck(actionTime, dateFormatter);
if (actionDate == null)
messages.add(MSG.DATE_PARSE);
}
if (messages.size() > 0) {
if ((WS.JSON_PATH.equals(type)))
throw new EasyRecException(messages, WS.ACTION_SENDACTION, WS.RESPONSE_TYPE_JSON, callback);
else
throw new EasyRecException(messages, WS.ACTION_SENDACTION);
}
itemType = checkItemType(itemType, type, coreTenantId, tenantId, WS.ACTION_RATE, callback);
Session session = new Session(sessionId, request.getRemoteAddr());
Item item = shopRecommenderService.sendAction(r, userId, itemId, itemType, itemDescription,
itemUrl, itemImageUrl, actionType, actValue, actionDate, session);
ResponseItem respItem = new ResponseItem(tenantId, WS.ACTION_SENDACTION, userId, sessionId, actionValue, item);
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(respItem, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(respItem, WS.RESPONSE_TYPE_JSON).build();
} else {
return Response.ok(respItem, WS.RESPONSE_TYPE_XML).build();
}
}
@GET
@Path("/otherusersalsoviewed")
public Response otherUsersAlsoViewed(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("userid") String userId,
@QueryParam("sessionid") String sessionId, @QueryParam("itemid") String itemId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("itemtype") String itemType,
@QueryParam("requesteditemtype") String requestedItemType,
@QueryParam("callback") String callback,
@QueryParam("withProfile") @DefaultValue("false") boolean withProfile) throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_ALSO_VIEWED);
Recommendation rec = null;
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_OTHER_USERS_ALSO_VIEWED, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
if (r.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_OTHER_USERS_ALSO_VIEWED, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
itemType = checkItemType(itemType, type, coreTenantId, tenantId, WS.ACTION_OTHER_USERS_ALSO_VIEWED, callback);
requestedItemType = checkItemType(requestedItemType, type, coreTenantId, tenantId, WS.ACTION_OTHER_USERS_ALSO_VIEWED, callback, null);
Session session = new Session(sessionId, request);
try {
if ((numberOfResults == null) || (numberOfResults > WS.DEFAULT_NUMBER_OF_RESULTS))
numberOfResults = WS.DEFAULT_NUMBER_OF_RESULTS;
rec = shopRecommenderService.alsoViewedItems(coreTenantId, userId, itemId, itemType, requestedItemType,
session, numberOfResults);
//added by FK on 2012-12-18 for adding profile data to recommendations.
if (withProfile) {
addProfileDataToItems(rec);
}
} catch (EasyRecRestException sre) {
exceptionResponse(WS.ACTION_OTHER_USERS_ALSO_VIEWED, sre.getMessageObject(), type,
callback);
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(rec, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(rec, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(rec, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/recommendationsforuser")
public Response recommendationsForUser(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("userid") String userId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("requesteditemtype") String requestedItemType,
@QueryParam("callback") String callback,
@QueryParam("actiontype") @DefaultValue(TypeMappingService.ACTION_TYPE_VIEW) String actiontype,
@QueryParam("withProfile") @DefaultValue("false") boolean withProfile)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_RECS_FOR_USER);
Recommendation rec = null;
Session session = new Session(null, request);
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_RECOMMENDATIONS_FOR_USER, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
RemoteTenant remoteTenant = remoteTenantDAO.get(coreTenantId);
if (remoteTenant.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_RECOMMENDATIONS_FOR_USER, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
if (Strings.isNullOrEmpty(userId))
exceptionResponse(WS.ACTION_RECOMMENDATIONS_FOR_USER, MSG.USER_NO_ID, type, callback);
requestedItemType = checkItemType(requestedItemType, type, coreTenantId, tenantId, WS.ACTION_RECOMMENDATIONS_FOR_USER, callback, null);
if (typeMappingService.getIdOfActionType(coreTenantId, actiontype) == null) {
exceptionResponse(WS.ACTION_RECOMMENDATIONS_FOR_USER, MSG.OPERATION_FAILED.append(String.format(" actionType %s not found for tenant %s", actiontype, tenantId)), type, callback);
}
if ((numberOfResults == null) || (numberOfResults > WS.DEFAULT_NUMBER_OF_RESULTS))
numberOfResults = WS.DEFAULT_NUMBER_OF_RESULTS;
if (rec == null || rec.getRecommendedItems().isEmpty()) {
try {
rec = shopRecommenderService.itemsBasedOnActionHistory(coreTenantId, userId, session, actiontype, null, WS.ACTION_HISTORY_DEPTH, null,
requestedItemType, numberOfResults);
//added by FK on 2012-12-18 for adding profile data to recommendations.
if (withProfile) {
addProfileDataToItems(rec);
}
} catch (EasyRecRestException sre) {
exceptionResponse(WS.ACTION_RECOMMENDATIONS_FOR_USER, sre.getMessageObject(), type, callback);
}
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(rec, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(rec, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(rec, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/actionhistoryforuser")
public Response actionHistoryForUser(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("userid") String userId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("requesteditemtype") String requestedItemType,
@QueryParam("callback") String callback,
@QueryParam("actiontype") @DefaultValue(TypeMappingService.ACTION_TYPE_VIEW) String actiontype)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_ACTIONHISTORY);
Recommendation rec = null;
Session session = new Session(null, request);
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_HISTORY, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
RemoteTenant remoteTenant = remoteTenantDAO.get(coreTenantId);
if (remoteTenant.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_HISTORY, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
if (Strings.isNullOrEmpty(userId))
exceptionResponse(WS.ACTION_HISTORY, MSG.USER_NO_ID, type, callback);
requestedItemType = checkItemType(requestedItemType, type, coreTenantId, tenantId, WS.ACTION_HISTORY, callback, null);
if (typeMappingService.getIdOfActionType(coreTenantId, actiontype) == null) {
exceptionResponse(WS.ACTION_HISTORY, MSG.OPERATION_FAILED.append(String.format(" actionType %s not found for tenant %s", actiontype, tenantId)), type, callback);
}
if ((numberOfResults == null) || (numberOfResults > WS.DEFAULT_NUMBER_OF_RESULTS))
numberOfResults = WS.DEFAULT_NUMBER_OF_RESULTS;
if (rec == null || rec.getRecommendedItems().isEmpty()) {
try {
rec = shopRecommenderService.actionHistory(coreTenantId, userId, session, actiontype, requestedItemType, numberOfResults + 5, numberOfResults); // +5 to compensate for inactive items
} catch (EasyRecRestException sre) {
exceptionResponse(WS.ACTION_HISTORY, sre.getMessageObject(), type, callback);
}
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(rec, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(rec, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(rec, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/otherusersalsobought")
public Response otherUsersAlsoBought(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("userid") String userId,
@QueryParam("sessionid") String sessionId, @QueryParam("itemid") String itemId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("itemtype") String itemType,
@QueryParam("requesteditemtype") String requestedItemType,
@QueryParam("callback") String callback,
@QueryParam("withProfile") @DefaultValue("false") boolean withProfile)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_ALSO_BOUGHT);
Recommendation rec = null;
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_OTHER_USERS_ALSO_BOUGHT, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
if (r.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_OTHER_USERS_ALSO_BOUGHT, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
itemType = checkItemType(itemType, type, coreTenantId, tenantId, WS.ACTION_OTHER_USERS_ALSO_BOUGHT, callback);
requestedItemType = checkItemType(requestedItemType, type, coreTenantId, tenantId, WS.ACTION_OTHER_USERS_ALSO_BOUGHT, callback, null);
Session session = new Session(sessionId, request);
try {
if ((numberOfResults == null) || (numberOfResults > WS.DEFAULT_NUMBER_OF_RESULTS))
numberOfResults = WS.DEFAULT_NUMBER_OF_RESULTS;
rec = shopRecommenderService.alsoBoughtItems(coreTenantId, userId, itemId, itemType, requestedItemType,
session, numberOfResults);
//added by FK on 2012-12-18 for adding profile data to recommendations.
if (withProfile) {
addProfileDataToItems(rec);
}
} catch (EasyRecRestException sre) {
exceptionResponse(WS.ACTION_OTHER_USERS_ALSO_BOUGHT, sre.getMessageObject(), type, callback);
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(rec, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(rec, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(rec, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/itemsratedgoodbyotherusers")
public Response itemsRatedGoodByOtherUsers(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId,
@QueryParam("userid") String userId,
@QueryParam("sessionid") String sessionId,
@QueryParam("itemid") String itemId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("itemtype") String itemType,
@QueryParam("requesteditemtype") String requestedItemType,
@QueryParam("callback") String callback,
@QueryParam("withProfile") @DefaultValue("false") boolean withProfile) throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_ALSO_RATED);
Recommendation rec = null;
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_ITEMS_RATED_GOOD_BY_OTHER_USERS, MSG.TENANT_WRONG_TENANT_APIKEY, type,
callback);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
if (r.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_ITEMS_RATED_GOOD_BY_OTHER_USERS, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
itemType = checkItemType(itemType, type, coreTenantId, tenantId, WS.ACTION_ITEMS_RATED_GOOD_BY_OTHER_USERS, callback);
requestedItemType = checkItemType(requestedItemType, type, coreTenantId, tenantId, WS.ACTION_ITEMS_RATED_GOOD_BY_OTHER_USERS, callback, null);
Session session = new Session(sessionId, request);
try {
if ((numberOfResults == null) || (numberOfResults > WS.DEFAULT_NUMBER_OF_RESULTS))
numberOfResults = WS.DEFAULT_NUMBER_OF_RESULTS;
rec = shopRecommenderService.alsoGoodRatedItems(coreTenantId, userId, itemId, itemType, requestedItemType,
session, numberOfResults);
//added by FK on 2012-12-18 for adding profile data to recommendations.
if (withProfile) {
addProfileDataToItems(rec);
}
} catch (EasyRecRestException sre) {
exceptionResponse(WS.ACTION_ITEMS_RATED_GOOD_BY_OTHER_USERS, sre.getMessageObject(),
type, callback);
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(rec, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(rec, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(rec, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/mostboughtitems")
public Response mostBoughtItems(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("timeRange") String timeRange,
@QueryParam("startDate") String startDate, @QueryParam("endDate") String endDate,
@QueryParam("requesteditemtype") String requesteditemtype,
@QueryParam("clusterid") String clusterId,
@QueryParam("callback") String callback,
@QueryParam("withProfile") @DefaultValue("false") boolean withProfile) throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_MOST_BOUGHT);
Recommendation rr = null;
Integer cluster = null;
if (clusterId != null) {
cluster = this.idMappingDAO.lookup(clusterId);
}
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_MOST_BOUGHT, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
if (r.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_MOST_BOUGHT, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
TimeConstraintVO tc = checkTimeConstraints(startDate, endDate);
if (tc == null)
exceptionResponse(WS.ACTION_MOST_BOUGHT, MSG.DATE_PARSE, type, callback);
requesteditemtype = checkItemType(requesteditemtype, type, coreTenantId, tenantId, WS.ACTION_MOST_BOUGHT, callback, null);
List<Item> items;
if (tc != null) {
items = shopRecommenderService.mostBoughtItems(coreTenantId, requesteditemtype,
cluster, numberOfResults != null ? numberOfResults : WS.DEFAULT_NUMBER_OF_RESULTS, timeRange, tc,
new Session(null, request));
rr = new Recommendation(tenantId, WS.ACTION_MOST_BOUGHT, null, null, null, items);
//added by FK on 2012-12-18 for adding profile data to recommendations.
if (withProfile) {
addProfileDataToItems(rr);
}
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(rr, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(rr, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(rr, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/mostvieweditems")
public Response mostViewedItems(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("timeRange") String timeRange,
@QueryParam("startDate") String startDate, @QueryParam("endDate") String endDate,
@QueryParam("requesteditemtype") String requestedItemType,
@QueryParam("clusterid") String clusterId,
@QueryParam("callback") String callback,
@QueryParam("withProfile") @DefaultValue("false") boolean withProfile)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_MOST_VIEWED);
Recommendation rr = null;
Integer cluster = null;
if (clusterId != null) {
cluster = this.idMappingDAO.lookup(clusterId);
}
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_MOST_VIEWED, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
if (r.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_MOST_VIEWED, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
TimeConstraintVO tc = checkTimeConstraints(startDate, endDate);
if (tc == null)
exceptionResponse(WS.ACTION_MOST_VIEWED, MSG.DATE_PARSE, type, callback);
requestedItemType = checkItemType(requestedItemType, type, coreTenantId, tenantId, WS.ACTION_MOST_VIEWED, callback, null);
List<Item> items;
if (tc != null) {
items = shopRecommenderService.mostViewedItems(coreTenantId, requestedItemType,
cluster, numberOfResults != null ? numberOfResults : WS.DEFAULT_NUMBER_OF_RESULTS, timeRange, tc,
new Session(null, request));
rr = new Recommendation(tenantId, WS.ACTION_MOST_VIEWED, null, null, null, items);
//added by FK on 2012-12-18 for adding profile data to recommendations.
if (withProfile) {
addProfileDataToItems(rr);
}
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(rr, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(rr, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(rr, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/mostrateditems")
public Response mostRatedItems(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("timeRange") String timeRange, @QueryParam("startDate") String startDate,
@QueryParam("endDate") String endDate,
@QueryParam("requesteditemtype") String requestedItemType,
@QueryParam("clusterid") String clusterId,
@QueryParam("callback") String callback,
@QueryParam("withProfile") @DefaultValue("false") boolean withProfile) throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_MOST_RATED);
Recommendation rr = null;
Integer cluster = null;
if (clusterId != null) {
cluster = this.idMappingDAO.lookup(clusterId);
}
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_MOST_RATED, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
if (r.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_MOST_RATED, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
TimeConstraintVO tc = checkTimeConstraints(startDate, endDate);
if (tc == null)
exceptionResponse(WS.ACTION_MOST_RATED, MSG.DATE_PARSE, type, callback);
requestedItemType = checkItemType(requestedItemType, type, coreTenantId, tenantId, WS.ACTION_MOST_RATED, callback, null);
List<Item> items;
if (tc != null) {
items = shopRecommenderService.mostRatedItems(coreTenantId, requestedItemType,
cluster, numberOfResults != null ? numberOfResults : WS.DEFAULT_NUMBER_OF_RESULTS,
timeRange, tc, new Session(null, request));
rr = new Recommendation(tenantId, WS.ACTION_MOST_RATED, null, null, null, items);
//added by FK on 2012-12-18 for adding profile data to recommendations.
if (withProfile) {
addProfileDataToItems(rr);
}
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(rr, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(rr, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(rr, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/itemsofcluster")
public Response getItemsOfCluster(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId,
@QueryParam("clusterid") String clusterId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("strategy") String strategy,
@QueryParam("usefallback") @DefaultValue("false") Boolean useFallback,
@QueryParam("requesteditemtype") String requestedItemType,
@QueryParam("callback") String callback,
@QueryParam("withProfile") @DefaultValue("false") boolean withProfile) {
Monitor monitor = MonitorFactory.start(JAMON_REST_ITEMS_OF_CLUSTERS);
Recommendation recommendation = null;
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_ITEMS_OF_CLUSTER, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
RemoteTenant remoteTenant = remoteTenantDAO.get(coreTenantId);
if (remoteTenant.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_ITEMS_OF_CLUSTER, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
if (clusterId == null)
exceptionResponse(WS.ACTION_ITEMS_OF_CLUSTER, MSG.CLUSTER_NO_ID, type, callback);
requestedItemType = checkItemType(requestedItemType, type, coreTenantId, tenantId, WS.ACTION_ITEMS_OF_CLUSTER, callback, null);
List<Item> items;
if (clusterId != null)
try {
Integer coreItemType = typeMappingService.getIdOfItemType(coreTenantId, requestedItemType);
items = shopRecommenderService.itemsOfCluster(coreTenantId, clusterId,
numberOfResults != null ? numberOfResults : WS.DEFAULT_NUMBER_OF_RESULTS, strategy, useFallback,
coreItemType, new Session(null, request));
recommendation = new Recommendation(tenantId, WS.ACTION_ITEMS_OF_CLUSTER, null, null, null, items);
//added by FK on 2012-12-18 for adding profile data to recommendations.
if (withProfile) {
addProfileDataToItems(recommendation);
}
} catch (EasyRecRestException sre) {
exceptionResponse(WS.ACTION_ITEMS_OF_CLUSTER, sre.getMessageObject(), type,
callback);
}
monitor.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(recommendation, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(recommendation, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(recommendation, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/bestrateditems")
public Response bestRatedItems(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("userid") String userId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("timeRange") String timeRange, @QueryParam("startDate") String startDate,
@QueryParam("endDate") String endDate,
@QueryParam("requesteditemtype") String requestedItemType,
@QueryParam("callback") String callback,
@QueryParam("withProfile") @DefaultValue("false") boolean withProfile)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_BEST_RATED);
Recommendation rr = null;
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_BEST_RATED, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
if (r.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_BEST_RATED, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
TimeConstraintVO tc = checkTimeConstraints(startDate, endDate);
if (tc == null)
exceptionResponse(WS.ACTION_BEST_RATED, MSG.DATE_PARSE, type, callback);
requestedItemType = checkItemType(requestedItemType, type, coreTenantId, tenantId, WS.ACTION_BEST_RATED, callback, null);
List<Item> items;
if (tc != null) {
items = shopRecommenderService.bestRatedItems(coreTenantId, userId, requestedItemType,
numberOfResults != null ? numberOfResults : WS.DEFAULT_NUMBER_OF_RESULTS, timeRange, tc,
new Session(null, request));
rr = new Recommendation(tenantId, WS.ACTION_BEST_RATED, null, null, null, items);
//added by FK on 2012-12-18 for adding profile data to recommendations.
if (withProfile) {
addProfileDataToItems(rr);
}
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(rr, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(rr, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(rr, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/worstrateditems")
public Response worstRatedItems(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("userid") String userId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("timeRange") String timeRange,
@QueryParam("startDate") String startDate, @QueryParam("endDate") String endDate,
@QueryParam("requesteditemtype") String requestedItemType,
@QueryParam("callback") String callback,
@QueryParam("withProfile") @DefaultValue("false") boolean withProfile)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_WORST_RATED);
Recommendation rr = null;
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_WORST_RATED, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
if (r.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_WORST_RATED, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
TimeConstraintVO tc = checkTimeConstraints(startDate, endDate);
if (tc == null)
exceptionResponse(WS.ACTION_WORST_RATED, MSG.DATE_PARSE, type, callback);
requestedItemType = checkItemType(requestedItemType, type, coreTenantId, tenantId, WS.ACTION_WORST_RATED, null, callback);
List<Item> items;
if (tc != null) {
items = shopRecommenderService.worstRatedItems(coreTenantId, userId, requestedItemType,
numberOfResults != null ? numberOfResults : WS.DEFAULT_NUMBER_OF_RESULTS, timeRange, tc,
new Session(null, request));
rr = new Recommendation(tenantId, WS.ACTION_WORST_RATED, null, null, null, items);
//added by FK on 2012-12-18 for adding profile data to recommendations.
if (withProfile) {
addProfileDataToItems(rr);
}
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(rr, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(rr, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(rr, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/relateditems")
public Response relatedItems(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId,
@QueryParam("assoctype") String assocType, @QueryParam("userid") String userId,
@QueryParam("sessionid") String sessionId, @QueryParam("itemid") String itemId,
@QueryParam("numberOfResults") Integer numberOfResults,
@QueryParam("itemtype") String itemType,
@QueryParam("requesteditemtype") String requestedItemType,
@QueryParam("callback") String callback,
@QueryParam("withProfile") @DefaultValue("false") boolean withProfile)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_RELATED_ITEMS);
Recommendation rec = null;
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
Integer assocTypeId = null;
if (coreTenantId == null)
exceptionResponse(WS.ACTION_RELATED_ITEMS, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
if (r.isMaxActionLimitExceeded())
exceptionResponse(WS.ACTION_RELATED_ITEMS, MSG.MAXIMUM_ACTIONS_EXCEEDED, type, callback);
if (itemId == null)
exceptionResponse(WS.ACTION_RELATED_ITEMS, MSG.ITEM_NO_ID, type, callback);
if (assocType != null) {
assocTypeId = typeMappingService.getIdOfAssocType(coreTenantId, assocType, Boolean.TRUE); // only visible assocTypes can be queried
if (assocTypeId == null)
exceptionResponse(WS.ACTION_RELATED_ITEMS, MSG.ASSOC_TYPE_DOES_NOT_EXIST, type, callback);
} else {
assocType = AssocTypeDAO.ASSOCTYPE_IS_RELATED;
}
itemType = checkItemType(itemType, type, coreTenantId, tenantId, WS.ACTION_RELATED_ITEMS, callback);
requestedItemType = checkItemType(requestedItemType, type, coreTenantId, tenantId, WS.ACTION_RELATED_ITEMS, callback, null);
Session session = new Session(null, request);
try {
if ((numberOfResults == null) || (numberOfResults > WS.DEFAULT_NUMBER_OF_RESULTS))
numberOfResults = WS.DEFAULT_NUMBER_OF_RESULTS;
rec = shopRecommenderService.relatedItems(coreTenantId, assocType, userId, itemId, itemType, requestedItemType, session,
numberOfResults);
//added by FK on 2012-12-18 for adding profile data to recommendations.
if (withProfile) {
addProfileDataToItems(rec);
}
} catch (EasyRecRestException e) {
exceptionResponse(WS.ACTION_RELATED_ITEMS, e.getMessageObject(), type,
callback);
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(rec, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(rec, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(rec, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/setitemactive")
public Response setItemActive(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("itemid") String itemId,
@QueryParam("active") Boolean active, @QueryParam("itemtype") String itemType,
@QueryParam("callback") String callback) throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_ITEM_ACTIVE);
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_SET_ITEM_ACTIVE, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
if (itemId == null)
exceptionResponse(WS.ACTION_SET_ITEM_ACTIVE, MSG.ITEM_NO_ID, type, callback);
if (active == null)
exceptionResponse(WS.ACTION_SET_ITEM_ACTIVE, MSG.ITEM_NO_ACTIVE, type, callback);
itemType = checkItemType(itemType, type, coreTenantId, tenantId, WS.ACTION_SET_ITEM_ACTIVE, callback);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
Item item = itemDAO.get(r, itemId, itemType);
if (item == null)
exceptionResponse(WS.ACTION_SET_ITEM_ACTIVE, MSG.ITEM_NOT_EXISTS, type, callback);
else {
if (item.isActive() && !active)
itemDAO.deactivate(coreTenantId, itemId, itemType);
if (!item.isActive() && active)
itemDAO.activate(coreTenantId, itemId, itemType);
}
ResponseItem respItem = new ResponseItem(tenantId, WS.ACTION_SET_ITEM_ACTIVE + active, null, null, null, item);
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(respItem, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(respItem, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(respItem, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/itemtypes")
public Response itemTypes(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("callback") String callback)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_ITEMTYPES);
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_ITEMTYPES, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
ResponseItemTypes responseItemTypes = null;
try {
Set<String> itemTypes = shopRecommenderService.getItemTypes(coreTenantId);
responseItemTypes = new ResponseItemTypes(tenantId, itemTypes);
} catch (EasyRecRestException e) {
exceptionResponse(WS.ACTION_ITEMTYPES, e.getMessageObject().append("Failed to retrieve item types"), type,
callback);
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null) {
return Response.ok(new JSONWithPadding(responseItemTypes, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
} else {
return Response.ok(responseItemTypes, WS.RESPONSE_TYPE_JSON).build();
}
} else {
return Response.ok(responseItemTypes, WS.RESPONSE_TYPE_XML).build();
}
}
@GET
@Path("/clusters")
public Response clusters(@PathParam("type") String type, @QueryParam("apikey") String apiKey,
@QueryParam("tenantid") String tenantId, @QueryParam("callback") String callback)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_CLUSTERS);
Integer coreTenantId = operatorDAO.getTenantId(apiKey, tenantId);
if (coreTenantId == null)
exceptionResponse(WS.ACTION_CLUSTERS, MSG.TENANT_WRONG_TENANT_APIKEY, type, callback);
ResponseClusters responseClusters = null;
try {
List<ClusterVO> clusters = shopRecommenderService.getClusters(coreTenantId);
responseClusters = new ResponseClusters(tenantId, clusters);
} catch (EasyRecRestException e) {
exceptionResponse(WS.ACTION_CLUSTERS, e.getMessageObject().append("Failed to retrieve clusters"), type,
callback);
}
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null) {
return Response.ok(new JSONWithPadding(responseClusters, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
} else {
return Response.ok(responseClusters, WS.RESPONSE_TYPE_JSON).build();
}
} else {
return Response.ok(responseClusters, WS.RESPONSE_TYPE_XML).build();
}
}
///////////////////////////////////////////////////////////////////////////
// import API
///////////////////////////////////////////////////////////////////////////
@GET
@Path("/importrule")
public Response importrule(@PathParam("type") String type, @QueryParam("token") String token,
@QueryParam("tenantid") String tenantId, @QueryParam("itemfromid") String itemFromId,
@QueryParam("itemfromtype") String itemFromType, @QueryParam("itemtoid") String itemToId,
@QueryParam("itemtotype") String itemToType, @QueryParam("assocvalue") String assocvalue,
@QueryParam("assoctype") String assocType, @QueryParam("callback") String callback)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_IMPORT_RULE);
Item itemFrom = null;
Item itemTo = null;
Float assocValue = null;
Integer assocTypeId = null;
Integer coreTenantId = null;
// Collect a List of messages for the user to understand,
// what went wrong (e.g. Wrong API key).
List<Message> messages = Lists.newArrayList();
Operator o = operatorDAO.getOperatorFromToken(token);
if (itemFromType != null) itemFromType = CharMatcher.WHITESPACE.trimFrom(itemFromType);
if (itemToType != null) itemToType = CharMatcher.WHITESPACE.trimFrom(itemToType);
if (Strings.isNullOrEmpty(itemFromType)) itemFromType = Item.DEFAULT_STRING_ITEM_TYPE;
if (Strings.isNullOrEmpty(itemToType)) itemToType = Item.DEFAULT_STRING_ITEM_TYPE;
// TODO create itemtypes if they don't exist?
if (o != null) {
coreTenantId = operatorDAO.getTenantId(o.getApiKey(), tenantId);
if (itemFromId != null && itemFromId.equals(itemToId))
messages.add(MSG.ITEMFROM_EQUAL_ITEMTO);
RemoteTenant r = remoteTenantDAO.get(coreTenantId);
if (r != null) {
itemFrom = itemDAO.get(r, itemFromId, itemFromType);
if (itemFrom == null)
messages.add(MSG.ITEM_FROM_ID_DOES_NOT_EXIST);
itemTo = itemDAO.get(r, itemToId, itemToType);
if (itemTo == null)
messages.add(MSG.ITEM_TO_ID_DOES_NOT_EXIST);
try {
assocTypeId = typeMappingService.getIdOfAssocType(coreTenantId, assocType);
} catch (Exception e) {
messages.add(MSG.ASSOC_TYPE_DOES_NOT_EXIST);
}
} else
messages.add(MSG.TENANT_WRONG_TENANT);
try {
assocValue = Float.parseFloat(assocvalue);
if (assocValue < 0 || assocValue > 100)
messages.add(MSG.INVALID_ASSOC_VALUE);
} catch (Exception e) {
messages.add(MSG.INVALID_ASSOC_VALUE);
}
} else
messages.add(MSG.WRONG_TOKEN);
if (messages.size() > 0) {
if ((WS.JSON_PATH.equals(type)))
throw new EasyRecException(messages, WS.ACTION_IMPORT_RULE, WS.RESPONSE_TYPE_JSON, callback);
else
throw new EasyRecException(messages, WS.ACTION_IMPORT_RULE);
}
remoteAssocService.addRule(coreTenantId, itemFromId, itemFromType, itemToId, itemToType, assocTypeId,
assocValue);
ResponseRule respRule =
new ResponseRule(tenantId, WS.ACTION_IMPORT_RULE, itemFrom.getItemId(), itemTo.getItemId(), assocType,
Float.toString(assocValue));
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(respRule, callback), WS.RESPONSE_TYPE_JSCRIPT).build();
else
return Response.ok(respRule, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(respRule, WS.RESPONSE_TYPE_XML).build();
}
@GET
@Path("/importitem")
public Response importitem(@PathParam("type") String type, @QueryParam("token") String token,
@QueryParam("tenantid") String tenantId, @QueryParam("itemid") String itemId,
@QueryParam("itemdescription") String itemDescription,
@QueryParam("itemurl") String itemUrl, @QueryParam("itemimageurl") String itemImageUrl,
@QueryParam("itemtype") String itemType,
@QueryParam("callback") String callback) throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_IMPORT_ITEM);
// Collect a List of messages for the user to understand,
// what went wrong (e.g. Wrong API key).
List<Message> messages = new ArrayList<Message>();
Integer coreTenantId = null;
Operator o = operatorDAO.getOperatorFromToken(token);
if (o != null) {
coreTenantId = operatorDAO.getTenantId(o.getApiKey(), tenantId);
checkParameters(coreTenantId, itemId, itemDescription, itemUrl, messages);
} else
messages.add(MSG.WRONG_TOKEN);
if (messages.size() > 0) {
if ((WS.JSON_PATH.equals(type)))
throw new EasyRecException(messages, WS.ACTION_IMPORT_ITEM, WS.RESPONSE_TYPE_JSON, callback);
else
throw new EasyRecException(messages, WS.ACTION_IMPORT_ITEM);
}
itemType = checkItemType(itemType, type, coreTenantId, tenantId, WS.ACTION_IMPORT_ITEM, callback);
itemDAO.insertOrUpdate(coreTenantId, itemId, itemType, itemDescription, itemUrl, itemImageUrl);
ResponseItem respItem = new ResponseItem(tenantId, WS.ACTION_IMPORT_ITEM, null, null, null,
itemDAO.get(remoteTenantDAO.get(coreTenantId), itemId, itemType));
mon.stop();
if (WS.JSON_PATH.equals(type)) {
if (callback != null)
return Response.ok(new JSONWithPadding(respItem, callback), WS.RESPONSE_TYPE_JSCRIPT)
.build();
else
return Response.ok(respItem, WS.RESPONSE_TYPE_JSON).build();
} else
return Response.ok(respItem, WS.RESPONSE_TYPE_XML).build();
}
/**
* With this call you can create a new cluster.
*
* @param type "1.0" for XML response, "1.0/json" for JSON
* @param token
* @param tenantId
* @param clusterId
* @param clusterDescription
* @param clusterParent
* @param callback
* @return
* @throws EasyRecException
*/
@GET
@Path("/createcluster")
public Response createcluster(@PathParam("type") String type,
@QueryParam("token") String token,
@QueryParam("tenantid") String tenantId,
@QueryParam("clusterid") String clusterId,
@QueryParam("clusterdescription") String clusterDescription,
@DefaultValue("CLUSTERS") @QueryParam("clusterparent") String clusterParent,
@QueryParam("callback") String callback)
throws EasyRecException {
Monitor mon = MonitorFactory.start(JAMON_REST_CREATE_CLUSTER);
// Collect a List of messages for the user to understand,
// what went wrong (e.g. Wrong API key).
List<Message> errorMessages = new ArrayList<Message>();
List<Message> successMessages = new ArrayList<Message>();
Integer coreTenantId = null;
Operator o = operatorDAO.getOperatorFromToken(token);
if (o != null) {
coreTenantId = operatorDAO.getTenantId(o.getApiKey(), tenantId);
checkParameters(coreTenantId, clusterId, errorMessages);
} else
errorMessages.add(MSG.WRONG_TOKEN);
if (errorMessages.size() > 0) {
if ((WS.JSON_PATH.equals(type)))
throw new EasyRecException(errorMessages, WS.ACTION_CREATE_CLUSTER, WS.RESPONSE_TYPE_JSON, callback);
else
throw new EasyRecException(errorMessages, WS.ACTION_CREATE_CLUSTER);
}
try {
clusterService.addCluster(coreTenantId, clusterId, clusterDescription, clusterParent);
} catch (ClusterException e) {
// ToDo: more fine-grained Exceptions and consequently more specific error numbers
errorMessages.add(new ErrorMessage(799, e.getMessage()));
}
successMessages.add(MSG.CLUSTER_SUCCESSFULLY_CREATED);
Response response = formatResponse(successMessages, errorMessages,
WS.ACTION_CREATE_CLUSTER, type, callback);
mon.stop();
return response;
}
// private methods
private void addProfileDataToItems(Recommendation recommendation) {
for (Item item : recommendation.getRecommendedItems()) {
item.setProfileData(profileService.getProfile(item));
}
}
private void exceptionResponse(String operation, Message message, String type, String callback)
throws EasyRecException {
List<Message> messages = new ArrayList<Message>();
messages.add(message);
if ((WS.JSON_PATH.equals(type)))
throw new EasyRecException(messages, operation, WS.RESPONSE_TYPE_JSON, callback);
else
throw new EasyRecException(messages, operation);
}
private void checkParameters(Integer coreTenantId, String itemId, String itemDescription, String itemUrl,
List<Message> messages) throws EasyRecException {
if (coreTenantId == null)
messages.add(MSG.TENANT_WRONG_TENANT_APIKEY);
if (Strings.isNullOrEmpty(itemId))
messages.add(MSG.ITEM_NO_ID);
if (Strings.isNullOrEmpty(itemDescription)) {
messages.add(MSG.ITEM_NO_DESCRIPTION);
} else {
if (itemDescription.length() > 500) {
itemDescription = itemDescription.substring(0, 499);
}
}
if (itemUrl == null)
messages.add(MSG.ITEM_NO_URL);
}
private void checkParameters(Integer coreTenantId, String clusterID,
List<Message> messages) throws EasyRecException {
if (coreTenantId == null)
messages.add(MSG.TENANT_WRONG_TENANT_APIKEY);
if (clusterID == null)
messages.add(MSG.CLUSTER_NO_ID);
}
private void checkParams(Integer coreTenantId, String itemId, String itemDescription, String itemUrl,
String sessionId, List<Message> messages) throws EasyRecException {
checkParameters(coreTenantId, itemId, itemDescription, itemUrl, messages);
if (Strings.isNullOrEmpty(sessionId))
messages.add(MSG.USER_NO_SESSION_ID);
}
private String checkItemType(String itemType, String type, Integer coreTenantId, String tenantId, String operation,
String callback) {
return checkItemType(itemType, type, coreTenantId, tenantId, operation, callback, Item.DEFAULT_STRING_ITEM_TYPE);
}
private String checkItemType(String itemType, String type, Integer coreTenantId, String tenantId, String operation,
String callback, @Nullable String defaultValue) {
if (itemType != null)
itemType = CharMatcher.WHITESPACE.trimFrom(itemType);
if (Strings.isNullOrEmpty(itemType))
return defaultValue;
else
try {
typeMappingService.getIdOfItemType(coreTenantId, itemType, true);
return itemType;
} catch (IllegalArgumentException ex) {
exceptionResponse(operation, MSG.OPERATION_FAILED.append(
String.format(" itemType %s not found for tenant %s", itemType, tenantId)), type, callback);
return null;
}
}
private TimeConstraintVO checkTimeConstraints(String startTime, String endTime) {
Date startDate = null;
Date endDate;
SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
if (startTime != null) {
startDate = MyUtils.dateFormatCheck(startTime, dateFormatter);
if (startDate == null)
return null;
}
if (endTime == null)
endDate = new Date(System.currentTimeMillis());
else {
endDate = MyUtils.dateFormatCheck(endTime, dateFormatter);
if (endDate == null)
return null;
}
return new TimeConstraintVO(startDate, endDate);
}
/**
* This method takes an object and creates a <code>Response</code> object
* out of it which will be returned. If <code>messages</code> contains error
* messages they will be send back instead.
* The format of the <code>Response</code>
* depends on the <code>responseType</code>.
* Supported types are <code>application/xml</code> and <code>application/json</code>
*
* @param respondData an object which will be returned as a
* <code>Response</code> object
* @param messages a list of <code>Message</code> objects which contain
* error messages of the API request
* @param responseType defines the format of the <code>Response</code> object
* @param callback if set and responseType is jason the result will be returned
* via this javascript callback function (optional)
* @return a <code>Response</code> object containing the <code>responseData</code>
* in the format defined with <code>responseType</code>
*/
private Response formatResponse(Object respondData,
List<Message> messages,
String serviceName,
String responseType,
String callback) {
//handle error messages if existing
if (messages.size() > 0) {
if ((WS.JSON_PATH.equals(responseType)))
throw new EasyRecException(messages, serviceName, WS.RESPONSE_TYPE_JSON, callback);
else
throw new EasyRecException(messages, serviceName);
}
if (respondData instanceof List) {
respondData = new ResponseSuccessMessage(serviceName, (List<SuccessMessage>) respondData);
}
//convert respondData to Respond object
if (WS.JSON_PATH.equals(responseType)) {
if (callback != null) {
return Response.ok(new JSONWithPadding(respondData, callback),
WS.RESPONSE_TYPE_JSCRIPT).build();
} else {
return Response.ok(respondData, WS.RESPONSE_TYPE_JSON).build();
}
} else if (WS.XML_PATH.equals(responseType)) {
return Response.ok(respondData, WS.RESPONSE_TYPE_XML).build();
} else {
return Response.status(Response.Status.UNSUPPORTED_MEDIA_TYPE).build();
}
}
}