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    }