001 /** 002 * Copyright 2005-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.rice.kew.util; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.apache.commons.lang.text.StrSubstitutor; 020 import org.kuali.rice.core.api.CoreApiServiceLocator; 021 import org.kuali.rice.core.api.util.KeyValue; 022 import org.kuali.rice.kew.actionrequest.ActionRequestValue; 023 import org.kuali.rice.kew.api.KewApiConstants; 024 import org.kuali.rice.kim.api.KimConstants; 025 026 import java.util.Calendar; 027 import java.util.Collections; 028 import java.util.Comparator; 029 import java.util.Date; 030 import java.util.HashMap; 031 import java.util.List; 032 import java.util.Map; 033 034 035 /** 036 * Various static utility methods. 037 * 038 * @author Kuali Rice Team (rice.collab@kuali.org) 039 */ 040 public final class Utilities { 041 /** 042 * Commons-Lang StrSubstitor which substitutes variables specified like ${name} in strings, 043 * using a lookup implementation that pulls variables from the core config 044 */ 045 private static final StrSubstitutor SUBSTITUTOR = new StrSubstitutor(new ConfigStringLookup()); 046 047 private Utilities() { 048 throw new UnsupportedOperationException("do not call"); 049 } 050 051 /** 052 * Performs variable substitution on the specified string, replacing variables specified like ${name} 053 * with the value of the corresponding config parameter obtained from the current context Config object. 054 * This version of the method also takes an application id to qualify the parameter. 055 * @param applicationId the application id to use for qualifying the parameter 056 * @param string the string on which to perform variable substitution 057 * @return a string with any variables substituted with configuration parameter values 058 */ 059 public static String substituteConfigParameters(String applicationId, String string) { 060 StrSubstitutor sub = new StrSubstitutor(new ConfigStringLookup(applicationId)); 061 return sub.replace(string); 062 } 063 064 /** 065 * Performs variable substitution on the specified string, replacing variables specified like ${name} 066 * with the value of the corresponding config parameter obtained from the current context Config object 067 * @param string the string on which to perform variable substitution 068 * @return a string with any variables substituted with configuration parameter values 069 */ 070 public static String substituteConfigParameters(String string) { 071 return SUBSTITUTOR.replace(string); 072 } 073 074 public static String parseGroupNamespaceCode(String namespaceAndNameCombo) { 075 if (namespaceAndNameCombo == null) { 076 return null; 077 } 078 String[] groupData = namespaceAndNameCombo.split(KewApiConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER); 079 if (groupData.length == 1) { 080 return KimConstants.KIM_GROUP_WORKFLOW_NAMESPACE_CODE; 081 } else if (groupData.length == 2) { 082 return groupData[0].trim(); 083 } else { 084 return null; 085 } 086 } 087 088 public static String parseGroupName(String namespaceAndNameCombo) { 089 if (namespaceAndNameCombo == null) { 090 return null; 091 } 092 String[] groupData = namespaceAndNameCombo.split(KewApiConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER); 093 if (groupData.length == 1) { 094 return groupData[0].trim(); 095 } else if (groupData.length == 2) { 096 return groupData[1].trim(); 097 } else { 098 return null; 099 } 100 } 101 102 /** 103 * 104 * Consider moving out of this class if this bugs 105 */ 106 public static class PrioritySorter implements Comparator<ActionRequestValue> { 107 @Override 108 public int compare(ActionRequestValue ar1, ActionRequestValue ar2) { 109 int value = ar1.getPriority().compareTo(ar2.getPriority()); 110 if (value == 0) { 111 value = ActionRequestValue.compareActionCode(ar1.getActionRequested(), ar2.getActionRequested(), true); 112 if (value == 0) { 113 if ( (ar1.getActionRequestId() != null) && (ar2.getActionRequestId() != null) ) { 114 value = ar1.getActionRequestId().compareTo(ar2.getActionRequestId()); 115 } else { 116 // if even one action request id is null at this point return that the two are equal 117 value = 0; 118 } 119 } 120 } 121 return value; 122 } 123 } 124 125 /** 126 * 127 * Consider moving out of this class if this bugs 128 */ 129 public static class RouteLogActionRequestSorter extends PrioritySorter implements Comparator<ActionRequestValue> { 130 @Override 131 public int compare(ActionRequestValue ar1, ActionRequestValue ar2) { 132 if (! ar1.getChildrenRequests().isEmpty()) { 133 Collections.sort(ar1.getChildrenRequests(), this); 134 } 135 if (! ar2.getChildrenRequests().isEmpty()) { 136 Collections.sort(ar2.getChildrenRequests(), this); 137 } 138 139 int routeLevelCompareVal = ar1.getRouteLevel().compareTo(ar2.getRouteLevel()); 140 if (routeLevelCompareVal != 0) { 141 return routeLevelCompareVal; 142 } 143 144 if (StringUtils.equals(ar1.getStatus(), ar2.getStatus())){ 145 return super.compare(ar1, ar2); 146 } else if (ar1.isActive() && ar2.isInitialized()) { 147 return -1; 148 } else if (ar2.isActive() && ar1.isInitialized()) { 149 return 1; 150 } 151 152 return super.compare(ar1, ar2); 153 } 154 } 155 156 public static boolean checkDateRanges(String fromDate, String toDate) { 157 try { 158 Date parsedDate = CoreApiServiceLocator.getDateTimeService().convertToDate(fromDate.trim()); 159 Calendar fromCalendar = Calendar.getInstance(); 160 fromCalendar.setLenient(false); 161 fromCalendar.setTime(parsedDate); 162 fromCalendar.set(Calendar.HOUR_OF_DAY, 0); 163 fromCalendar.set(Calendar.MINUTE, 0); 164 fromCalendar.set(Calendar.SECOND, 0); 165 fromCalendar.set(Calendar.MILLISECOND, 0); 166 parsedDate = CoreApiServiceLocator.getDateTimeService().convertToDate(toDate.trim()); 167 Calendar toCalendar = Calendar.getInstance(); 168 toCalendar.setLenient(false); 169 toCalendar.setTime(parsedDate); 170 toCalendar.set(Calendar.HOUR_OF_DAY, 0); 171 toCalendar.set(Calendar.MINUTE, 0); 172 toCalendar.set(Calendar.SECOND, 0); 173 toCalendar.set(Calendar.MILLISECOND, 0); 174 if (fromCalendar.after(toCalendar)) { 175 return false; 176 } 177 return true; 178 } catch (Exception ex) { 179 return false; 180 } 181 } 182 183 /** 184 * Helper method that takes a List of {@link KeyValue} and presents it as a Map 185 * @param collection collection of {@link KeyValue} 186 * @return a Map<String, String> representing the keys and values in the KeyValue collection 187 */ 188 public static <T extends KeyValue> Map<String, String> getKeyValueCollectionAsMap(List<T> collection) { 189 Map<String, String> map = new HashMap<String, String>(collection.size()); 190 for (KeyValue kv: collection) { 191 map.put(kv.getKey(), kv.getValue()); 192 } 193 return map; 194 } 195 196 /** 197 * Helper method that takes a List of {@link KeyValue} and presents it as a Map containing 198 * KeyValue values 199 * @param <T> the key type 200 * @param collection collection of {@link KeyValue} 201 * @return a Map<T,Z> where keys of the KeyValues in the collection are mapped to their respective KeyValue object 202 */ 203 public static <T extends KeyValue> Map<String, T> getKeyValueCollectionAsLookupTable(List<T> collection) { 204 Map<String, T> map = new HashMap<String, T>(collection.size()); 205 for (T kv: collection) { 206 map.put(kv.getKey(), kv); 207 } 208 return map; 209 } 210 }