Coverage Report - org.kuali.student.common.ui.server.gwt.AbstractDataService
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractDataService
0%
0/139
0%
0/44
2.957
 
 1  
 package org.kuali.student.common.ui.server.gwt;
 2  
 
 3  
 import java.util.HashMap;
 4  
 import java.util.List;
 5  
 import java.util.Map;
 6  
 import java.util.UUID;
 7  
 
 8  
 import java.net.URLDecoder;
 9  
 import org.apache.commons.lang.StringUtils;
 10  
 import org.apache.log4j.Logger;
 11  
 import org.kuali.rice.kew.dto.DocumentDetailDTO;
 12  
 import org.kuali.rice.kew.service.WorkflowUtility;
 13  
 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
 14  
 import org.kuali.rice.kim.service.IdentityManagementService;
 15  
 import org.kuali.student.common.assembly.data.Data;
 16  
 import org.kuali.student.common.assembly.data.Metadata;
 17  
 import org.kuali.student.common.assembly.transform.AuthorizationFilter;
 18  
 import org.kuali.student.common.assembly.transform.MetadataFilter;
 19  
 import org.kuali.student.common.assembly.transform.TransformFilter;
 20  
 import org.kuali.student.common.assembly.transform.TransformFilter.TransformFilterAction;
 21  
 import org.kuali.student.common.assembly.transform.TransformationManager;
 22  
 import org.kuali.student.common.dto.DtoConstants;
 23  
 import org.kuali.student.common.exceptions.DataValidationErrorException;
 24  
 import org.kuali.student.common.exceptions.DoesNotExistException;
 25  
 import org.kuali.student.common.exceptions.OperationFailedException;
 26  
 import org.kuali.student.common.exceptions.VersionMismatchException;
 27  
 import org.kuali.student.common.rice.StudentIdentityConstants;
 28  
 import org.kuali.student.common.rice.authorization.PermissionType;
 29  
 import org.kuali.student.common.ui.client.service.DataSaveResult;
 30  
 import org.kuali.student.common.ui.shared.IdAttributes;
 31  
 import org.kuali.student.common.util.security.SecurityUtils;
 32  
 import org.kuali.student.common.validation.dto.ValidationResultInfo;
 33  
 import org.kuali.student.core.assembly.transform.ProposalWorkflowFilter;
 34  
 import org.kuali.student.core.proposal.dto.ProposalInfo;
 35  
 import org.kuali.student.core.proposal.service.ProposalService;
 36  
 import org.springframework.transaction.annotation.Transactional;
 37  
 
 38  
 @Transactional(readOnly=true,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
 39  0
 public abstract class AbstractDataService implements DataService{
 40  
 
 41  
         private static final long serialVersionUID = 1L;
 42  
 
 43  0
         final Logger LOG = Logger.getLogger(AbstractDataService.class);
 44  
 
 45  
         private TransformationManager transformationManager;
 46  
         
 47  
         private IdentityManagementService permissionService;
 48  
         
 49  
         private WorkflowUtility workflowUtilityService;
 50  
 
 51  
     //TODO: why do we have this reference in the base class????
 52  
         private ProposalService proposalService;
 53  
 
 54  
         @Override
 55  
         public Data getData(String id) throws OperationFailedException {
 56  0
                 Map<String, Object> filterProperties = getDefaultFilterProperties();
 57  0
                 filterProperties.put(TransformFilter.FILTER_ACTION, TransformFilterAction.GET);
 58  0
                 filterProperties.put(MetadataFilter.METADATA_ID_VALUE, id);
 59  
                 
 60  0
                 String dtoId = URLDecoder.decode(id);
 61  
                 //First check if this is a proposal id
 62  
         //TODO: Igor : Why do we check for this when getting the data for programs?
 63  
                 try{
 64  0
                         if (proposalService != null){
 65  0
                                 ProposalInfo proposalInfo = proposalService.getProposal(dtoId);
 66  0
                                 filterProperties.put(ProposalWorkflowFilter.PROPOSAL_INFO, proposalInfo);
 67  0
                                 dtoId = proposalInfo.getProposalReference().get(0);
 68  
                         }                        
 69  
 
 70  0
                         Object dto = get(dtoId);
 71  0
                         if (dto != null){
 72  0
                                 return transformationManager.transform(dto, getDtoClass().getName(), filterProperties);
 73  
                         }
 74  0
                 } catch(DoesNotExistException e){
 75  0
                         return null;
 76  0
                 } catch (Exception e) {
 77  0
                         LOG.error("Error getting data",e);
 78  0
                         throw new OperationFailedException("Error getting data",e);
 79  0
                 }
 80  0
                 return null;
 81  
         }
 82  
 
 83  
         @Override
 84  
         public Metadata getMetadata(String id, Map<String, String> attributes) {
 85  0
                 Map<String, Object> filterProperties = getDefaultFilterProperties();
 86  0
                 filterProperties.put(MetadataFilter.METADATA_ID_VALUE, id);
 87  
                 
 88  
                 //Place id attributes into filter properties
 89  0
                 String idType = (attributes != null? attributes.get(IdAttributes.ID_TYPE):null);
 90  0
                 String docType = (attributes != null ? attributes.get(StudentIdentityConstants.DOCUMENT_TYPE_NAME):null);
 91  0
                 String dtoState = (attributes != null ? attributes.get(DtoConstants.DTO_STATE):null);
 92  0
                 String dtoNextState = (attributes != null ? attributes.get(DtoConstants.DTO_NEXT_STATE):null);
 93  0
                 String workflowNode = (attributes != null ? attributes.get(DtoConstants.DTO_WORKFLOW_NODE):null);
 94  
                                 
 95  0
                 if (idType == null){
 96  0
                         filterProperties.remove(MetadataFilter.METADATA_ID_TYPE);
 97  
                 } else {
 98  0
                         filterProperties.put(MetadataFilter.METADATA_ID_TYPE, idType);
 99  
                 }
 100  
         
 101  0
                 if (docType == null){
 102  0
                         filterProperties.put(ProposalWorkflowFilter.WORKFLOW_DOC_TYPE, getDefaultWorkflowDocumentType());
 103  
                 } else {
 104  0
                         filterProperties.put(ProposalWorkflowFilter.WORKFLOW_DOC_TYPE, docType);
 105  
                 }
 106  
 
 107  0
                 if (dtoState != null){
 108  0
                         filterProperties.put(DtoConstants.DTO_STATE, dtoState);                        
 109  
                 }
 110  
                 
 111  0
                 if (dtoNextState != null){
 112  0
                         filterProperties.put(DtoConstants.DTO_NEXT_STATE, dtoNextState);                        
 113  
                 }
 114  
 
 115  0
                 if (workflowNode != null){
 116  0
                         filterProperties.put(DtoConstants.DTO_WORKFLOW_NODE, workflowNode);                        
 117  
                 }
 118  
 
 119  0
                 if (checkDocumentLevelPermissions()){
 120  0
                         filterProperties.put(AuthorizationFilter.DOC_LEVEL_PERM_CHECK, Boolean.TRUE.toString());
 121  
                 }
 122  
                 
 123  0
                 Metadata metadata = transformationManager.getMetadata(getDtoClass().getName(), filterProperties); 
 124  0
                 return metadata;
 125  
         }
 126  
 
 127  
         @Override
 128  
         @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
 129  
         public DataSaveResult saveData(Data data) throws OperationFailedException, DataValidationErrorException, VersionMismatchException{
 130  0
                 Map<String, Object> filterProperties = getDefaultFilterProperties();
 131  0
                 filterProperties.put(TransformFilter.FILTER_ACTION, TransformFilterAction.SAVE);
 132  
                 
 133  0
                 DataSaveResult saveResult = new DataSaveResult();
 134  
                 try {
 135  
                         //Convert data object to dto object
 136  0
                         Object dto = transformationManager.transform(data, getDtoClass(), filterProperties);
 137  
                         
 138  
                         //This calls save method for DataService impl, which makes the needed service calls to persist dto
 139  
                         //The service call should do it's own validation, any errors will cause DataValidationErrorException
 140  
                         //and is handled in the catch below.
 141  0
                         dto = save(dto, filterProperties);
 142  
                         
 143  
                         //Validate saved data again to get validation warnings that may exist on the data
 144  0
                         List<ValidationResultInfo> validationResults = validate(dto);
 145  
                         
 146  
                         //Convert saved data object back to data object to send to UI
 147  0
                         Data persistedData = transformationManager.transform(dto, getDtoClass().getName(), filterProperties);                        
 148  
                         
 149  0
                         saveResult.setValue(persistedData);
 150  0
                         saveResult.setValidationResults(validationResults);                        
 151  0
                 }catch (DataValidationErrorException dvee){
 152  
                         //Throw the error, we need the the transaction to be rolled back when service throws an error.
 153  0
                         throw dvee;
 154  0
                 }catch (OperationFailedException ofe){
 155  0
                     throw ofe;
 156  0
                 }catch (VersionMismatchException vme){
 157  0
                     throw vme;
 158  0
                 }catch (Exception e) {
 159  0
                         LOG.error("Failed to save data",e);
 160  0
                         throw new OperationFailedException("Failed to save data",e);
 161  0
                 }
 162  
                 
 163  0
                 return saveResult;
 164  
         }
 165  
         
 166  
         
 167  
 
 168  
         @Override
 169  
         public List<ValidationResultInfo> validateData(Data data) throws OperationFailedException {
 170  
                 List<ValidationResultInfo> validationResults;
 171  
                 
 172  
                 try {
 173  0
                         Metadata metadata = transformationManager.getUnfilteredMetadata(getDtoClass().getName());
 174  0
                         Object dto = transformationManager.getMapper().convertFromData(data, getDtoClass(), metadata);
 175  0
                         validationResults = validate(dto);
 176  0
                 } catch (Exception e) {
 177  0
                         throw new OperationFailedException("Unable to validate data", e);
 178  0
                 }
 179  
 
 180  0
                 return validationResults;
 181  
         }
 182  
 
 183  
         @Override
 184  
         public Boolean isAuthorized(PermissionType type, Map<String,String> attributes) {
 185  0
                 String user = SecurityUtils.getCurrentPrincipalId();
 186  0
                 boolean result = false;
 187  0
                 if (checkDocumentLevelPermissions()) {
 188  0
                         if (type == null) {
 189  0
                                 return null;
 190  
                         }
 191  0
                         String namespaceCode = type.getPermissionNamespace();
 192  0
                         String permissionTemplateName = type.getPermissionTemplateName();
 193  
                         
 194  0
                         AttributeSet roleQuals = new AttributeSet();
 195  0
                         AttributeSet permissionDetails = new AttributeSet();
 196  
                         
 197  0
                         if (attributes != null) {
 198  
                                 //Determine permission details and role qualifiers to pass into permission service.
 199  
                                 //We will use same attributes for permission details and role qualifiers (never hurts to use more than needed)
 200  
                                 
 201  0
                                 if (proposalService != null){
 202  0
                                         ProposalInfo proposalInfo = null;
 203  
                                         try {
 204  
                                                 //Retrieve the proposal info provided the proposal id (passed in as KS_JEW_OBJECT_ID) or the workflow id
 205  0
                                                 if (attributes.containsKey(IdAttributes.IdType.KS_KEW_OBJECT_ID.toString())){
 206  0
                                                         proposalInfo = proposalService.getProposal(attributes.get(IdAttributes.IdType.KS_KEW_OBJECT_ID.toString()));
 207  0
                                                 } else if (attributes.containsKey(IdAttributes.IdType.DOCUMENT_ID.toString())){
 208  0
                                                         proposalInfo = proposalService.getProposalByWorkflowId(attributes.get(IdAttributes.IdType.DOCUMENT_ID.toString()));
 209  
                                                 }
 210  
                                                 
 211  
                                                 //Check if the route status is in the list of allowed statuses
 212  0
                                                 DocumentDetailDTO docDetail = getWorkflowUtilityService().getDocumentDetail(Long.parseLong(proposalInfo.getWorkflowId()));
 213  0
                                                 String routeStatusCode = docDetail.getDocRouteStatus(); 
 214  
 
 215  
                                                 //Populate attributes with additional attributes required for permission check
 216  0
                                                 if (proposalInfo != null){
 217  0
                                                         attributes.put(IdAttributes.IdType.KS_KEW_OBJECT_ID.toString(), proposalInfo.getId());
 218  0
                                                         attributes.put(StudentIdentityConstants.QUALIFICATION_DATA_ID, proposalInfo.getId()); // this is what most of the permissions/roles check
 219  0
                                                         attributes.put(IdAttributes.IdType.DOCUMENT_ID.toString(), proposalInfo.getWorkflowId());
 220  0
                                                         attributes.put(StudentIdentityConstants.DOCUMENT_TYPE_NAME, proposalInfo.getType());
 221  0
                                                         attributes.put(StudentIdentityConstants.ROUTE_STATUS_CODE, routeStatusCode);
 222  
                                                         
 223  
                                                         //Call t his to add any additional attributes that child classes need
 224  0
                                                         addAdditionalAttributes(attributes,proposalInfo,docDetail);
 225  
                                                 }
 226  0
                                         } catch (Exception e){
 227  0
                                                 LOG.error("Could not retrieve proposal to determine permission qualifiers:" + e.toString());
 228  0
                                         }
 229  
                                 }
 230  
                                 
 231  0
                                 permissionDetails.putAll(attributes);
 232  
                                 
 233  
                                 //Put in additional random number for role qualifiers. This is to avoid this request from being cached. 
 234  
                                 //Might want to do this only for specific templates to take advantage of caching
 235  0
                                 attributes.put("RAND_NO_CACHE", UUID.randomUUID().toString());
 236  0
                                 roleQuals.putAll(attributes);
 237  
                         }
 238  0
                         if (StringUtils.isNotBlank(namespaceCode) && StringUtils.isNotBlank(permissionTemplateName)) {
 239  0
                                 LOG.info("Checking Permission '" + namespaceCode + "/" + permissionTemplateName + "' for user '" + user + "'");
 240  0
                                 result = getPermissionService().isAuthorizedByTemplateName(user, namespaceCode, permissionTemplateName, permissionDetails, roleQuals);
 241  
                         }
 242  
                         else {
 243  0
                                 LOG.info("Can not check Permission with namespace '" + namespaceCode + "' and template name '" + permissionTemplateName + "' for user '" + user + "'");
 244  0
                                 return Boolean.TRUE;
 245  
                         }
 246  0
                 }
 247  
                 else {
 248  0
                         LOG.info("Will not check for document level permissions. Defaulting authorization to true.");
 249  0
                         result = true;
 250  
                 }
 251  0
                 LOG.info("Result of authorization check for user '" + user + "': " + result);
 252  0
                 return Boolean.valueOf(result);
 253  
         }
 254  
         
 255  
         protected void addAdditionalAttributes(Map<String, String> attributes,
 256  
                         ProposalInfo proposalInfo, DocumentDetailDTO docDetail) {
 257  0
                 return;
 258  
         }
 259  
 
 260  
         public Map<String, Object> getDefaultFilterProperties(){
 261  0
                 Map<String, Object> filterProperties = new HashMap<String,Object>();
 262  0
                 filterProperties.put(MetadataFilter.METADATA_ID_TYPE, StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_ID);
 263  0
                 filterProperties.put(ProposalWorkflowFilter.WORKFLOW_USER, SecurityUtils.getCurrentPrincipalId());
 264  
                 
 265  0
                 return filterProperties;
 266  
         }
 267  
         
 268  
         protected DataSaveResult _saveData(Data data, Map<String, Object> filterProperties) throws OperationFailedException{
 269  
                 try {
 270  0
                         filterProperties.put(MetadataFilter.METADATA_ID_VALUE, (String)data.query("id"));        
 271  
 
 272  0
                         Object dto = transformationManager.transform(data, getDtoClass(),filterProperties);
 273  0
                         dto = save(dto, filterProperties);
 274  
                                 
 275  0
                         Data persistedData = transformationManager.transform(dto,getDtoClass().getName(), filterProperties);
 276  0
                         return new DataSaveResult(null, persistedData);
 277  0
                 } catch (DataValidationErrorException dvee){
 278  0
                         return new DataSaveResult(dvee.getValidationResults(), null);
 279  0
                 } catch (Exception e) {
 280  0
                         LOG.error("Unable to save", e);
 281  0
                         throw new OperationFailedException("Unable to save");
 282  
                 }                
 283  
         }
 284  
         
 285  
         protected boolean checkDocumentLevelPermissions() {
 286  0
                 return false;
 287  
         }
 288  
 
 289  
 
 290  
 
 291  
         public TransformationManager getTransformationManager() {
 292  0
                 return transformationManager;
 293  
         }
 294  
 
 295  
         public void setTransformationManager(TransformationManager transformationManager) {
 296  0
                 this.transformationManager = transformationManager;
 297  0
         }
 298  
 
 299  
         public IdentityManagementService getPermissionService() {
 300  0
                 return permissionService;
 301  
         }
 302  
 
 303  
         public void setPermissionService(IdentityManagementService permissionService) {
 304  0
                 this.permissionService = permissionService;
 305  0
         }
 306  
         
 307  
         public ProposalService getProposalService() {
 308  0
                 return proposalService;
 309  
         }
 310  
 
 311  
         public void setProposalService(ProposalService proposalService) {
 312  0
                 this.proposalService = proposalService;
 313  0
         }
 314  
         
 315  
         public WorkflowUtility getWorkflowUtilityService() {
 316  0
                 return workflowUtilityService;
 317  
         }
 318  
 
 319  
         public void setWorkflowUtilityService(WorkflowUtility workflowUtilityService) {
 320  0
                 this.workflowUtilityService = workflowUtilityService;
 321  0
         }
 322  
 
 323  
         protected abstract String getDefaultWorkflowDocumentType();
 324  
         
 325  
         protected abstract String getDefaultMetaDataState();
 326  
         
 327  
         /**
 328  
          * Implement this method to make to make service call to get DTO object. The method is called
 329  
          * by the get(Data) method before it invokes transformationManager to convert DTO to a Data map 
 330  
          * 
 331  
          * @param id DTO id
 332  
          * @return the dto retrieved by calling the appropriate service method
 333  
          * @throws Exception
 334  
          */
 335  
         protected abstract Object get(String id) throws Exception;
 336  
         
 337  
         /**
 338  
          * Implement this method to make a service call to get DTO object. The method is called         
 339  
          * by the save(Data) method after it invokes transformationManager to convert Data map to DTO 
 340  
          * 
 341  
          * @param dto
 342  
          * @param properties
 343  
          * @return the persisted dto object
 344  
          * @throws Exception
 345  
          */
 346  
         protected abstract Object save(Object dto, Map<String, Object> properties) throws Exception;
 347  
         
 348  
         /**
 349  
          * Implement this method to make a service call to get DTO object. The method is called         
 350  
          * in the save(data) method before calling the save(dto,properties) method to validate the data
 351  
  
 352  
          * @param dto
 353  
          * @return
 354  
          * @throws Exception
 355  
          */
 356  
         protected abstract List<ValidationResultInfo> validate(Object dto) throws Exception;
 357  
 
 358  
         /**
 359  
          * Implement this method to return the type of the dto object.
 360  
          * 
 361  
          * @return The object type returned and expected by the get & save dto methods
 362  
          */
 363  
         protected abstract Class<?> getDtoClass();
 364  
 }