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

com.codeslap.persistence.HasMany Maven / Gradle / Ivy

/*
 * Copyright 2013 CodeSlap
 *
 * 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 com.codeslap.persistence;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * Establishes a has many relation
 *
 * @author cristian
 * @version 1.0
 */
public class HasMany {

    private final Class mContainerClass;
    private final Class mContainedClass;
    private final String mThrough;
    private final String mThroughColumnName;
    private final Field mThroughField;

    public HasMany(Class classA, Class hasMany, String through, boolean artificial) {
        // do not accept recursive relations
        if (classA == hasMany) {
            throw new IllegalArgumentException("Recursive has-many relations are not accepted");
        }
        // make sure the 'through' exists
        try {
            mThroughField = classA.getDeclaredField(through);
            mThroughColumnName = SQLHelper.getColumnName(mThroughField);
        } catch (NoSuchFieldException e) {
            throw new IllegalStateException(e);
        }
        if (!artificial) {
            // we must make sure the relation exists
            boolean relationExists = false;
            for (Field field : SQLHelper.getDeclaredFields(classA)) {
                if (field.getType() == List.class) {
                    ParameterizedType stringListType = (ParameterizedType) field.getGenericType();
                    Class collectionClass = (Class) stringListType.getActualTypeArguments()[0];
                    if (collectionClass == hasMany) {
                        relationExists = true;
                        break;
                    }
                }
            }
            // if relation does not exist, do not continue
            if (!relationExists) {
                String msg = String.format("Relation does not exist (%s has many %s)", classA, hasMany);
                throw new IllegalStateException(msg);
            }
        }
        // if it does exist, set the fields
        mContainerClass = classA;
        mContainedClass = hasMany;
        mThrough = through;
    }

    public HasMany(Class classA, Class hasMany, String through) {
        this(classA, hasMany, through, false);
    }

    /**
     * Creates a has-many relation
     *
     * @param classA  the class that has many objects...
     * @param hasMany the class contained in classA
     */
    public HasMany(Class classA, Class hasMany) {
        this(classA, hasMany, SQLHelper.getPrimaryKey(hasMany));
    }

    /**
     * Creates a has-many relation
     *
     * @param classA     the class that has many objects...
     * @param hasMany    the class contained in classA
     * @param artificial must be true if the relation does not actually exists and you will force it
     */
    public HasMany(Class classA, Class hasMany, boolean artificial) {
        this(classA, hasMany, SQLHelper.ID, artificial);
    }

    Class getContainerClass() {
        return mContainerClass;
    }

    Class getContainedClass() {
        return mContainedClass;
    }

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

        HasMany hasMany = (HasMany) o;

        if (mContainerClass != null ? !mContainerClass.equals(hasMany.mContainerClass) : hasMany.mContainerClass != null)
            return false;
        if (mContainedClass != null ? !mContainedClass.equals(hasMany.mContainedClass) : hasMany.mContainedClass != null)
            return false;
        if (mThrough != null ? !mThrough.equals(hasMany.mThrough) : hasMany.mThrough != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = mContainerClass != null ? mContainerClass.hashCode() : 0;
        result = 31 * result + (mContainedClass != null ? mContainedClass.hashCode() : 0);
        result = 31 * result + (mThrough != null ? mThrough.hashCode() : 0);
        return result;
    }

    String getThroughColumnName() {
        return mThroughColumnName;
    }

    Field getThroughField() {
        return mThroughField;
    }

    String getForeignKey() {
        return String.format("%s_%s", SQLHelper.normalize(mContainerClass.getSimpleName()), SQLHelper.normalize(mThrough));
    }

    @Override
    public String toString() {
        return mContainerClass + " has many " + mContainedClass + " through " + mThrough;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy