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