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