IMEI Validation app in JavaFX

IMEI (International Mobile Station Equipment Identity) is a unique number to identify GSM, UMTS, LTE and iDEN mobile phones.

The IMEI is basically used to identify a device. It is usually found printed inside the battery or you can dial *#06# to see your device IMEI.

The Digits are calculated with an algorithm called "Luhn algorithm" also known as "mod 10"  created by scientist Hans Peter Luhn.

It is also used to validate a variety of identification numbers, such as credit card numbers, National Provider Identifier numbers in the US etc. Which means you can use the same app to validate variety of things those using "mod 10" .

How it works ?

  1. Take the digit from the rightmost and double the value of every other digit.
  2. If the result of this doubling operation is greater than 9 (e.g., 8 × 2 = 16), then add the digits of the product (e.g., 16: 1 + 6 = 7, 18: 1 + 8 = 9) or alternatively subtract 9 from the product (e.g., 16: 16 - 9 = 7, 18: 18 - 9 = 9) or in simple wordsif the result in a two digits number, add up the digits to get a single digit number. This will results in eight single digit numbers.
  3. Take the sum of all the digits.
  4. if the sum is divided by 10 then its valid else its not.

so enough theory lets jump into coding.
below is the code implemented with mod 10.




package chap09;

/**
 *
 * @author Aamir khan
 */
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.geometry.Pos;
import javafx.scene.layout.VBox;
import java.util.stream.IntStream;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.application.Application;
import javafx.scene.control.TextField;

/**
 *
 *
 * @author Aamir khan
 */
public class IMEIValidaotrApp extends Application {

    //components
    IMEIField field;
    Label status;
    VBox root;
    Button checkBtn;

    //this is a bad idea use a separate css file indeed
    private final String INVALID_LABEL_CSS = "-fx-text-fill:white; "
            + "-fx-background-color: #E26868;"
            + "-fx-padding:5px;"
            + "-fx-border-width:1; -fx-border-color:#B63E5A;"
            + "-fx-font-size: 9pt;";

    private final String VALID_LABEL_CSS = "-fx-text-fill:white; "
            + "-fx-background-color: #20A286;"
            + "-fx-padding:5px;"
            + "-fx-border-width:1; -fx-border-color:#19B99A;"
            + "-fx-font-size: 9pt;";

    private final String CHECK_BUTTON_CSS = "-fx-background-color:#c3c4c4,"
            + "linear-gradient(#d6d6d6 50%, white 100%),"
            + "radial-gradient(center 50% -40%, radius 200%, #e6e6e6 45%, rgba(230,230,230,0) 50%);"
            + "-fx-background-radius: 30; -fx-background-insets: 0,1,1;"
            + "-fx-text-fill: black;"
            + "-fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 3, 0.0 , 0 , 1 );";

    @Override
    public void init() {

        field = new IMEIField();
        field.setText("490154203237518");//for the Demo

        status = new Label();

        checkBtn = new Button("Check");
        checkBtn.setDefaultButton(true);
        //disable the button if the length is less than 15
        checkBtn.disableProperty().bind(field.textProperty().length().lessThan(15));
        checkBtn.setStyle(CHECK_BUTTON_CSS);
    }

    @Override
    public void start(Stage window) throws Exception {

        root = new VBox(status, field, checkBtn);
        root.setAlignment(Pos.CENTER);
        root.setSpacing(5.0);
        root.setStyle("-fx-padding: 10; -fx-font-size: 18;");

        window.setScene(new Scene(root, 300, 200));
        window.setTitle("IMEI Checker");
        window.setResizable(false);
        window.show();

        checkBtn.setOnAction(e -> validateIMEI());

    }

    /**
     * implementation of
     * <a href = "https://en.wikipedia.org/wiki/Luhn_algorithm Luhn algorithm">Luhn
     * algorithm</a>
     * is also known as “Modulus 10” algorithm.<br>
     * It is a simple checksum formula used to validate a variety of
     * identification numbers,<br>
     * such as credit card numbers, IMEI numbers, National Provider Identifier
     * numbers in US and Canadian Social Insurance Numbers.<br>
     * It was created by IBM scientist Hans Peter Luhn.<br>
     * Verification is done by validating check digit.<br><br>
     *
     * <p>
     * simply Double the value of every second digit from the right end (first
     * right will be check digit number). Add the individual digits comprising
     * both the products from step (1) and unaffected digits in the original
     * number. If the total modulo 10 is equal to 0, then the number is valid,
     * else it is not valid. an example of IMEI no. 490154203237518</p>
     */
    private void validateIMEI() {

        final int[] numbers = field.getText().chars().map(this::ConvertASCIIToNumer).toArray();
        boolean isValid = IntStream.range(0, numbers.length)
                .map(i -> (((i % 2) ^ (numbers.length % 2)) == 0)
                        ? ((2 * numbers[i]) / 10 + (2 * numbers[i]) % 10)
                        : numbers[i])
                .sum() % 10 == 0;

        if (isValid) {
            status.setStyle(VALID_LABEL_CSS);
            status.setText("VALID");
        } else {
            status.setText("INVALID");
            status.setStyle(INVALID_LABEL_CSS);
        }
    }

    /**
     * Returns the numeric value of the ASCII
     */
    private int ConvertASCIIToNumer(int value) {
        return Character.digit(value, 10);
    }

    /**
     * a specific class for Holding
     * <a href =
     * "https://en.wikipedia.org/wiki/International_Mobile_Station_Equipment_Identity">
     * IMEI Numbers
     * </a>
     */
    class IMEIField extends TextField {

        private final int LIMIT = 15;//A Valid IMEI Number has 15 digits

        @Override
        public void replaceText(int start, int end, String text) {
            if (validate(text)) {
                super.replaceText(start, end, text);
                onLengthListener();
            }
        }

        @Override
        public void replaceSelection(String text) {
            if (validate(text)) {
                super.replaceSelection(text);
                onLengthListener();
            }
        }

        private void onLengthListener() {
            //Stop if user type more than LIMIT
            textProperty().
                    addListener((observable, oldValue, newValue) -> {
                        if (newValue.length() > LIMIT) {
                            setText(oldValue);
                        }
                    });

        }

        /**
         * Validate input against the {@link String} and make sure input is
         * Number only
         *
         * @return true if the value is a Numeric Value <b>0-9</b>
         */
        private boolean validate(String text) {

            //furtuhre check can be done for "Empty input" or for "White Space"
            //return (" ".equals(text) || "".equals(text) ||text.matches("[0-9]"));
            return ("".equals(text) || text.matches("[0-9]"));
        }

    }

    //Mr. Main
    public static void main(String[] args) {
        launch(args);//Entry point for the FX Thread

    }

}

No comments :

Post a Comment