001 /**
002 * Copyright 2005-2011 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 }