org.agatom.springatom.data.vin.decoder.resolver.DefaultWMIManufacturedInResolver.java Source code

Java tutorial

Introduction

Here is the source code for org.agatom.springatom.data.vin.decoder.resolver.DefaultWMIManufacturedInResolver.java

Source

/**************************************************************************************************
 * This file is part of [SpringAtom] Copyright [kornicameister@gmail.com][2014]                   *
 * *
 * [SpringAtom] is free software: you can redistribute it and/or modify                           *
 * it under the terms of the GNU General Public License as published by                           *
 * the Free Software Foundation, either version 3 of the License, or                              *
 * (at your option) any later version.                                                            *
 * *
 * [SpringAtom] is distributed in the hope that it will be useful,                                *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of                                 *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                  *
 * GNU General Public License for more details.                                                   *
 * *
 * You should have received a copy of the GNU General Public License                              *
 * along with [SpringAtom].  If not, see <http://www.gnu.org/licenses/gpl.html>.                  *
 **************************************************************************************************/

package org.agatom.springatom.data.vin.decoder.resolver;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Maps;
import com.neovisionaries.i18n.CountryCode;
import javassist.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Description;
import org.springframework.context.annotation.Role;
import org.springframework.core.io.FileSystemResourceLoader;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Component
@Role(BeanDefinition.ROLE_SUPPORT)
@Description("Retrieves manufacturedIn by looking up in the entries loaded from file storage")
class DefaultWMIManufacturedInResolver implements WMIManufacturedInResolver {
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultWMIManufacturedInResolver.class);
    private static final String WMI_PATH = "classpath:org/agatom/springatom/data/wmi.json";
    @Autowired
    private ObjectMapper objectMapper = null;
    private Map<CodeRangeWrapper, CountryCode> countryCodeMap = Maps.newTreeMap();

    @PostConstruct
    private void initializeWMICodes() {
        try {
            final InputStream stream = new FileSystemResourceLoader().getResource(WMI_PATH).getInputStream();
            final WMIBeanList wmiBeans = this.objectMapper.readValue(stream, WMIBeanList.class);
            Assert.notNull(wmiBeans, "Failed to read WMI codes, returned WMIBeanList is null");
            this.postProcessWMIBeans(wmiBeans);
        } catch (Exception exp) {
            LOGGER.error("initializeWMICodes failed", exp);
        }
    }

    private void postProcessWMIBeans(final WMIBeanList wmiBeans) throws NotFoundException {
        for (final WMIBean wmiBean : wmiBeans) {
            final List<String> codes = wmiBean.codes;
            Assert.notEmpty(codes);

            final List<CountryCode> byName = CountryCode.findByName(wmiBean.country);
            if (CollectionUtils.isEmpty(byName)) {
                final String format = String.format("%s has no country code corresponding", wmiBean.country);
                LOGGER.warn(format);
                continue;
            }

            for (final String code : codes) {
                final String[] split = code.split("-");

                final CodeRangeWrapper wrapper = CodeRangeWrapper.newCodeRangeWrapper(split[0],
                        split.length == 2 ? split[1] : "");
                final CountryCode countryCode = byName.get(0);

                LOGGER.trace(String.format("Key=>%s, CountryCode=%s", wrapper, countryCode));

                this.countryCodeMap.put(wrapper, countryCode);
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public CountryCode getCountryCode(final String wmi) {
        final String cc = wmi.substring(0, 2);
        final Set<CodeRangeWrapper> codeRangeWrappers = this.countryCodeMap.keySet();
        final Optional<CodeRangeWrapper> fm = FluentIterable.from(codeRangeWrappers)
                .firstMatch(new Predicate<CodeRangeWrapper>() {
                    @Override
                    public boolean apply(@Nullable final CodeRangeWrapper input) {
                        LOGGER.trace(String.format("Examining CRW=%s", input));
                        assert input != null;
                        return input.isInRange(cc);
                    }
                });
        if (fm.isPresent()) {
            return this.countryCodeMap.get(fm.get());
        }
        return null;
    }

    private static class CodeRangeWrapper implements Comparable<CodeRangeWrapper> {
        char[] bArray = null;
        char[] eArray = null;
        private String beginCode = null;
        private String endCode = null;

        static CodeRangeWrapper newCodeRangeWrapper(final String beginCode, final String endCode) {
            final CodeRangeWrapper wrapper = new CodeRangeWrapper();
            wrapper.bArray = CodeRangeWrapper.toCharArray(beginCode);
            wrapper.eArray = CodeRangeWrapper.toCharArray(endCode);
            wrapper.beginCode = beginCode;
            wrapper.endCode = endCode;
            return wrapper;
        }

        static char[] toCharArray(final String str) {
            if (!StringUtils.hasText(str)) {
                return new char[] {};
            }
            final int length = str.length();
            final char[] arr = new char[length];
            for (int i = 0; i < length; i++) {
                arr[i] = str.charAt(i);
            }
            return arr;
        }

        boolean isInRange(final String code) {
            final char[] chars = CodeRangeWrapper.toCharArray(code);
            final int length = chars.length;
            boolean inRange = false;
            for (int i = 0; i < length; i++) {
                if (this.eArray.length != 0) {
                    inRange = this.bArray[i] <= chars[i] && chars[i] <= this.eArray[i];
                } else {
                    inRange = this.bArray[i] == chars[i];
                }
                if (!inRange) {
                    return false;
                }
            }
            return inRange;
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(bArray, eArray);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;

            CodeRangeWrapper that = (CodeRangeWrapper) o;

            return Objects.equal(this.bArray, that.bArray) && Objects.equal(this.eArray, that.eArray);
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(this).addValue(beginCode).addValue(endCode).toString();
        }

        @Override
        public int compareTo(@Nonnull final CodeRangeWrapper crw) {
            return ComparisonChain.start().compare(this.beginCode, crw.beginCode).compare(this.endCode, crw.endCode)
                    .result();
        }
    }

    @SuppressWarnings("UnusedDeclaration")
    public static class WMIBeanList implements Serializable, Iterable<WMIBean> {
        private static final long serialVersionUID = 3060321745730000503L;
        private Set<WMIBean> wmi = null;

        public WMIBeanList() {
        }

        public Set<WMIBean> getWmi() {
            return wmi;
        }

        public WMIBeanList setWmi(final Set<WMIBean> wmi) {
            this.wmi = wmi;
            return this;
        }

        @Override
        public Iterator<WMIBean> iterator() {
            return this.wmi.iterator();
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(this).addValue(wmi).toString();
        }
    }

    private static class WMIBean implements Serializable {
        private static final long serialVersionUID = -8996607327207872771L;
        private String country = null;
        private List<String> codes = null;

        public WMIBean() {
        }

        public String getCountry() {
            return country;
        }

        public WMIBean setCountry(final String country) {
            this.country = country;
            return this;
        }

        public List<String> getCodes() {
            return codes;
        }

        public WMIBean setCodes(final List<String> codes) {
            this.codes = codes;
            return this;
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(this).addValue(country).addValue(codes).toString();
        }
    }
}