/** * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at the * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Initial code contributed and copyrighted by<br> * frentix GmbH, http://www.frentix.com * <p> */ package org.olat.core.commons.services.notifications.restapi; import static org.olat.restapi.security.RestSecurityHelper.isAdmin; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.olat.basesecurity.BaseSecurity; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.services.notifications.NotificationHelper; import org.olat.core.commons.services.notifications.NotificationsManager; import org.olat.core.commons.services.notifications.Publisher; import org.olat.core.commons.services.notifications.PublisherData; import org.olat.core.commons.services.notifications.Subscriber; import org.olat.core.commons.services.notifications.SubscriptionContext; import org.olat.core.commons.services.notifications.SubscriptionInfo; import org.olat.core.commons.services.notifications.model.SubscriptionListItem; import org.olat.core.commons.services.notifications.restapi.vo.PublisherVO; import org.olat.core.commons.services.notifications.restapi.vo.SubscriberVO; import org.olat.core.commons.services.notifications.restapi.vo.SubscriptionInfoVO; import org.olat.core.commons.services.notifications.restapi.vo.SubscriptionListItemVO; import org.olat.core.id.Identity; import org.olat.core.id.context.BusinessControlFactory; import org.olat.core.id.context.ContextEntry; import org.olat.core.util.StringHelper; import org.olat.restapi.security.RestSecurityHelper; import org.olat.user.restapi.UserVO; /** * * <h3>Description:</h3> * REST API for notifications * <p> * Initial Date: 25 aug 2010 <br> * @author srosse, srosse@frentix.com, http://www.frentix.com */ @Path("notifications") public class NotificationsWebService { @GET @Path("subscribers/{ressourceName}/{ressourceId}/{subIdentifier}") @Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON}) public Response getSubscriber(@PathParam("ressourceName") String ressourceName, @PathParam("ressourceId") Long ressourceId, @PathParam("subIdentifier") String subIdentifier, @Context HttpServletRequest request) { if(!isAdmin(request)) { return Response.serverError().status(Status.UNAUTHORIZED).build(); } NotificationsManager notificationsMgr = NotificationsManager.getInstance(); SubscriptionContext subsContext = new SubscriptionContext(ressourceName, ressourceId, subIdentifier); Publisher publisher = notificationsMgr.getPublisher(subsContext); if(publisher == null) { return Response.ok().status(Status.NO_CONTENT).build(); } List<Subscriber> subscribers = notificationsMgr.getSubscribers(publisher); SubscriberVO[] subscriberVoes = new SubscriberVO[subscribers.size()]; int count = 0; for(Subscriber subscriber:subscribers) { SubscriberVO subscriberVO = new SubscriberVO(); subscriberVO.setPublisherKey(publisher.getKey()); subscriberVO.setSubscriberKey(subscriber.getKey()); subscriberVO.setIdentityKey(subscriber.getIdentity().getKey()); subscriberVoes[count++] = subscriberVO; } return Response.ok(subscriberVoes).build(); } @PUT @Path("subscribers") @Consumes({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON}) public Response subscribe(PublisherVO publisherVO, @Context HttpServletRequest request) { if(!isAdmin(request)) { return Response.serverError().status(Status.NOT_FOUND).build(); } NotificationsManager notificationsMgr = NotificationsManager.getInstance(); BaseSecurity securityManager = CoreSpringFactory.getImpl(BaseSecurity.class); SubscriptionContext subscriptionContext = new SubscriptionContext(publisherVO.getResName(), publisherVO.getResId(), publisherVO.getSubidentifier()); PublisherData publisherData = new PublisherData(publisherVO.getType(), publisherVO.getData(), publisherVO.getBusinessPath()); List<UserVO> userVoes = publisherVO.getUsers(); List<Long> identityKeys = new ArrayList<>(); for(UserVO userVo:userVoes) { identityKeys.add(userVo.getKey()); } List<Identity> identities = securityManager.loadIdentityByKeys(identityKeys); notificationsMgr.subscribe(identities, subscriptionContext, publisherData); return Response.ok().build(); } @DELETE @Path("subscribers/{subscriberKey}") @Consumes({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON}) public Response unsubscribe(@PathParam("subscriberKey") Long subscriberKey, @Context HttpServletRequest request) { if(!isAdmin(request)) { return Response.serverError().status(Status.NOT_FOUND).build(); } NotificationsManager notificationsMgr = NotificationsManager.getInstance(); if(notificationsMgr.deleteSubscriber(subscriberKey)) { return Response.ok().build(); } return Response.ok().status(Status.NOT_MODIFIED).build(); } /** * Retrieves the notification of the logged in user. * @response.representation.200.mediaType application/xml, application/json * @response.representation.200.doc The notifications * @response.representation.200.example {@link org.olat.core.commons.services.notifications.restapi.vo.Examples#SAMPLE_INFOVOes} * @response.representation.404.doc The identity not found * @param date The date (optional) * @param type The type of notifications (User, Forum...) (optional) * @param httpRequest The HTTP request * @return an xml or json representation of a the user being search. The xml * correspond to a <code>SubscriptionInfoVO</code>. <code>SubscriptionInfoVO</code> */ @GET @Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON}) public Response getNotifications(@QueryParam("date") String date, @QueryParam("type") String type, @Context HttpServletRequest httpRequest) { Identity identity = RestSecurityHelper.getIdentity(httpRequest); Locale locale = RestSecurityHelper.getLocale(httpRequest); Date compareDate; if(StringHelper.containsNonWhitespace(date)) { compareDate = parseDate(date, locale); } else { NotificationsManager man = NotificationsManager.getInstance(); compareDate = man.getCompareDateFromInterval(man.getUserIntervalOrDefault(identity)); } List<String> types = new ArrayList<String>(1); if(StringHelper.containsNonWhitespace(type)) { types.add(type); } Map<Subscriber,SubscriptionInfo> subsInfoMap = NotificationHelper.getSubscriptionMap(identity, locale, true, compareDate, types); List<SubscriptionInfoVO> voes = new ArrayList<SubscriptionInfoVO>(); for(Map.Entry<Subscriber, SubscriptionInfo> entry: subsInfoMap.entrySet()) { SubscriptionInfo info = entry.getValue(); if(info.hasNews()) { Subscriber subscriber = entry.getKey(); voes.add(createSubscriptionInfoVO(subscriber.getPublisher(), info)); } } SubscriptionInfoVO[] voesArr = new SubscriptionInfoVO[voes.size()]; voes.toArray(voesArr); return Response.ok(voesArr).build(); } private SubscriptionInfoVO createSubscriptionInfoVO(Publisher publisher, SubscriptionInfo info) { SubscriptionInfoVO infoVO = new SubscriptionInfoVO(info); if(info.getSubscriptionListItems() != null && !info.getSubscriptionListItems().isEmpty()) { List<SubscriptionListItemVO> itemVOes = new ArrayList<SubscriptionListItemVO>(info.getSubscriptionListItems().size()); String publisherType = publisher.getType(); String resourceType = publisher.getResName(); for(SubscriptionListItem item:info.getSubscriptionListItems()) { SubscriptionListItemVO itemVO = new SubscriptionListItemVO(item); //resource specific if("BusinessGroup".equals(resourceType)) { itemVO.setGroupKey(publisher.getResId()); } else if("CourseModule".equals(resourceType)) { itemVO.setCourseKey(publisher.getResId()); itemVO.setCourseNodeId(publisher.getSubidentifier()); } //publisher specififc if("Forum".equals(publisherType)) { //extract the message id List<ContextEntry> ces = BusinessControlFactory.getInstance().createCEListFromString(item.getBusinessPath()); if(ces.size() > 0) { ContextEntry lastCe = ces.get(ces.size() - 1); if("Message".equals(lastCe.getOLATResourceable().getResourceableTypeName())) { itemVO.setMessageKey(lastCe.getOLATResourceable().getResourceableId()); } } } else if("FolderModule".equals(publisherType)) { List<ContextEntry> ces = BusinessControlFactory.getInstance().createCEListFromString(item.getBusinessPath()); if(ces.size() > 0) { ContextEntry lastCe = ces.get(ces.size() - 1); if(lastCe.getOLATResourceable().getResourceableTypeName().startsWith("path=")) { String path = BusinessControlFactory.getInstance().getPath(lastCe); itemVO.setPath(path); } } } itemVOes.add(itemVO); } infoVO.setItems(itemVOes); } return infoVO; } private Date parseDate(String date, Locale locale) { if(StringHelper.containsNonWhitespace(date)) { if(date.indexOf('T') > 0) { if(date.indexOf('.') > 0) { try { return new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.S").parse(date); } catch (ParseException e) { //fail silently } } else { try { return new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss").parse(date); } catch (ParseException e) { //fail silently } } } //try with the locale if(date.length() > 10) { //probably date time try { DateFormat format = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, locale); format.setLenient(true); return format.parse(date); } catch (ParseException e) { //fail silently } } else { try { DateFormat format = DateFormat.getDateInstance(DateFormat.MEDIUM, locale); format.setLenient(true); return format.parse(date); } catch (ParseException e) { //fail silently } } } Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); cal.add(Calendar.MONTH, -1); return cal.getTime(); } }