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 }