All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.airavata.wsmg.client.util.DcDate Maven / Gradle / Ivy

The newest version!
/*
 *
 * 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.
 *
 */

package org.apache.airavata.wsmg.client.util;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;

//TODO: support for fractional seconds

/**
 * Represent dc:date as an immutable value object. http://www.w3.org/TR/NOTE-datetime
 * http://www.sics.se/~preben/DC/date_help.html
 * 
 */
public final class DcDate implements Cloneable {

    public Object clone() throws CloneNotSupportedException {
        // it is easy as object is immutable
        DcDate dd = (DcDate) super.clone();
        return dd;
    }

    private String canonical;

    // private Date date;
    private int year;

    private int month; // 1-12

    private int day; // 1-31

    private int hh = -1; // 00-23

    private int mm = -1; // 00-59

    private int ss = -1; // 00-59

    private String decimalFraction = null; // decimal fraction

    private int zoneOffset; // in minutes +/-(12*60) ???

    private Calendar instant;

    private int millisOffset = -1; // milliseconds

    // public DcDate() throws SException {
    //
    // this(System.currentTimeMillis());
    // }
    //
    // public DcDate(long timeMillis) throws SException {
    // this(timeMillis, null);
    // Calendar local = new GregorianCalendar();
    // local.setTimeInMillis(timeMillis);
    // }

    // public DcDate(String tzName) throws SException {
    // TimeZone tz = tzName != null ? TimeZone.getTimeZone(tzName) :
    // TimeZone.getDefault();
    // TimeZone.getTimeZone("GMT")
    public DcDate(TimeZone tz) throws RuntimeException {

        // based on http://javaalmanac.com/egs/java.util/GetAllZones.html?l=rel

        Calendar cal = new GregorianCalendar(tz);
        init(cal, tz);
    }

    public DcDate(Calendar cal) throws RuntimeException {
        init(cal, cal.getTimeZone());
    }

    private void init(Calendar cal, TimeZone tz) throws RuntimeException {
        // Get the number of hours from GMT
        int rawOffset = tz.getRawOffset();
        zoneOffset = rawOffset / (60 * 1000);

        instant = cal;
        // http://javaalmanac.com/egs/java.util/GetCurDate.html
        year = cal.get(Calendar.YEAR);
        month = cal.get(Calendar.MONTH) + 1; // 0=Jan, 1=Feb, ...
        day = cal.get(Calendar.DAY_OF_MONTH);
        hh = cal.get(Calendar.HOUR_OF_DAY); // 0..23
        mm = cal.get(Calendar.MINUTE); // 0..59
        ss = cal.get(Calendar.SECOND); // 0..59
        // int ms = cal.get(Calendar.MILLISECOND); // 0..999
        // date = cal.getTime();
        canonical = computeCanonical();
    }

    public DcDate(String dcDate) throws RuntimeException {
        // try {
        // synchronized(sdf) { //TODO REVISIT: SimpleFormat is not multi-thread
        // safe!
        // d = sdf.parse(dcDate);
        // }
        // } catch (ParseException e) {
        // throw new SException("could not parse dc:date "+dcDate+getCtx(pp),
        // e);
        // }
        // 2003-05-06T23:07:04Z
        // 2003-08-09T18:36:00-05:00
        // 1234567890123456789012345
        // 2004-02-02T19:09:46-05:00
        // 1997
        // 1997-07
        // 1997-07-16
        // 1997-07-16T19:20+01:00
        // 1997-07-16T19:20:30+01:00
        // 1997-07-16T19:20:30.45+01:00
        assert dcDate != null;
        // assert pp != null;
        canonical = dcDate;
        year = getInt(dcDate, 1, 4); // add min, max check for all getInt
        if (dcDate.length() == 4) {
            return;
        }
        check(dcDate, 5, '-');
        month = getInt(dcDate, 6, 2);
        if (dcDate.length() == 7) {
            return;
        }
        check(dcDate, 8, '-');
        day = getInt(dcDate, 9, 2);
        if (dcDate.length() == 10) {
            return;
        }
        check(dcDate, 11, 'T');
        hh = getInt(dcDate, 12, 2);
        check(dcDate, 14, ':');
        mm = getInt(dcDate, 15, 2);
        if (dcDate.length() == 16) {
            throw new RuntimeException("expected date formatted as YYYY-MM-DDThh:mm[:ss[.mmm]]TZD and not " + dcDate);
        }
        int pos = 17;
        char c17 = dcDate.charAt(pos - 1);
        if (c17 == ':') {
            check(dcDate, 17, ':');
            ss = getInt(dcDate, 18, 2);
            pos = 20;
        }
        char zoneIndicator = dcDate.charAt(pos - 1);
        if (zoneIndicator == '.') { // OK we have yet millliseocnds to parse
            // (and ignore ...)
            // Ex: 2004-04-13T11:53:15.4362784-04:00
            // eat digits
            char d;
            int oldPos = pos;
            do {
                d = dcDate.charAt(pos);
                ++pos;
            } while (d >= '0' && d <= '9');
            if (oldPos + 1 == pos) {
                throw new RuntimeException("expected date formtted as YYYY-MM-DDThh:mm[:ss[.s]]TZD and not " + dcDate);

            }
            zoneIndicator = d;
            int newPos = pos;
            decimalFraction = dcDate.substring(oldPos, newPos - 1);
            if (newPos - oldPos >= 3) {
                newPos = oldPos + 3;
            }
            int len = newPos - (oldPos + 1);
            int ii = getInt(dcDate, oldPos + 1, len);
            if (len == 1) {
                millisOffset = 100 * ii;
            } else if (len == 2) {
                millisOffset = 10 * ii;
            } else if (len == 3) {
                millisOffset = ii;
            }
        }
        if (zoneIndicator == 'Z') {
            // done
        } else if (zoneIndicator == '-' || zoneIndicator == '+') {
            int zoneHH = getInt(dcDate, pos + 1, 2);
            check(dcDate, pos + 3, ':');
            int zoneMM = getInt(dcDate, pos + 4, 2);
            zoneOffset = 60 * zoneHH + zoneMM;
            if (zoneIndicator == '-') {
                zoneOffset *= -1;
            }
        } else {
            throw new RuntimeException("unknown zone indicator " + zoneIndicator + " in " + dcDate);
        }
        // Get the number of hours from GMT

        // TimeZone tz = TimeZone.
        instant = new GregorianCalendar();
        int rawOffset = zoneOffset * 60 * 1000;
        instant.set(Calendar.ZONE_OFFSET, rawOffset);
        instant.set(Calendar.YEAR, year);
        instant.set(Calendar.MONTH, month - 1); // 0=Jan, 1=Feb, ...
        instant.set(Calendar.DAY_OF_MONTH, day);
        instant.set(Calendar.HOUR_OF_DAY, hh); // 0..23
        instant.set(Calendar.MINUTE, mm); // 0..59
        instant.set(Calendar.SECOND, ss); // 0..59
        instant.set(Calendar.MILLISECOND, millisOffset); // /0..999 ?
        instant.getTimeInMillis(); // full time in ms -- test?
    }

    public long getTimeInMillis() {
        return instant.getTimeInMillis();
    }

    public int getYear() {
        return year;
    }

    public int getMonth() {
        return month;
    }

    public int getDay() {
        return day;
    }

    public int getHour() {
        return hh;
    }

    public int getMinute() {
        return mm;
    }

    public int getSecond() {
        return ss;
    }

    public int getTimeZoneOffset() {
        return zoneOffset;
    }

    public String getDcDate() {
        return canonical;
    }

    public String getDecimalFraction() {
        return decimalFraction;
    }

    private String computeCanonical() {
        // 2003-08-09T18:36:00-05:00
        // 1234567890123456789012345
        StringBuffer sb = new StringBuffer();
        fill(sb, year, 4);
        if (month > 0) {
            sb.append('-');
            fill(sb, month, 2);
            if (day > 0) {
                sb.append('-');
                fill(sb, day, 2);
                if (hh > -1) {
                    sb.append('T');
                    fill(sb, hh, 2);
                    sb.append(':');
                    fill(sb, mm, 2);
                    if (ss > -1) {
                        sb.append(':');
                        fill(sb, ss, 2);
                    }
                    if (decimalFraction != null) {
                        sb.append('.');
                        sb.append(decimalFraction);
                    }
                    if (zoneOffset == 0) {
                        sb.append('Z');
                    } else {
                        int off = zoneOffset;
                        if (zoneOffset > 0) {
                            sb.append('+');
                        } else {
                            sb.append('-');
                            off *= -1;
                        }
                        int zoneHH = off / 60;
                        int zoneMM = off % 60;
                        fill(sb, zoneHH, 2);
                        sb.append(':');
                        fill(sb, zoneMM, 2);
                    }
                }
            }
        }
        return sb.toString();
    }

    public String toString() {
        return canonical;
    }

    public final static String LOCATION_PROPERTY = "http://xmlpull.org/v1/doc/properties.html#location";

    public static String printable(char ch) {
        return "'" + escape(ch) + "'";
    }

    public static String printable(String s) {
        return "\"" + escape(s) + "\"";
    }

    public static String escape(char ch) {
        if (ch == '\n') {
            return "\\n";
        } else if (ch == '\r') {
            return "\\r";
        } else if (ch == '\t') {
            return "\\t";
        } else if (ch == '\'') {
            return "\\'";
        }
        if (ch > 127 || ch < 32) {
            return "\\u" + Integer.toHexString((int) ch);
        }
        return "" + ch;
    }

    public static String escape(String s) {
        if (s == null) {
            return null;
        }
        final int sLen = s.length();
        StringBuffer buf = new StringBuffer(sLen + 10);
        for (int i = 0; i < sLen; ++i) {
            buf.append(escape(s.charAt(i)));
        }
        s = buf.toString();
        return s;
    }

    private static final int LOOKUP_10S[] = { 1, 10, 10 * 10, 10 * 100, 100 * 100 };

    public static void fill(StringBuffer sb, int value, int fields) {
        assert fields > 0;
        assert fields <= 4;
        assert value >= 0;
        int mm = LOOKUP_10S[fields];
        assert value < mm;
        // assert mm > 0
        // TODO: optimize it ...
        while (fields-- > 0) {
            mm /= 10;
            if (value >= mm) {
                sb.append((value / mm) % 10);
                // i /= 10;
            } else {
                sb.append('0');
            }
        }

        // String s = sb.toString();
        // assert s.toString().length == fields;
        // return s;
    }

    public static void check(String dcDate, int pos, char ch) {
        if (pos > dcDate.length()) {
            throw new RuntimeException("expected " + printable(ch) + " at position " + pos + " but " + dcDate
                    + " is too short");
        }
        char c = dcDate.charAt(pos - 1);
        if (c != ch) {
            throw new RuntimeException("expected " + printable(ch) + " but got " + printable(c) + " in " + dcDate);
        }
    }

    public static int getInt(String dcDate, int pos, int len) throws RuntimeException {
        assert len > 0;
        int end = pos + len - 1;
        String s = dcDate.substring(pos - 1, end);
        try {
            int i = Integer.parseInt(s);
            return i;
        } catch (NumberFormatException e) {
            throw new RuntimeException("expected number for " + printable(s) + " in " + dcDate, e);

        }
    }

    /**
     * Take string and return string that has no spaces, only alpahnumerics, each word is capitalized (like WikiWords)
     * sometimes called CamelCase?!.
     */
    public static String getWikiTitle(String title) {
        StringBuffer sb = new StringBuffer();
        List words = breakIntoWords(title);
        boolean start = true;
        for (Iterator it = words.iterator(); it.hasNext();) {
            String word = it.next();
            boolean wordStart = true;
            for (int i = 0; i < word.length(); i++) {
                char c = word.charAt(i);
                if (Character.isLetterOrDigit(c)) {
                    if (wordStart && !start) {
                        sb.append(Character.toUpperCase(c));
                    } else {
                        sb.append(c);
                    }
                    wordStart = false;
                }
            }
            start = false;
        }
        return sb.toString();
    }

    public static List breakIntoWords(String s) {
        List words = new ArrayList(s.length() / 5);
        boolean inWord = true;
        int wordStart = 0;
        for (int pos = 0; pos < s.length(); ++pos) {
            char ch = s.charAt(pos);
            boolean isWordSeparator = Character.isWhitespace(ch);
            if (ch == ',') {
                isWordSeparator = true;
            }
            if (ch == '.') {
                isWordSeparator = true;
            }
            if (isWordSeparator) {
                if (inWord) {
                    words.add(s.substring(wordStart, pos));
                    inWord = false;
                }
            } else {
                if (!inWord) {
                    inWord = true;
                    wordStart = pos;
                }
            }
            assert inWord == !isWordSeparator;
        }
        if (inWord) {
            words.add(s.substring(wordStart));
        }
        return words;
    }

    public static String makeTwoDigit(int oneOrTwoDigits) {
        if (oneOrTwoDigits < 0 || oneOrTwoDigits > 99) {
            throw new IllegalArgumentException();
        }
        if (oneOrTwoDigits < 10) {
            return "0" + oneOrTwoDigits;
        }
        return "" + oneOrTwoDigits;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy