/******************************************************************************
* Copyright: GPL v3 *
* *
* This program 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. *
* *
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>. *
******************************************************************************/
package dbaCore.logic.normalization;
import dbaCore.data.Attribute;
import dbaCore.data.FunctionalDependency;
import dbaCore.data.NormalizationResult;
import dbaCore.data.RelationSchema;
import dbaCore.logic.Analysis.RelationUtils;
import java.util.ArrayList;
/**
* Normalization to 2.NF using Decomposition
*
* @author Sebastian Theuermann
*/
public class DecompositionTo2NF extends Decomposition {
@Override
public void normalize(RelationSchema relationToNormalize, NormalizationResult result, Boolean minimizeFds) {
if (minimizeFds) {
normalizeRelation(getMinimalRelation(relationToNormalize), result);
} else {
normalizeRelation(relationToNormalize, result);
}
}
private void normalizeRelation(RelationSchema relationToNormalize, NormalizationResult result) {
RelationSchema newSchema;
ArrayList<FunctionalDependency> violatingFds = checker.checkForSecondNF(relationToNormalize);
FunctionalDependency violatingFd;
// If there is no FD violating 2NF ==> nothing to do here
if (relationToNormalize.getFunctionalDependencies().isEmpty() || violatingFds.isEmpty()) {
// Remove duplicate entry of relation in results
for (RelationSchema relation : result.getRelations()) {
if (relation.equals(relationToNormalize)) {
result.getRelations().remove(relation);
break;
}
}
result.getRelations().add(relationToNormalize);
return;
}
// FD Y ==> A violates 2NF
newSchema = new RelationSchema();
newSchema.setName(RelationUtils.getInstance().getRelationName(relationToNormalize.getName(),
result.getRelations()));
violatingFd = violatingFds.get(0);
// S2 = YA
// S1 = S - A
transferFd(relationToNormalize, newSchema, violatingFd);
// Update keys
updatePrimaryAndForeignKeys(relationToNormalize, newSchema, result.getForeignKeys());
// Recursive calls
normalizeRelation(newSchema, result);
normalizeRelation(relationToNormalize, result);
}
/**
* Transfers the Fd and it's attributes to a new relation
*
* @param oldSchema the old relation containing the fd
* @param newSchema the new schema as target of the transfer
* @param fd the functionalDependency that should be transfered
*/
private void transferFd(RelationSchema oldSchema, RelationSchema newSchema, FunctionalDependency fd) {
oldSchema.removeFunctionalDependency(fd);
// Copy everything to new schema
for (Attribute sourceAttribute : fd.getSourceAttributes()) {
newSchema.addAttribute((Attribute) sourceAttribute.getClone());
}
for (Attribute targetAttribute : fd.getTargetAttributes()) {
newSchema.addAttribute((Attribute) targetAttribute.getClone());
}
newSchema.getFunctionalDependencies().add(fd.getClone());
// reconnect attributes with functional dependencies
newSchema.restoreReferences();
// Remove copied things in the old schema
oldSchema.getAttributes().removeAll(fd.getTargetAttributes());
}
}