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    }