| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| //$Id$ |
| |
| package org.apache.oodt.cas.metadata.util; |
| |
| //JDK imports |
| import java.text.SimpleDateFormat; |
| import java.util.Calendar; |
| import java.util.Date; |
| import java.util.GregorianCalendar; |
| import java.util.List; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| //APACHE imports |
| import org.apache.commons.lang.StringUtils; |
| |
| //OODT imports |
| import org.apache.oodt.commons.date.DateUtils; |
| import org.apache.oodt.commons.exec.EnvUtilities; |
| import org.apache.oodt.cas.metadata.Metadata; |
| |
| /** |
| * @author mattmann |
| * @author bfoster |
| * @version $Revision$ |
| * |
| * <p> |
| * A Utility class for replacing environment variables and maniuplating file |
| * path strings. |
| * </p>. |
| */ |
| public final class PathUtils { |
| |
| public static String DELIMITER = ","; |
| |
| public static String replaceEnvVariables(String origPath) { |
| return replaceEnvVariables(origPath, null); |
| } |
| |
| public static String replaceEnvVariables(String origPath, Metadata metadata) { |
| return replaceEnvVariables(origPath, metadata, false); |
| } |
| |
| public static String replaceEnvVariables(String origPath, |
| Metadata metadata, boolean expand) { |
| StringBuffer finalPath = new StringBuffer(); |
| |
| for (int i = 0; i < origPath.length(); i++) { |
| if (origPath.charAt(i) == '[') { |
| VarData data = readEnvVarName(origPath, i); |
| String var = null; |
| if (metadata != null |
| && metadata.getMetadata(data.getFieldName()) != null) { |
| List valList = metadata.getAllMetadata(data.getFieldName()); |
| var = (String) valList.get(0); |
| if (expand) |
| for (int j = 1; j < valList.size(); j++) |
| var += DELIMITER + (String) valList.get(j); |
| } else { |
| var = EnvUtilities.getEnv(data.getFieldName()); |
| } |
| finalPath.append(var); |
| i = data.getEndIdx(); |
| } else { |
| finalPath.append(origPath.charAt(i)); |
| } |
| } |
| |
| return finalPath.toString(); |
| } |
| |
| public static String doDynamicReplacement(String string) throws Exception { |
| return doDynamicReplacement(string, null); |
| } |
| |
| public static String doDynamicReplacement(String string, Metadata metadata) |
| throws Exception { |
| return PathUtils.replaceEnvVariables(doDynamicDateReplacement( |
| doDynamicDateRollReplacement( |
| doDynamicDateFormatReplacement( |
| doDynamicUtcToTaiDateReplacement( |
| doDynamicDateToSecsReplacement( |
| doDynamicDateToMillisReplacement( |
| string, metadata), |
| metadata), |
| metadata), |
| metadata), |
| metadata), |
| metadata), |
| metadata, true); |
| } |
| |
| public static String doDynamicDateReplacement(String string, |
| Metadata metadata) throws Exception { |
| Pattern datePattern = Pattern |
| .compile("\\[\\s*DATE\\s*(?:[+-]{1}[^\\.]{1,}?){0,1}\\.\\s*(?:(?:DAY)|(?:MONTH)|(?:YEAR)|(?:UTC)|(?:TAI)){1}\\s*\\]"); |
| Matcher dateMatcher = datePattern.matcher(string); |
| while (dateMatcher.find()) { |
| String dateString = string.substring(dateMatcher.start(), |
| dateMatcher.end()); |
| GregorianCalendar gc = new GregorianCalendar(); |
| |
| // roll the date if roll days was specfied |
| int plusMinusIndex; |
| if ((plusMinusIndex = dateString.indexOf('-')) != -1 |
| || (plusMinusIndex = dateString.indexOf('+')) != -1) { |
| int dotIndex; |
| if ((dotIndex = dateString.indexOf('.', plusMinusIndex)) != -1) { |
| int rollDays = Integer.parseInt(PathUtils |
| .replaceEnvVariables( |
| dateString.substring(plusMinusIndex, |
| dotIndex), metadata).replaceAll( |
| "[\\+\\s]", "")); |
| gc.add(GregorianCalendar.DAY_OF_YEAR, rollDays); |
| } else |
| throw new Exception( |
| "Malformed dynamic date replacement specified (no dot separator) - '" |
| + dateString + "'"); |
| } |
| |
| // determine type and make the appropriate replacement |
| String[] splitDate = dateString.split("\\."); |
| if (splitDate.length < 2) |
| throw new Exception("No date type specified - '" + dateString |
| + "'"); |
| String dateType = splitDate[1].replaceAll("[\\[\\]\\s]", ""); |
| String replacement = ""; |
| if (dateType.equals("DAY")) { |
| replacement = StringUtils.leftPad(gc |
| .get(GregorianCalendar.DAY_OF_MONTH) |
| + "", 2, "0"); |
| } else if (dateType.equals("MONTH")) { |
| replacement = StringUtils.leftPad((gc |
| .get(GregorianCalendar.MONTH) + 1) |
| + "", 2, "0"); |
| } else if (dateType.equals("YEAR")) { |
| replacement = gc.get(GregorianCalendar.YEAR) + ""; |
| } else if (dateType.equals("UTC")) { |
| replacement = DateUtils.toString(DateUtils.toUtc(gc)); |
| } else if (dateType.equals("TAI")) { |
| replacement = DateUtils.toString(DateUtils.toTai(gc)); |
| } else { |
| throw new Exception("Invalid date type specified '" |
| + dateString + "'"); |
| } |
| |
| string = StringUtils.replace(string, dateString, replacement); |
| dateMatcher = datePattern.matcher(string); |
| } |
| return string; |
| } |
| |
| /** |
| * usage format: [DATE_ADD(<date>,<date-format>,<add-amount>,<hr | min | sec | day | mo | yr>)] |
| * example: [DATE_ADD(2009-12-31, yyyy-MM-dd, 1, day)] . . . output will be: 2010-01-01 |
| * - dynamic replacement is allowed for the <date> as well, for example: |
| * [DATE_ADD([DATE.UTC], yyyy-MM-dd'T'HH:mm:ss.SSS'Z', 1, day)] will add one day to the |
| * current UTC time |
| */ |
| public static String doDynamicDateRollReplacement(String string, |
| Metadata metadata) throws Exception { |
| Pattern dateFormatPattern = Pattern |
| .compile("\\[\\s*DATE_ADD\\s*\\(.{1,}?,.{1,}?,.{1,}?,.{1,}?\\)\\s*\\]"); |
| Matcher dateFormatMatcher = dateFormatPattern.matcher(string); |
| while (dateFormatMatcher.find()) { |
| String dateFormatString = string.substring(dateFormatMatcher |
| .start(), dateFormatMatcher.end()); |
| |
| // get arguments |
| Matcher argMatcher = Pattern.compile("\\(.*\\)").matcher( |
| dateFormatString); |
| argMatcher.find(); |
| String argsString = dateFormatString.substring(argMatcher.start() + 1, |
| argMatcher.end() - 1); |
| argsString = doDynamicReplacement(argsString, metadata); |
| String[] args = argsString.split(","); |
| String dateString = args[0].trim(); |
| dateString = doDynamicReplacement(dateString, metadata); |
| String dateFormat = args[1].trim(); |
| int addAmount = Integer.parseInt(args[2].trim()); |
| String addUnits = args[3].trim().toLowerCase(); |
| |
| // reformat date |
| Date date = new SimpleDateFormat(dateFormat).parse(dateString); |
| Calendar calendar = (Calendar) Calendar.getInstance().clone(); |
| calendar.setTime(date); |
| if (addUnits.equals("hr") || addUnits.equals("hour")) |
| calendar.add(Calendar.HOUR_OF_DAY, addAmount); |
| else if (addUnits.equals("min") || addUnits.equals("minute")) |
| calendar.add(Calendar.MINUTE, addAmount); |
| else if (addUnits.equals("sec") || addUnits.equals("second")) |
| calendar.add(Calendar.SECOND, addAmount); |
| else if (addUnits.equals("day")) |
| calendar.add(Calendar.DAY_OF_YEAR, addAmount); |
| else if (addUnits.equals("mo") || addUnits.equals("month")) |
| calendar.add(Calendar.MONTH, addAmount); |
| else if (addUnits.equals("yr") || addUnits.equals("year")) |
| calendar.add(Calendar.YEAR, addAmount); |
| |
| String newDateString = new SimpleDateFormat(dateFormat).format(calendar.getTime()); |
| |
| // swap in date string |
| string = StringUtils.replace(string, dateFormatString, |
| newDateString); |
| dateFormatMatcher = dateFormatPattern.matcher(string); |
| } |
| |
| return string; |
| } |
| |
| public static String doDynamicDateFormatReplacement(String string, |
| Metadata metadata) throws Exception { |
| Pattern dateFormatPattern = Pattern |
| .compile("\\[\\s*FORMAT\\s*\\(.{1,}?,.{1,}?,.{1,}?\\)\\s*\\]"); |
| Matcher dateFormatMatcher = dateFormatPattern.matcher(string); |
| while (dateFormatMatcher.find()) { |
| String dateFormatString = string.substring(dateFormatMatcher |
| .start(), dateFormatMatcher.end()); |
| |
| // get arguments |
| Matcher argMatcher = Pattern.compile("\\(.*\\)").matcher( |
| dateFormatString); |
| argMatcher.find(); |
| String argsString = dateFormatString.substring(argMatcher.start() + 1, |
| argMatcher.end() - 1); |
| argsString = doDynamicReplacement(argsString, metadata); |
| String[] args = argsString.split(","); |
| String curFormat = args[0].trim(); |
| String dateString = args[1].trim(); |
| String newFormat = args[2].trim(); |
| |
| // reformat date |
| Date date = new SimpleDateFormat(curFormat).parse(dateString); |
| String newDateString = new SimpleDateFormat(newFormat).format(date); |
| |
| // swap in date string |
| string = StringUtils.replace(string, dateFormatString, |
| newDateString); |
| dateFormatMatcher = dateFormatPattern.matcher(string); |
| } |
| |
| return string; |
| } |
| |
| /** |
| * Replaces String method of format [UTC_TO_TAI(<utc-string format: "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'">)] |
| * with TAI time with format: "yyyy-MM-dd'T'HH:mm:ss.SSS-0000<leapSecs>" |
| */ |
| public static String doDynamicUtcToTaiDateReplacement(String string, |
| Metadata metadata) throws Exception { |
| Pattern utcToTaiPattern = Pattern.compile("\\[\\s*UTC_TO_TAI\\s*\\(.{1,}?\\)\\s*\\]"); |
| Matcher matcher = utcToTaiPattern.matcher(string); |
| while (matcher.find()) { |
| String utcToTaiString = string.substring(matcher.start(), matcher.end()); |
| Matcher argMatcher = Pattern.compile("\\(.*\\)").matcher(utcToTaiString); |
| argMatcher.find(); |
| String utcDateString = |
| utcToTaiString.substring(argMatcher.start() + 1, argMatcher.end() - 1).trim(); |
| utcDateString = doDynamicReplacement(utcDateString, metadata); |
| string = StringUtils.replace(string, utcToTaiString, |
| DateUtils.toString(DateUtils.toTai(DateUtils.toCalendar(utcDateString, |
| DateUtils.FormatType.UTC_FORMAT)))); |
| matcher = utcToTaiPattern.matcher(string); |
| } |
| return string; |
| } |
| |
| /** |
| * Replaces String method of format [DATE_TO_SECS(<date-string>,<DateUtils.FormatType>,<epoch-date format: "yyyy-MM-dd">)] |
| * with seconds between <epoch-date> and <date-string> |
| */ |
| public static String doDynamicDateToSecsReplacement(String string, |
| Metadata metadata) throws Exception { |
| Pattern utcToTaiPattern = Pattern.compile("\\[\\s*DATE_TO_SECS\\s*\\(.{1,}?\\,.{1,}?,.{1,}?\\)\\s*\\]"); |
| Matcher matcher = utcToTaiPattern.matcher(string); |
| while (matcher.find()) { |
| String dateToSecsString = string.substring(matcher.start(), matcher.end()); |
| Matcher argMatcher = Pattern.compile("\\(.*\\)").matcher(dateToSecsString); |
| argMatcher.find(); |
| String argsString = dateToSecsString.substring(argMatcher.start() + 1, |
| argMatcher.end() - 1); |
| argsString = doDynamicReplacement(argsString, metadata); |
| String[] args = argsString.split(","); |
| String dateString = args[0].trim(); |
| String dateType = args[1].trim(); |
| String epochString = args[2].trim(); |
| Calendar date = DateUtils.toCalendar(dateString, DateUtils.FormatType.valueOf(dateType)); |
| Calendar epoch = DateUtils.toLocalCustomFormatCalendar(epochString, "yyyy-MM-dd"); |
| String seconds = DateUtils.toString(DateUtils.getTimeInSecs(date, epoch)); |
| string = StringUtils.replace(string, dateToSecsString, seconds); |
| matcher = utcToTaiPattern.matcher(string); |
| } |
| return string; |
| } |
| |
| /** |
| * Replaces String method of format [DATE_TO_MILLIS(<date-string>,<DateUtils.FormatType>,<epoch-date format: "yyyy-MM-dd">)] |
| * with milliseconds between <epoch-date> and <date-string> |
| */ |
| public static String doDynamicDateToMillisReplacement(String string, |
| Metadata metadata) throws Exception { |
| Pattern utcToTaiPattern = Pattern.compile("\\[\\s*DATE_TO_MILLIS\\s*\\(.{1,}?\\,.{1,}?,.{1,}?\\)\\s*\\]"); |
| Matcher matcher = utcToTaiPattern.matcher(string); |
| while (matcher.find()) { |
| String dateToMillisString = string.substring(matcher.start(), matcher.end()); |
| Matcher argMatcher = Pattern.compile("\\(.*\\)").matcher(dateToMillisString); |
| argMatcher.find(); |
| String argsString = dateToMillisString.substring(argMatcher.start() + 1, |
| argMatcher.end() - 1); |
| argsString = doDynamicReplacement(argsString, metadata); |
| String[] args = argsString.split(","); |
| String dateString = args[0].trim(); |
| String dateType = args[1].trim(); |
| String epochString = args[2].trim(); |
| Calendar date = DateUtils.toCalendar(dateString, DateUtils.FormatType.valueOf(dateType)); |
| Calendar epoch = DateUtils.toLocalCustomFormatCalendar(epochString, "yyyy-MM-dd"); |
| String milliseconds = DateUtils.getTimeInMillis(date, epoch) + ""; |
| string = StringUtils.replace(string, dateToMillisString, milliseconds); |
| matcher = utcToTaiPattern.matcher(string); |
| } |
| return string; |
| } |
| |
| private static VarData readEnvVarName(String origPathStr, int startIdx) { |
| StringBuffer varName = new StringBuffer(); |
| int idx = startIdx + 1; |
| |
| do { |
| varName.append(origPathStr.charAt(idx)); |
| idx++; |
| } while (origPathStr.charAt(idx) != ']'); |
| |
| VarData data = new PathUtils().new VarData(); |
| data.setFieldName(varName.toString()); |
| data.setEndIdx(idx); |
| return data; |
| |
| } |
| |
| class VarData { |
| |
| private String fieldName = null; |
| |
| private int endIdx = -1; |
| |
| public VarData() { |
| } |
| |
| /** |
| * @return the endIdx |
| */ |
| public int getEndIdx() { |
| return endIdx; |
| } |
| |
| /** |
| * @param endIdx |
| * the endIdx to set |
| */ |
| public void setEndIdx(int endIdx) { |
| this.endIdx = endIdx; |
| } |
| |
| /** |
| * @return the fieldName |
| */ |
| public String getFieldName() { |
| return fieldName; |
| } |
| |
| /** |
| * @param fieldName |
| * the fieldName to set |
| */ |
| public void setFieldName(String fieldName) { |
| this.fieldName = fieldName; |
| } |
| |
| } |
| |
| } |