blob: d20ec6cddcac2f7990013d85f2ca39bd7b31ead9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013-2016 LAAS-CNRS (www.laas.fr)
* 7 Colonel Roche 31077 Toulouse - France
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Initial Contributors:
* Thierry Monteil : Project manager, technical co-manager
* Mahdi Ben Alaya : Technical co-manager
* Samir Medjiah : Technical co-manager
* Khalil Drira : Strategy expert
* Guillaume Garzone : Developer
* François Aïssaoui : Developer
*
* New contributors :
*******************************************************************************/
package org.eclipse.om2m.core.controller;
import java.util.List;
import org.eclipse.om2m.commons.constants.ConsistencyStrategy;
import org.eclipse.om2m.commons.constants.Constants;
import org.eclipse.om2m.commons.constants.MemberType;
import org.eclipse.om2m.commons.constants.MimeMediaType;
import org.eclipse.om2m.commons.constants.Operation;
import org.eclipse.om2m.commons.constants.ResourceStatus;
import org.eclipse.om2m.commons.constants.ResourceType;
import org.eclipse.om2m.commons.constants.ResponseStatusCode;
import org.eclipse.om2m.commons.constants.ShortName;
import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
import org.eclipse.om2m.commons.entities.AeEntity;
import org.eclipse.om2m.commons.entities.CSEBaseEntity;
import org.eclipse.om2m.commons.entities.GroupEntity;
import org.eclipse.om2m.commons.entities.RemoteCSEEntity;
import org.eclipse.om2m.commons.entities.ResourceEntity;
import org.eclipse.om2m.commons.entities.SubscriptionEntity;
import org.eclipse.om2m.commons.exceptions.BadRequestException;
import org.eclipse.om2m.commons.exceptions.ConflictException;
import org.eclipse.om2m.commons.exceptions.NotImplementedException;
import org.eclipse.om2m.commons.exceptions.NotPermittedAttrException;
import org.eclipse.om2m.commons.exceptions.Om2mException;
import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException;
import org.eclipse.om2m.commons.resource.Group;
import org.eclipse.om2m.commons.resource.RequestPrimitive;
import org.eclipse.om2m.commons.resource.ResponsePrimitive;
import org.eclipse.om2m.commons.utils.Util.DateUtil;
import org.eclipse.om2m.core.datamapper.DataMapperSelector;
import org.eclipse.om2m.core.entitymapper.EntityMapperFactory;
import org.eclipse.om2m.core.notifier.Notifier;
import org.eclipse.om2m.core.persistence.PersistenceService;
import org.eclipse.om2m.core.router.Patterns;
import org.eclipse.om2m.core.urimapper.UriMapper;
import org.eclipse.om2m.core.util.ControllerUtil;
import org.eclipse.om2m.core.util.ControllerUtil.UpdateUtil;
import org.eclipse.om2m.core.util.GroupUtil;
import org.eclipse.om2m.persistence.service.DAO;
import org.eclipse.om2m.persistence.service.DBService;
import org.eclipse.om2m.persistence.service.DBTransaction;
/**
* Controller for group
*
*/
public class GroupController extends Controller {
/*
* Req
* @resourceName NP
* resourceType NP
* resourceID NP
* parentID NP
* accessControlPolicyIDs O
* creationTime NP
* expirationTime O
* lastModifiedTime NP
* labels O
* announceTo O
* announcedAttribute O
* creator O
* memberType M
* currentNrOdMembers NP
* maxNrOfMembers M
* memberID M
* membersACPIDs O
* memberTypeValidated NP
* consistencyStrategy O
* groupName O
*/
@Override
public ResponsePrimitive doCreate(RequestPrimitive request) {
ResponsePrimitive response = new ResponsePrimitive(request);
// Get the DAO of the parent
DAO<ResourceEntity> dao = (DAO<ResourceEntity>) Patterns.getDAO(request.getTargetId(), dbs);
if (dao == null){
throw new ResourceNotFoundException("Cannot find parent resource");
}
// Get the parent entity
ResourceEntity parentEntity = (ResourceEntity) dao.find(transaction, request.getTargetId());
// Check the parent existence
if (parentEntity == null){
throw new ResourceNotFoundException("Cannot find parent resource");
}
// Get lists to change in the method corresponding to specific object
List<AccessControlPolicyEntity> acpsToCheck = null;
List<GroupEntity> childGroups = null;
List<SubscriptionEntity> subscriptions = null;
// Distinguish parents
// Case of CSEBase
if(parentEntity.getResourceType().intValue() == (ResourceType.CSE_BASE)){
CSEBaseEntity cseBase = (CSEBaseEntity) parentEntity;
acpsToCheck = cseBase.getAccessControlPolicies();
childGroups = cseBase.getGroups();
subscriptions = cseBase.getSubscriptions();
}
if(parentEntity.getResourceType().intValue() == (ResourceType.AE)){
AeEntity ae = (AeEntity) parentEntity;
acpsToCheck = ae.getAccessControlPolicies();
childGroups = ae.getChildGroups();
subscriptions = ae.getSubscriptions();
}
if(parentEntity.getResourceType().intValue() == (ResourceType.REMOTE_CSE)){
RemoteCSEEntity remoteCSE = (RemoteCSEEntity) parentEntity;
acpsToCheck = remoteCSE.getAccessControlPolicies();
childGroups = remoteCSE.getChildGrps();
subscriptions = remoteCSE.getSubscriptions();
}
if(parentEntity.getResourceType().intValue() == (ResourceType.REMOTE_CSE_ANNC)){
throw new NotImplementedException("remote cse announcer not implemented");
}
if(parentEntity.getResourceType().intValue() == (ResourceType.AE_ANNC)){
// TODO AE_ANNC group parent
throw new NotImplementedException("ae annc not implemented");
}
// Check access control policy of the originator
checkACP(acpsToCheck, request.getFrom(), Operation.CREATE);
// Check if content is present
if (request.getContent() == null){
throw new BadRequestException("A content is requiered for Group creation");
}
Group group = null;
try {
if(request.getRequestContentType().equals(MimeMediaType.OBJ)){
group = (Group) request.getContent();
} else {
group = (Group) DataMapperSelector.getDataMapperList().
get(request.getRequestContentType()).stringToObj((String)request.getContent());
}
} catch (ClassCastException e){
throw new BadRequestException("Incorrect resource representation in content", e);
}
if (group == null){
throw new BadRequestException("Error in provided content");
}
GroupEntity groupEntity = new GroupEntity();
// Check attributes
// @resourceName NP
// resourceType NP
// resourceID NP
// parentID NP
// creationTime NP
// lastModifiedTime NP
// expirationTime O
// labels O
// announceTo O
// announcedAttribute O
// Creating the corresponding entity
ControllerUtil.CreateUtil.fillEntityFromAnnounceableResource(group, groupEntity);
// currentNrOdMembers NP
if (group.getCurrentNrOfMembers() != null){
throw new NotPermittedAttrException("CurrentNrOfMembers is Not Permitted");
}
// memberTypeValidated NP
if (group.getMemberTypeValidated() != null){
throw new NotPermittedAttrException("MemberTypeValidated is Not Permitted");
}
// maxNrOfMembers M
if(group.getMaxNrOfMembers() == null){
throw new BadRequestException("MaxNrOfMembers is Mandatory");
}
groupEntity.setMaxNrOfMembers(group.getMaxNrOfMembers());
// memberType O
if(group.getMemberType() == null){
groupEntity.setMemberType(MemberType.MIXED);
} else {
groupEntity.setMemberType(group.getMemberType());
}
// memberID M
if (group.getMemberIDs().isEmpty()){
throw new BadRequestException("MemberIDs is Mandatory");
}
if(group.getMemberIDs().size() > group.getMaxNrOfMembers().intValue()){
throw new Om2mException("Max number of member exceeded",
ResponseStatusCode.MAX_NUMBER_OF_MEMBER_EXCEEDED);
}
groupEntity.getMemberIDs().addAll(group.getMemberIDs());
// consistencyStrategy O
if (group.getConsistencyStrategy() != null){
groupEntity.setConsistencyStrategy(group.getConsistencyStrategy());
} else {
groupEntity.setConsistencyStrategy(ConsistencyStrategy.ABANDON_MEMBER);
}
// accessControlPolicyIDs O
if(!group.getAccessControlPolicyIDs().isEmpty()){
groupEntity.setAccessControlPolicies(
ControllerUtil.buildAcpEntityList(group.getAccessControlPolicyIDs(), transaction));
} else {
groupEntity.getAccessControlPolicies().addAll(acpsToCheck);
}
// creator O
if(group.getCreator() != null){
groupEntity.setCreator(group.getCreator());
}
// membersACPIDs O
if (!group.getMembersAccessControlPolicyIDs().isEmpty()){
groupEntity.getMemberAcpIds().addAll(group.getMembersAccessControlPolicyIDs());
}
// groupName O
if (group.getGroupName() != null){
groupEntity.setGroupName(group.getGroupName());
}
String generatedId = generateId();
groupEntity.setResourceID("/" + Constants.CSE_ID + "/" + ShortName.GROUP + Constants.PREFIX_SEPERATOR + generatedId);;
groupEntity.setCreationTime(DateUtil.now());
groupEntity.setLastModifiedTime(DateUtil.now());
groupEntity.setParentID(parentEntity.getResourceID());
groupEntity.setResourceType(ResourceType.GROUP);
if (group.getName() != null){
if (!Patterns.checkResourceName(group.getName())){
throw new BadRequestException("Name provided is incorrect. Must be:" + Patterns.ID_STRING);
}
groupEntity.setName(group.getName());
} else
if(request.getName() != null){
if (!Patterns.checkResourceName(request.getName())){
throw new BadRequestException("Name provided is incorrect. Must be:" + Patterns.ID_STRING);
}
groupEntity.setName(request.getName());
} else {
groupEntity.setName(ShortName.GROUP + "_" + generatedId);
}
groupEntity.setHierarchicalURI(parentEntity.getHierarchicalURI()+ "/" + groupEntity.getName());
// Validate the memberType of memberIDs
GroupUtil.validateGroupMember(groupEntity);
if (!UriMapper.addNewUri(groupEntity.getHierarchicalURI(), groupEntity.getResourceID(), ResourceType.GROUP)){
throw new ConflictException("Name already present in the parent collection.");
}
dbs.getDAOFactory().getGroupDAO().create(transaction, groupEntity);
// Get the managed object from db
GroupEntity groupDB = dbs.getDAOFactory().getGroupDAO().find(transaction, groupEntity.getResourceID());
childGroups.add(groupDB);
dao.update(transaction, parentEntity);
transaction.commit();
Notifier.notify(subscriptions, groupDB, ResourceStatus.CHILD_CREATED);
response.setResponseStatusCode(ResponseStatusCode.CREATED);
setLocationAndCreationContent(request, response, groupDB);
return response;
}
@Override
public ResponsePrimitive doRetrieve(RequestPrimitive request) {
/*
* Generic retrieve procedure
*/
ResponsePrimitive response = new ResponsePrimitive(request);
// Check the existence of the resource
GroupEntity groupEntity = dbs.getDAOFactory().getGroupDAO().
find(transaction, request.getTargetId());
if (groupEntity == null){
throw new ResourceNotFoundException("Resource not found");
}
checkACP(groupEntity.getAccessControlPolicies(), request.getFrom(),
Operation.RETRIEVE);
// Create the object used to create the representation of the resource
Group group = EntityMapperFactory.getGroupMapper().mapEntityToResource(groupEntity, request);
response.setContent(group);
response.setResponseStatusCode(ResponseStatusCode.OK);
return response;
}
/*
* Req
* @resourceName NP
* resourceType NP
* resourceID NP
* parentID NP
* accessControlPolicyIDs NP
* creationTime NP
* expirationTime O
* lastModifiedTime NP
* labels O
* announceTo O
* announcedAttribute O
* creator NP
* memberType O
* currentNrOdMembers NP
* maxNrOfMembers O
* memberID O
* membersACPIDs O
* memberTypeValidated NP
* consistencyStrategy NP
* groupName O
*/
@Override
public ResponsePrimitive doUpdate(RequestPrimitive request) {
ResponsePrimitive response = new ResponsePrimitive(request);
DBService dbs = PersistenceService.getInstance().getDbService();
DBTransaction transaction = dbs.getDbTransaction();
transaction.open();
// Retrieve the resource from database
GroupEntity groupEntity = dbs.getDAOFactory()
.getGroupDAO().find(transaction, request.getTargetId());
if (groupEntity == null){
throw new ResourceNotFoundException("Resource not found");
}
checkACP(groupEntity.getAccessControlPolicies(), request.getFrom(),
Operation.UPDATE);
// Check if content is present
if (request.getContent() == null){
throw new BadRequestException("A content is requiered for Group update");
}
Group group = null;
try {
if(request.getRequestContentType().equals(MimeMediaType.OBJ)){
group = (Group) request.getContent();
} else {
group = (Group) DataMapperSelector.getDataMapperList().
get(request.getRequestContentType()).stringToObj((String)request.getContent());
}
} catch (ClassCastException e){
throw new BadRequestException("Incorrect resource representation in content", e);
}
if (group == null){
throw new BadRequestException("Error in provided content");
}
// Check attributes
// NP Attributes are ignores
// @resourceName NP
// resourceType NP
// resourceID NP
// parentID NP
// accessControlPolicyIDs NP
// creationTime NP
// lastModifiedTime NP
UpdateUtil.checkNotPermittedParameters(group);
// creator NP
if(group.getCreator() != null){
throw new BadRequestException("Creator is NP");
}
// currentNrOdMembers NP
if(group.getCurrentNrOfMembers() != null){
throw new BadRequestException("CurrentNrOfMembers is NP");
}
// memberTypeValidated NP
if(group.getMemberTypeValidated() != null){
throw new BadRequestException("MemberTypeValidated is NP");
}
// consistencyStrategy NP
if(group.getConsistencyStrategy() != null){
throw new BadRequestException("ConsistencyStrategy is NP");
}
Group modifiedAttributes = new Group();
// expirationTime O
if (group.getExpirationTime() != null){
groupEntity.setExpirationTime(group.getExpirationTime());
modifiedAttributes.setExpirationTime(group.getExpirationTime());
}
// labels O
if(!group.getLabels().isEmpty()){
groupEntity.getLabelsEntities().clear();
groupEntity.setLabelsEntitiesFromSring(group.getLabels());
modifiedAttributes.getLabels().addAll(group.getLabels());
}
// announceTo O
if(!group.getAnnounceTo().isEmpty()){
// TODO Announcement in group update
groupEntity.getAnnounceTo().clear();
groupEntity.getAnnounceTo().addAll(group.getAnnounceTo());
modifiedAttributes.getAnnounceTo().addAll(group.getAnnounceTo());
}
// announcedAttribute O
if(!group.getAnnouncedAttribute().isEmpty()){
groupEntity.getAnnouncedAttribute().clear();
groupEntity.getAnnouncedAttribute().addAll(group.getAnnouncedAttribute());
modifiedAttributes.getAnnouncedAttribute().addAll(group.getAnnouncedAttribute());
}
// memberType O
if(group.getMemberType() != null){
groupEntity.setMemberType(group.getMemberType());
modifiedAttributes.setMemberType(group.getMemberType());
}
// maxNrOfMembers O
if(group.getMaxNrOfMembers() != null){
groupEntity.setMaxNrOfMembers(group.getMaxNrOfMembers());
modifiedAttributes.setMaxNrOfMembers(group.getMaxNrOfMembers());
}
// memberID O
if(!group.getMemberIDs().isEmpty()){
groupEntity.getMemberIDs().clear();
groupEntity.getMemberIDs().addAll(group.getMemberIDs());
modifiedAttributes.getMemberIDs().addAll(group.getMemberIDs());
}
// membersACPIDs O
if(!group.getMembersAccessControlPolicyIDs().isEmpty()){
for(AccessControlPolicyEntity acpe : groupEntity.getAccessControlPolicies()){
checkSelfACP(acpe, request.getFrom(), Operation.UPDATE);
}
groupEntity.getMemberAcpIds().clear();
groupEntity.getMemberAcpIds().addAll(group.getMembersAccessControlPolicyIDs());
modifiedAttributes.getMembersAccessControlPolicyIDs().addAll(group.getMembersAccessControlPolicyIDs());
}
// groupName O
if(group.getGroupName() != null){
groupEntity.setGroupName(group.getGroupName());
modifiedAttributes.setGroupName(group.getGroupName());
}
// Last Time Modified update
groupEntity.setLastModifiedTime(DateUtil.now());
modifiedAttributes.setLastModifiedTime(groupEntity.getLastModifiedTime());
response.setContent(modifiedAttributes);
GroupUtil.validateGroupMember(groupEntity);
// Update the resource in database
dbs.getDAOFactory().getGroupDAO().update(transaction, groupEntity);
transaction.commit();
Notifier.notify(groupEntity.getSubscriptions(), groupEntity, ResourceStatus.UPDATED);
response.setResponseStatusCode(ResponseStatusCode.UPDATED);
return response;
}
@Override
public ResponsePrimitive doDelete(RequestPrimitive request) {
/*
* Generic delete procedure
*/
ResponsePrimitive response = new ResponsePrimitive(request);
// Retrieve the resource from database
GroupEntity groupEntity = dbs.getDAOFactory()
.getGroupDAO().find(transaction, request.getTargetId());
if (groupEntity == null){
throw new ResourceNotFoundException("Resource not found");
}
checkACP(groupEntity.getAccessControlPolicies(), request.getFrom(),
Operation.DELETE);
UriMapper.deleteUri(groupEntity.getHierarchicalURI());
Notifier.notifyDeletion(groupEntity.getSubscriptions(), groupEntity);
// Delete the resource
dbs.getDAOFactory().getGroupDAO().delete(transaction, groupEntity);
// Commit the transaction
transaction.commit();
response.setResponseStatusCode(ResponseStatusCode.DELETED);
return response;
}
}