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

org.inigma.shared.tracking.TrackingUtil Maven / Gradle / Ivy

There is a newer version: 0.10.0
Show newest version
package org.inigma.shared.tracking;


/**
 * 

* Implementation based off of http://answers.google.com/answers/threadview/id/207899.html *

*

* Also off of http://www.logicalside.com/carrier_detection *

*/ public abstract class TrackingUtil { public static TrackingType getTrackingType(String trackingNumber) { if (isFedExExpress(trackingNumber) || isFedExGround(trackingNumber)) { return TrackingType.FedEx; } else if (isUps(trackingNumber)) { return TrackingType.UPS; } else if (isAirborne(trackingNumber)) { return TrackingType.Airborne; } else if (isUsps(trackingNumber)) { return TrackingType.USPS; } return null; } private static int differenceFromNextHighestMultipleOf10(int sum) { return ((sum / 10 * 10) + 10 - sum) % 10; } /** *
     * Airborne Express utilizes the stanard MOD 7 method for their tracking
     * numbers.  The check digit is the last digit of the tracking number.
     * 
     * [208-914-2901 x Val in Boise Call Center]
     * 
*/ private static boolean isAirborne(String trackingNumber) { return false; } /** *
     * EXPRESS SHIPMENTS:
     * 
     * For example, using tracking number: 012345678983
     * 
     * Take the first 11 digits of tracking number.  Starting with the 11th
     * position, take the digits 1, 3, and 7, and assign them to each digit
     * [repeatedly].
     *  
     * 012345678983
     * |||||||||||
     * 31731731731
     * 
     * Multiply each assigned number to its corresponding tracking number
     * digit:
     * 
     * 0 1 14 9 4 35 18 7 56 27 8
     * 
     * Add the products together [= 179 in this instance]
     * 
     * Divide the sum by 11.  You get 16 remainder 3.If the remainder is 10,
     * then the check digit is 0.  If there is no remainder, the check digit
     * is 0.  The remainder is the check digit and should equal the 12th
     * digit of the tracking number.
     * 
*/ private static boolean isFedExExpress(String trackingNumber) { if (trackingNumber == null || trackingNumber.length() != 12) { return false; } int hash[] = { 3, 1, 7 }; int sum = 0; for (int i = 0; i < 11; i++) { int digit = trackingNumber.charAt(i) - '0'; if (digit < 0 || digit > 9) { return false; } sum += digit * hash[i % hash.length]; } int remainder = sum % 11; if (remainder == 10) { remainder = 0; } return trackingNumber.charAt(11) - '0' == remainder; } /** *
     * FOR GROUND SHIPMENTS:
     * 
     * See this PDF file on the web:
     * 
     * grd.fedex.com/online/mcode/fedex_ground_label_layout_specification.pdf
     * 
     * under Check Digit Calculation Algorithms section
     * 
     * [Web API dept. - 800-810-9073 [option 1]]
     * [Bruce Clark                            ]
     * [CASE NUMBER: 11016731                  ]
     * 
     * --
     * 
     * Positions are from Right to Left
     * Step 1. Starting from position 2, add up the values of the even numbered positions.
     * Step 2. Multiply the results of step Step 1. By three.
     * Step 3. Starting from position 3, add up the values of the odd numbered positions. Remember – position 1 is the
     *  check digit you are trying to calculate.
     * Step 4. Add the result of step Step 2. To the result of step Step 3.
     * Step 5. Determine the smallest number which when added to the number from Step 4. Results in a multiple of 10.
     *  This is the check digit.
     * 
*/ private static boolean isFedExGround(String trackingNumber) { if (trackingNumber == null) { return false; } trackingNumber = trackingNumber.replaceAll(" ", ""); // remove all whitespace if (trackingNumber.length() == 22) { // 96 information ground shipment if (!trackingNumber.startsWith("96")) { return false; } trackingNumber = trackingNumber.substring(7); // strip the 96 information } if (trackingNumber.length() != 15) { // not a valid tracking number return false; } int checkDigit = trackingNumber.charAt(trackingNumber.length() - 1) - '0'; if (checkDigit < 0 || checkDigit > 9) { return false; } int sum = 0; for (int i = 0; i < trackingNumber.length() - 1; i++) { int digit = trackingNumber.charAt(i) - '0'; if (digit < 0 || digit > 9) { return false; } if (i % 2 == 0) { // odd numbers logic because it falls on even positions sum += digit; } else { // evens logic because it falls on odd positions sum += digit * 3; } } int calcCheckDigit = differenceFromNextHighestMultipleOf10(sum); return checkDigit == calcCheckDigit; } /** *
     * The 1Z tracking numbers utilize a modified MOD 10 calculation.
     * 
     * 1. Exclude 1Z data identifier from calculation.
     * 2. Convert all alpha characters to their numeric equivalents using
     * chart below.
     * 3. From left, add all odd positions.
     * 4. From left, add all even positions and multiply by two.
     * 5. Add results of steps 3 and 4.
     * 6. Subtract result from next highest multiple of 10.
     * 7. The remainder is your check digit [the last digit].     
     * 
     * Note: If the remainder is 10, the check digit is 0.Alpha to numeric
     * cross reference chart
     * 
     * A=2
     * B=3
     * C=4
     * D=5
     * E=6
     * F=7
     * G=8
     * H=9
     * I=0
     * J=1
     * K=2
     * L=3
     * M=4
     * N=5
     * O=6
     * p=7
     * Q=8
     * R=9
     * S=0
     * T=1
     * U=2
     * V=3
     * W=4
     * X=5
     * Y=6
     * Z=7
     * 
     * ---
     * 
     * For all other tracking numbers, the standard MOD 10 algorithm applies
     * for the 11th check-digit.
     * 
     * [Business Development Dept.                      ]
     * [404-828-6627 x Getty Gidash                     ] 
     * [Mark Lewis is a name that Getty may refer you to]
     * 
* *
     * Additional Reference:
     * http://www.codeproject.com/Articles/21224/Calculating-the-UPS-Tracking-Number-Check-Digit?fid=479913&df=90&mpp=25&noise=3&prof=False&sort=Position&view=Quick&spc=Relaxed&fr=8
     * 
     * 1.  The first two characters must be "1Z".
     * 2.  The next 6 characters we fill with our UPS account number "XXXXXX".
     * 3.  The next 2 characters denote the service type:
     *     a.  "01" for Next Day Air shipments.
     *     b.  "02" for Second Day Air shipments.
     *     c.  "03" for Ground shipments.
     * 4.  The next 5 characters is our invoice number (our invoices are 6 digits; we drop the first digit, e.g., the 123456 invoice would yield 23456 characters).
     * 5.  The next 2 digits is the package number, zero filled. E.g., package 1 is "01", 2 is "02".
     * 6.  The last and final character is the check digit.
     * 
     * 
* *
     * Additional Reference: http://www.ups.com/content/us/en/tracking/help/tracking/tnh.html
     *  UPS tracking numbers appear in the following formats:
     *     1Z9999999999999999
     *     999999999999
     *     T9999999999
     *     999999999
     * 
*/ private static boolean isUps(String trackingNumber) { if (trackingNumber == null) { return false; } trackingNumber = trackingNumber.toUpperCase().replaceAll(" ", ""); if (!trackingNumber.startsWith("1Z")) { return false; } int sum = 0; for (int i = 2; i < trackingNumber.length() - 1; i++) { char digit = trackingNumber.charAt(i); int value = digit - '0'; if (value > 9) { // need to convert letters to numbers accordingly value = (digit - 'A' + 2) % 10; } if (i % 2 == 0) { // even position sum += value; } else { // odd position sum += value * 2; } } int checkdigit = differenceFromNextHighestMultipleOf10(sum); return trackingNumber.charAt(trackingNumber.length() - 1) - '0' == checkdigit; } /** *
     * Please see the following publications for check digit information. 
     * Note: “PIC” is their term for “tracking number.”  In addition to the
     * specific sections/page numbers below, I would advise searching for
     * “check digit” in these documents.
     * 
     * Publication 91 – Delivery and Signature Confirmation numbers
     * Acrobat page 85 [literally page 79]
     * http://www.usps.com/cpim/ftp/pubs/pub91.pdf
     * 
     * Publication 97 – Express Mail Manifesting Technical Guide
     * Acrobat page 57 [literally page 59]
     * http://www.usps.com/cpim/ftp/pubs/pub97.pdf
     * 
     * Publication 109 – Special Services Technical GuideSection 7.6.3
     * http://www.usps.com/cpim/ftp/pubs/pub109.pdf
     * [Charles in Delivery Confirmation: 877-264-9693]
     * [He only has information on the Delivery       ]
     * [and signature confirmation schemes            ]
     * 
     * 
     * Additional link:
     * Mod information
     * http://www.formtechservices.com/dstuff/bookstuf/modnos.html
     * 
*/ private static boolean isUsps(String trackingNumber) { if (trackingNumber == null) { return false; } trackingNumber = trackingNumber.toUpperCase().replaceAll(" ", ""); int length = trackingNumber.length(); if (length != 22 && length != 20 && length != 13) { return false; } if (length == 13) { if (!trackingNumber.endsWith("US")) { return false; } trackingNumber = trackingNumber.substring(2, 11); // mod 11 check which if it fails drop back to mod 10 check as either are valid for express int multipliers[] = { 8, 6, 4, 2, 3, 5, 9, 7 }; int sum = 0; for (int i = 0; i < trackingNumber.length() - 1; i++) { int value = trackingNumber.charAt(i) - '0'; sum += value * multipliers[i]; } int remainder = sum % 11; int checkdigit; if (remainder == 0) { checkdigit = 5; } else if (remainder == 1) { checkdigit = 0; } else { checkdigit = 11 - remainder; } if (trackingNumber.charAt(trackingNumber.length() - 1) - '0' == checkdigit) { return true; } } int sum = 0; for (int i = trackingNumber.length() - 2; i >= 0; i--) { int value = trackingNumber.charAt(i) - '0'; if (i % 2 == trackingNumber.length() % 2) { sum += 3 * value; } else { sum += value; } } int checkdigit = differenceFromNextHighestMultipleOf10(sum); return trackingNumber.charAt(trackingNumber.length() - 1) - '0' == checkdigit; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy