/******************************************************************************* * Copyright (c) 2012-2016 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.everrest.core; import org.everrest.core.impl.ConstructorDescriptorImpl; import org.everrest.core.impl.FieldInjectorImpl; import org.everrest.core.impl.MultivaluedMapImpl; import org.everrest.core.impl.method.ParameterResolverFactory; import org.slf4j.LoggerFactory; import javax.ws.rs.core.MultivaluedMap; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class BaseObjectModel implements ObjectModel { private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(BaseObjectModel.class); private static final Comparator<ConstructorDescriptor> CONSTRUCTOR_COMPARATOR_BY_NUMBER_OF_PARAMETERS = new ConstructorComparatorByNumberOfParameters(); /** Compare two ConstructorDescriptor in number parameters order. */ private static class ConstructorComparatorByNumberOfParameters implements Comparator<ConstructorDescriptor> { @Override public int compare(ConstructorDescriptor constructorDescriptorOne, ConstructorDescriptor constructorDescriptorTwo) { int result = constructorDescriptorTwo.getParameters().size() - constructorDescriptorOne.getParameters().size(); if (result == 0) { LOG.warn("Two constructors with the same number of parameter found {} and {}", constructorDescriptorOne, constructorDescriptorTwo); } return result; } } protected final Class<?> clazz; protected final List<ConstructorDescriptor> constructors; protected final List<FieldInjector> fields; private ParameterResolverFactory parameterResolverFactory; /** Optional properties. */ private MultivaluedMapImpl properties; public BaseObjectModel(Object instance) { this.clazz = instance.getClass(); this.constructors = new ArrayList<>(); this.fields = new ArrayList<>(); parameterResolverFactory = new ParameterResolverFactory(); } public BaseObjectModel(Class<?> clazz) { this.clazz = clazz; this.constructors = new ArrayList<>(); this.fields = new ArrayList<>(); parameterResolverFactory = new ParameterResolverFactory(); processConstructors(); sortConstructorByNumberOfParameters(); processFields(); } void setParameterResolverFactory(ParameterResolverFactory parameterResolverFactory) { this.parameterResolverFactory = parameterResolverFactory; } protected void processConstructors() { for (Constructor<?> constructor : clazz.getConstructors()) { constructors.add(new ConstructorDescriptorImpl(constructor, parameterResolverFactory)); } if (constructors.size() == 0) { throw new RuntimeException(String.format("Not found accepted constructors for provider class %s", clazz.getName())); } } private void sortConstructorByNumberOfParameters() { if (constructors.size() > 1) { Collections.sort(constructors, CONSTRUCTOR_COMPARATOR_BY_NUMBER_OF_PARAMETERS); } } protected void processFields() { for (java.lang.reflect.Field jField : clazz.getDeclaredFields()) { fields.add(new FieldInjectorImpl(jField, parameterResolverFactory)); } Class<?> superclass = clazz.getSuperclass(); while (superclass != null && superclass != Object.class) { for (java.lang.reflect.Field jField : superclass.getDeclaredFields()) { FieldInjector fieldInjector = new FieldInjectorImpl(jField, parameterResolverFactory); if (fieldInjector.getAnnotation() != null) { fields.add(fieldInjector); } } superclass = superclass.getSuperclass(); } } @Override public Class<?> getObjectClass() { return clazz; } @Override public List<ConstructorDescriptor> getConstructorDescriptors() { return constructors; } @Override public List<FieldInjector> getFieldInjectors() { return fields; } @Override public MultivaluedMap<String, String> getProperties() { if (properties == null) { properties = new MultivaluedMapImpl(); } return properties; } @Override public List<String> getProperty(String key) { if (properties != null) { return properties.get(key); } return null; } }