io.github.carlomicieli.footballdb.starter.mapping.Height.java Source code

Java tutorial

Introduction

Here is the source code for io.github.carlomicieli.footballdb.starter.mapping.Height.java

Source

/*
 * Copyright 2014 the original author or authors.
 *
 *  Licensed 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 io.github.carlomicieli.footballdb.starter.mapping;

import org.apache.commons.lang3.StringUtils;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * It represent a football player height, expressed in feet and inches.
 * @author Carlo Micieli
 */
public final class Height {

    public static final int INCHES_BY_FOOT = 12;
    private final int feet;
    private final int inches;

    private final static Pattern NORMAL_PATTERN = Pattern.compile("(\\d)'(\\d{1,2})\"");
    private final static Pattern SHORT_PATTERN = Pattern.compile("(\\d)-(\\d{1,2})");

    private Height(int feet, int inches) {
        this.feet = feet;
        this.inches = inches;
    }

    public int feet() {
        return feet;
    }

    public int inches() {
        return inches;
    }

    public static Height valueOf(String value) {
        if (StringUtils.isBlank(value)) {
            return null;
        }

        return extractValue(value, NORMAL_PATTERN).orElseGet(() -> extractValue(value, SHORT_PATTERN).orElse(null));
    }

    public int toCentimeters() {
        final double INCHES_TO_CENTIMETERS = 2.54;
        final double FEET_TO_CENTIMETERS = 30.48;

        return (int) Math.round(INCHES_TO_CENTIMETERS * inches + FEET_TO_CENTIMETERS * feet);
    }

    @Override
    public String toString() {
        return feet + "'" + inches + "\"";
    }

    @Override
    public int hashCode() {
        return Objects.hash(feet, inches);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this)
            return true;
        if (!(obj instanceof Height))
            return false;

        Height that = (Height) obj;
        return Objects.equals(this.feet, that.feet) && Objects.equals(this.inches, that.inches);
    }

    private static Optional<Height> extractValue(String value, Pattern p) {
        Matcher m = p.matcher(value);
        if (m.find()) {
            int f = Integer.parseInt(m.group(1));
            int i = Integer.parseInt(m.group(2));
            return Optional.ofNullable(new Height(f, i));
        }

        return Optional.empty();
    }

    public static Height of(int feet, int inches) {
        check(() -> feet >= 0 && feet < 9, "invalid value for 'feet'");
        check(() -> inches >= 0, "negative value for 'inches'");
        return new Height(feet, inches);
    }

    private static void check(Supplier<Boolean> op, String msg) {
        if (!op.get())
            throw new IllegalArgumentException("Invalid height: " + msg);
    }

    public Height normalize() {
        int inches = this.inches % INCHES_BY_FOOT;
        int feet = this.feet + ((this.inches - inches) / INCHES_BY_FOOT);
        return new Height(feet, inches);
    }

    public int toInches() {
        return this.inches + (this.feet * INCHES_BY_FOOT);
    }
}