it.unibz.inf.ontop.sql.ForeignKeyConstraint.java Source code

Java tutorial

Introduction

Here is the source code for it.unibz.inf.ontop.sql.ForeignKeyConstraint.java

Source

package it.unibz.inf.ontop.sql;

/*
 * #%L
 * ontop-obdalib-core
 * %%
 * Copyright (C) 2009 - 2014 Free University of Bozen-Bolzano
 * %%
 * 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.
 * #L%
 */

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;

import java.util.ArrayList;
import java.util.List;

/**
 * Foreign Key constraints<br>
 * 
 * FOREIGN KEY (columnName (, columnName)*)  
 *          REFERENCES refTableName   (refColumnName (, refColumnName)*)<br>
 * 
 * (a particular case of linear tuple-generating dependencies<br>
 * \forall x (\exists y_1 R_1(x,y_1) \to \exists y_2 R_2(x,y_2))<br>
 * where x, y_1 and y_2 are *tuples* of variables)
 * 
 * @author Roman Kontchakov
 *
 */

public class ForeignKeyConstraint {

    public static final class Component {
        private final Attribute attribute, reference;

        private Component(Attribute attribute, Attribute reference) {
            this.attribute = attribute;
            this.reference = reference;
        }

        public Attribute getAttribute() {
            return attribute;
        }

        public Attribute getReference() {
            return reference;
        }

    }

    public static final class Builder {
        private final ImmutableList.Builder<Component> builder = new ImmutableList.Builder<>();
        private final DatabaseRelationDefinition relation, referencedRelation;

        /**
         * creates a FOREIGN KEY builder 
         * 
         * @param relation 
         * @param referencedRelation
         */

        public Builder(DatabaseRelationDefinition relation, DatabaseRelationDefinition referencedRelation) {
            this.relation = relation;
            this.referencedRelation = referencedRelation;
        }

        /**
         * adds a pair (attribute, referenced attribute) to the FK constraint
         * 
         * @param attribute
         * @param referencedAttribute
         * @return
         */

        public Builder add(Attribute attribute, Attribute referencedAttribute) {
            if (relation != attribute.getRelation())
                throw new IllegalArgumentException("Foreign Key requires the same table in all attributes: "
                        + relation + " -> " + referencedRelation + " (attribute " + attribute.getRelation().getID()
                        + "." + attribute + ")");

            if (referencedRelation != referencedAttribute.getRelation())
                throw new IllegalArgumentException(
                        "Foreign Key requires the same table in all referenced attributes: " + relation + " -> "
                                + referencedRelation + " (attribute " + referencedAttribute.getRelation().getID()
                                + "." + referencedAttribute + ")");

            builder.add(new Component(attribute, referencedAttribute));
            return this;
        }

        /**
         * builds a FOREIGN KEY constraint
         * 
         * @param name
         * @return null if the list of components is empty
         */

        public ForeignKeyConstraint build(String name) {
            ImmutableList<Component> components = builder.build();
            if (components.isEmpty())
                return null;

            return new ForeignKeyConstraint(name, components);
        }
    }

    /**
     * creates a FOREIGN KEY builder
     * 
     * @param relation
     * @param referencedRelation
     * @return
     */

    public static Builder builder(DatabaseRelationDefinition relation,
            DatabaseRelationDefinition referencedRelation) {
        return new Builder(relation, referencedRelation);
    }

    /**
     * creates a single-attribute foreign key 
     * 
     * @param name
     * @param attribute
     * @param referenced attribute
     * @return
     */
    public static ForeignKeyConstraint of(String name, Attribute attribute, Attribute reference) {
        return new Builder((DatabaseRelationDefinition) attribute.getRelation(),
                (DatabaseRelationDefinition) reference.getRelation()).add(attribute, reference).build(name);
    }

    private final String name;
    private final ImmutableList<Component> components;
    private final DatabaseRelationDefinition relation, referencedRelation;

    /**
     * private constructor (use Builder instead)
     * 
     * @param name
     * @param components
     */

    private ForeignKeyConstraint(String name, ImmutableList<Component> components) {
        this.name = name;
        this.components = components;
        this.relation = (DatabaseRelationDefinition) components.get(0).getAttribute().getRelation();
        this.referencedRelation = (DatabaseRelationDefinition) components.get(0).getReference().getRelation();
    }

    /**
     * returns the name of the foreign key constraint
     * 
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * returns the components of the foreign key constraint
     * each component defines a map from an attribute of the relation 
     *          to an attribute of the referenced relation
     *  
     * @return
     */
    public ImmutableList<Component> getComponents() {
        return components;
    }

    /**
     * returns referenced database relation
     * 
     * @return referenced relation 
     */
    public DatabaseRelationDefinition getReferencedRelation() {
        return referencedRelation;
    }

    /**
     * returns the relation with the foreign key
     * 
     * @return relation
     */

    public DatabaseRelationDefinition getRelation() {
        return relation;
    }

    @Override
    public String toString() {
        List<String> columns = new ArrayList<>(components.size());
        List<String> refColumns = new ArrayList<>(components.size());
        for (Component c : components) {
            columns.add(c.getAttribute().getID().toString());
            refColumns.add(c.getReference().getID().toString());
        }

        StringBuilder bf = new StringBuilder();

        bf.append("ALTER TABLE ").append(relation.getID().getSQLRendering()).append(" ADD CONSTRAINT ").append(name)
                .append(" FOREIGN KEY (");
        Joiner.on(", ").appendTo(bf, columns);
        bf.append(") REFERENCES ").append(referencedRelation.getID().getSQLRendering()).append(" (");
        Joiner.on(", ").appendTo(bf, refColumns);
        bf.append(")");

        return bf.toString();
    }
}