All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.restup.mapping.MappedClass Maven / Gradle / Ivy

There is a newer version: 0.0.5
Show newest version
package com.github.restup.mapping;

import com.github.restup.mapping.fields.MappedField;
import com.github.restup.util.Assert;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.commons.lang3.StringUtils;

/**
 * Provides an api to object to persistence mapping.
 *
 * @author andy.buttaro
 */
public interface MappedClass {

    static Builder builder() {
        return new AnonymousBuilder();
    }

    static  Builder builder(Class type) {
        return new Builder<>(type);
    }

    static Comparator> getDefaultFieldComparator() {
        return new DefaultMappedFieldComparator();
    }

    /**
     * @return The name of the object
     */
    String getName();

    /**
     * @return The pluralized name of the object
     */
    String getPluralName();

    /**
     * @return The type of the object
     */
    Type getType();

    /**
     * @return The type of the object's parent
     */
    Type getParentType();

    /**
     * If nested properties of this mapping have a {@link java.util.Map} with typed properties then
     * this should return true.
     *
     * @return true if the model contains a {@link java.util.Map} with typed properties
     */
    boolean isTypedMapPresent();

    /**
     * @return The attributes of the object
     */
    List> getAttributes();

    /**
     * @return a new instance of {@link #getType()}
     */
    T newInstance();

    static class AnonymousBuilder extends Builder {

        @Override
        public Builder addAttribute(MappedField.Builder builder) {
            builder.anonymousMapping();
            return super.addAttribute(builder);
        }
    }

    static class Builder {

        private final Type type;
        private String name;
        private String pluralName;
        private Type parentType;
        private List> attributes;
        private Comparator> fieldComparator;

        Builder(Type type) {
            Assert.notNull(type, "type is required");
            this.type = type;
            this.attributes = new ArrayList<>();
        }

        Builder() {
            this(new UntypedClass<>());
        }

        private Builder me() {
            return this;
        }

        public Builder name(String name) {
            this.name = name;
            return this.me();
        }

        public Builder defaultName(String name) {
            if (StringUtils.isEmpty(this.name)) {
                return this.name(name);
            }
            return this.me();
        }

        public Builder pluralName(String pluralName) {
            this.pluralName = pluralName;
            return this.me();
        }

        public Builder attributes(List> attributes) {
            this.attributes = attributes;
            return this.me();
        }

        Builder addAttribute(MappedField attribute) {
            this.attributes.add(attribute);
            return this.me();
        }

        public Builder addAttribute(MappedField.Builder builder) {
            return this.addAttribute(builder.build());
        }

        public Builder addAttribute(Class type, String name) {
            return this.addAttribute(this.attribute(type, name));
        }

        public Builder addCaseInsensitiveAttribute(String name, String lowerCaseNameField) {
            return this.addAttribute(MappedField.builder(String.class)
                .apiName(name)
                .caseSensitiviteField(lowerCaseNameField))
                // add lowerCaseNameField
                .addAttribute(MappedField.builder(String.class)
                    .beanName(lowerCaseNameField));
        }

        public Builder id(Class type) {
            return this.id(type, "id");
        }

        public Builder id(Class type, String name) {
            return this.addAttribute(this.attribute(type, name)
                .idField(true));
        }

        private MappedField.Builder attribute(Class type, String name) {
            return MappedField.builder(type)
                .apiName(name)
                .persistedName(name)
                .beanName(name);
        }

        public Builder sortAttributesWith(Comparator> fieldComparator) {
            this.fieldComparator = fieldComparator;
            return this.me();
        }

        public Builder parentType(Class parentType) {
            this.parentType = parentType;
            return this.me();
        }

        public MappedClass build() {
            Assert.notEmpty(this.name, "name is required");
            String pluralName = this.pluralName;
            boolean containsTypedMap = this.type instanceof UntypedClass;
            if (StringUtils.isEmpty(pluralName)) {
                pluralName = this.name + "s";
            }
            if (this.fieldComparator != null) {
                Collections.sort(this.attributes, this.fieldComparator);
            }
            return new BasicMappedClass<>(this.name, pluralName, this.type, this.parentType,
                this.attributes, containsTypedMap);
        }

    }

}