org.agatom.springatom.data.oid.impl.SOidServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.agatom.springatom.data.oid.impl.SOidServiceImpl.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.oid.impl;

import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Maps;
import org.agatom.springatom.data.oid.SOid;
import org.agatom.springatom.data.oid.SOidCreator;
import org.agatom.springatom.data.oid.SOidService;
import org.agatom.springatom.data.oid.annotation.OidProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;

import static org.springframework.core.GenericTypeResolver.resolveTypeArgument;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;

/**
 * <p>
 * <small>Class is a part of <b>SpringAtom</b> and was created at 2014-09-17</small>
 * </p>
 *
 * @author trebskit
 * @version 0.0.1
 * @since 0.0.1
 */
@Service("oidService")
@Role(BeanDefinition.ROLE_SUPPORT)
@Scope(BeanDefinition.SCOPE_SINGLETON)
class SOidServiceImpl implements SOidService {

    @Autowired
    private Collection<SOidCreator<?>> oidCreators = null;
    private Map<OidCreatorKey, SOidCreator<?>> oidCreatorsMap;

    @PostConstruct
    @SuppressWarnings("ConstantConditions")
    private void readOidCreators() {
        Assert.notEmpty(oidCreators);
        final Map<OidCreatorKey, SOidCreator<?>> localMap = Maps
                .newHashMapWithExpectedSize(this.oidCreators.size());
        for (final SOidCreator<?> oidCreator : oidCreators) {

            final Class<?> supportedType = resolveTypeArgument(oidCreator.getClass(), SOidCreator.class);
            final String prefix = findAnnotation(oidCreator.getClass(), OidProvider.class).prefix();

            localMap.put(new OidCreatorKey().setPrefix(prefix).setSupportedClass(supportedType), oidCreator);
        }
        this.oidCreatorsMap = Collections.unmodifiableMap(localMap);
    }

    @Override
    public SOid getOid(@Nonnull final String oid) throws Exception {
        final SOidCreator creator = this.getCreator(oid.split(":")[0]);
        return creator != null ? creator.fromString(oid) : null;
    }

    @Override
    public SOid getOid(@Nonnull final Object obj) throws Exception {
        try {
            final Class<?> userClass = ClassUtils.getUserClass(obj);
            final Method getOid = ClassUtils.getMethod(userClass, "getOid");
            final Object invoke = getOid.invoke(obj);
            if (invoke != null) {
                return (SOid) invoke;
            }
        } catch (Exception exp) {
            // ignore
        }
        final SOidCreator creator = this.getCreator(ClassUtils.getUserClass(obj));
        return creator != null ? creator.fromObject(obj) : null;
    }

    private SOidCreator<?> getCreator(final Class<?> clazz) {
        final Optional<OidCreatorKey> match = FluentIterable.from(this.oidCreatorsMap.keySet())
                .firstMatch(new Predicate<OidCreatorKey>() {
                    @Override
                    public boolean apply(@Nullable final OidCreatorKey input) {
                        assert input != null;
                        final Class<?> supportedType = input.supportedClass;
                        return ClassUtils.isAssignable(supportedType, clazz)
                                || ClassUtils.determineCommonAncestor(clazz, supportedType) != null;
                    }
                });
        if (match.isPresent()) {
            final OidCreatorKey key = match.get();
            return this.oidCreatorsMap.get(key);
        }
        return null;
    }

    private SOidCreator<?> getCreator(final String prefix) {
        final Optional<OidCreatorKey> match = FluentIterable.from(this.oidCreatorsMap.keySet())
                .firstMatch(new Predicate<OidCreatorKey>() {
                    @Override
                    public boolean apply(@Nullable final OidCreatorKey input) {
                        assert input != null;
                        return input.prefix.equalsIgnoreCase(prefix);
                    }
                });
        if (match.isPresent()) {
            final OidCreatorKey key = match.get();
            return this.oidCreatorsMap.get(key);
        }
        return null;
    }

    private static final class OidCreatorKey {
        private String prefix = null;
        private Class<?> supportedClass = null;

        public OidCreatorKey setPrefix(final String prefix) {
            this.prefix = prefix;
            return this;
        }

        public OidCreatorKey setSupportedClass(final Class<?> supportedClass) {
            this.supportedClass = ClassUtils.getUserClass(supportedClass);
            return this;
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(prefix, supportedClass);
        }

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

            OidCreatorKey that = (OidCreatorKey) o;

            return Objects.equal(this.prefix, that.prefix)
                    && Objects.equal(this.supportedClass, that.supportedClass);
        }
    }
}