View Javadoc

1   /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   */
15  
16  /**
17   *
18   */
19  package org.kuali.student.lum.kim;
20  
21  import org.apache.commons.lang.StringUtils;
22  import org.apache.log4j.Logger;
23  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
24  import org.kuali.rice.kew.api.KewApiServiceLocator;
25  import org.kuali.rice.kew.api.document.DocumentDetail;
26  import org.kuali.rice.kew.api.document.WorkflowDocumentService;
27  import org.kuali.rice.kew.doctype.bo.DocumentType;
28  import org.kuali.rice.kew.service.KEWServiceLocator;
29  import org.kuali.rice.kim.api.KimConstants;
30  import org.kuali.student.r1.common.rice.StudentIdentityConstants;
31  import org.kuali.student.r2.common.dto.ContextInfo;
32  
33  import org.kuali.student.r1.core.proposal.dto.ProposalInfo;
34  import org.kuali.student.r1.core.proposal.service.ProposalService;
35  
36  import javax.xml.namespace.QName;
37  import java.util.*;
38  
39  //import org.kuali.rice.kew.api.doctype.DocumentType;
40  
41  /**
42   * Class to allow convenience methods to help with qualification verification and translation
43   *
44   */
45  public class KimQualificationHelper {
46      protected static final Logger LOG = Logger.getLogger(KimQualificationHelper.class);
47  
48  	private static UniqueMap translationMap = new UniqueMap();
49  
50  	{
51  	    // below is example of how this could work
52  	    // translationMap.put("referenceType.clu.proposal", "kuali.proposal.type.course.create");
53  	}
54  
55  	protected static WorkflowDocumentService getWorkflowDocumentService() {
56  		return KewApiServiceLocator.getWorkflowDocumentService();
57  	}
58  
59      public static void validateRequiredAttributesAgainstReceived(Set<List<String>> requiredAttributes, Map<String,String> receivedAttributes, boolean checkRequiredAttributes, String commaSeparatorString) {
60  		// abort if type does not want the qualifiers to be checked
61  		if ( !checkRequiredAttributes ) {
62  			return;
63  		}
64  		// abort if the list is empty, no attributes need to be checked
65  		if ( requiredAttributes == null || requiredAttributes.isEmpty() ) {
66  			return;
67  		}
68  		// if attributes are null or empty, they're all missing
69  		if ( receivedAttributes == null || receivedAttributes.isEmpty() ) {
70  			return;
71  		}
72  
73  		Set<List<String>> totalMissingAttributes = new HashSet<List<String>>();
74  		for (List<String> currentReqAttributes : requiredAttributes) {
75  			List<String> missingAttributes = new ArrayList<String>();
76  			for( String requiredAttribute : currentReqAttributes ) {
77  				if( !receivedAttributes.containsKey(requiredAttribute) ) {
78  					missingAttributes.add(requiredAttribute);
79  				}
80  			}
81  			if (missingAttributes.isEmpty()) {
82  				// if no missing attributes from this list then we have required attributes needed
83  				return;
84  			}
85  			totalMissingAttributes.add(missingAttributes);
86          }
87  
88  		int i = 1;
89      	StringBuffer errorMessage = new StringBuffer("Missing Required Attributes from lists - ");
90      	for (List<String> missingAttributes : totalMissingAttributes) {
91              if(missingAttributes.size()>0) {
92              	errorMessage.append("List " + i + ": (");
93              	i++;
94              	Iterator<String> attribIter = missingAttributes.iterator();
95              	while ( attribIter.hasNext() ) {
96              		errorMessage.append( attribIter.next() );
97              		if( attribIter.hasNext() ) {
98              			errorMessage.append( commaSeparatorString );
99              		}
100             	}
101             	errorMessage.append(")");
102             }
103         }
104 		LOG.info("Found missing attributes: " + errorMessage.toString());
105         throw new RuntimeException (errorMessage.toString());
106     }
107 
108     protected static String getProposalId(Map<String,String> qualification) {
109         for (String proposalReferenceType : StudentIdentityConstants.QUALIFICATION_PROPOSAL_ID_REF_TYPES) {
110             if (qualification.containsKey(proposalReferenceType)) {
111                 return qualification.get(proposalReferenceType);
112             }
113         }
114         return null;
115     }
116 
117     public static Map<String,String> translateInputAttributeSet(Map<String,String> qualification, ContextInfo context) {
118 		try {
119 			DocumentDetail docDetail = null;
120 			// first get a valid DocumentDetailDTO object if possible
121 			String documentNumber = qualification.get(KimConstants.AttributeConstants.DOCUMENT_NUMBER);
122 			String proposalId = getProposalId(qualification);
123 			if (StringUtils.isBlank(documentNumber)) {
124 			    // if document number is not in qualification try to get it using proposal id qualification
125 	            if (StringUtils.isNotBlank(proposalId)) {
126 	                ProposalInfo propInfo = getProposalService().getProposal(proposalId);
127 	                documentNumber = propInfo.getWorkflowId();
128 	            }
129 			}
130 			if (StringUtils.isNotBlank(documentNumber)) {
131 				// document id exists so look up KEW document instance using it
132 				docDetail = getWorkflowDocumentService().getDocumentDetail(documentNumber);
133 			}
134 			else {
135 				// document id does not exist so attempt lookup by Document Type Name and Application ID
136 				String appId = qualification.get( StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_ID );
137 				if (StringUtils.isNotBlank(appId)) {
138 					String documentTypeName = qualification.get( KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME );
139 					if (StringUtils.isBlank(documentTypeName)) {
140 						// could not find Document Type Name in qualification so check for KS Object Type
141 						String ksObjectType = qualification.get( StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_TYPE );
142 						if (StringUtils.isNotBlank(ksObjectType)) {
143 							documentTypeName = translationMap.get(ksObjectType);
144 						}
145 					}
146 					// check for a valid Document Type Name
147 					if (StringUtils.isNotBlank(documentTypeName)) {
148 						// found valid Application ID and Document Type Name so KEW Document instance can be retrieved
149 
150 
151                         docDetail = getWorkflowDocumentService().getDocumentDetailByAppId(documentTypeName, appId);
152 					}
153 					else {
154 						// if neither Document Type Name nor KS object type is found then KEW document instance cannot be retrieved
155 						LOG.warn("Could not find valid document type name or KS object type using qualifications: " + qualification);
156 					}
157 				}
158 				else {
159 					// if application id is not found then KEW document instance cannot be retrieved
160 					LOG.warn("Could not find valid document id or application id using qualifications: " + qualification);
161 				}
162 			}
163 			translateQualifications(docDetail, proposalId, qualification);
164 		    return qualification;
165 	    }
166 		catch (Exception e) {
167             LOG.error(e.getLocalizedMessage(), e);
168             throw new RuntimeException(e);
169 		}
170 	}
171 
172 	protected static void translateQualifications(DocumentDetail docDetail, String proposalId, Map<String,String> qualifications) {
173 		if (docDetail != null) {
174 			// add document id if necessary
175 			if (!qualifications.containsKey(KimConstants.AttributeConstants.DOCUMENT_NUMBER)) {
176 				qualifications.put(KimConstants.AttributeConstants.DOCUMENT_NUMBER, docDetail.getDocument().getDocumentId());
177 			}
178 			// add KS proposal id if possible
179 			if (!qualifications.containsKey(StudentIdentityConstants.QUALIFICATION_KS_PROPOSAL_ID) && StringUtils.isNotBlank(proposalId)) {
180 			    qualifications.put(StudentIdentityConstants.QUALIFICATION_KS_PROPOSAL_ID, proposalId);
181 			}
182 			// add KS object id if necessary
183 			if (!qualifications.containsKey(StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_ID)) {
184 				qualifications.put(StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_ID, docDetail.getDocument().getApplicationDocumentId());
185 			}
186                         DocumentType docType = KEWServiceLocator.getDocumentTypeService().findById(docDetail.getDocument().getDocumentTypeId());
187 //			DocumentType docType = KEWServiceLocator.getDocumentTypeService().getDocumentType(docDetail.getDocTypeId());
188 			if (docType != null) {
189 				String documentTypeName = docType.getName();
190 				// add document type name if necessary
191 				if (!qualifications.containsKey(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME)) {
192 					qualifications.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, documentTypeName);
193 				}
194 				// add KS object type code if necessary
195 				if (!qualifications.containsKey(StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_TYPE)) {
196 					qualifications.put(StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_TYPE, translationMap.getKeyForValue(documentTypeName));
197 				}
198 			}
199 			else {
200 				String errorMsg = "Could not find valid KEW document type for document id " + docDetail.getDocument().getDocumentId();
201 				LOG.error(errorMsg);
202 				throw new RuntimeException(errorMsg);
203 			}
204 		}
205 		else {
206 			LOG.warn("Could not find KEW document instance for qualifications: " + qualifications);
207 			// add KS object type code if necessary
208 			if ((!qualifications.containsKey(StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_TYPE)) &&
209 					qualifications.containsKey(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME)) {
210 				qualifications.put(StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_TYPE, translationMap.getKeyForValue(qualifications.get(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME)));
211 			}
212 			else if ((!qualifications.containsKey(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME)) &&
213 					qualifications.containsKey(StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_TYPE)) {
214 				qualifications.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, translationMap.get(qualifications.get(StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_TYPE)));
215 			}
216 		}
217 	}
218 
219     protected static ProposalService getProposalService() {
220         return (ProposalService) GlobalResourceLoader.getService(new QName("http://student.kuali.org/wsdl/proposal","ProposalService"));
221     }
222 
223 	private static class UniqueMap extends HashMap<String,String> {
224 
225         private static final long serialVersionUID = 1L;
226 
227 		@Override
228         public String put(String key, String value) {
229 			if (this.containsValue(value)) {
230 				throw new UnsupportedOperationException("Map already contains an entry with value: " + value);
231 			}
232 	        return super.put(key, value);
233         }
234 
235 		public String getKeyForValue(String value) {
236 			for (Map.Entry<String, String> mapEntry : this.entrySet()) {
237 	            if (StringUtils.equals(value, mapEntry.getValue())) {
238 	            	return mapEntry.getKey();
239 	            }
240             }
241 			return null;
242 		}
243 	}
244 
245 }