/** * Licensed to the Austrian Association for Software Tool Integration (AASTI) * under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright * ownership. The AASTI licenses this file to you 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 org.openengsb.core.ekb.persistence.persist.edb.internal; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.apache.commons.lang.reflect.FieldUtils; import org.openengsb.core.api.model.OpenEngSBModel; import org.openengsb.core.edb.api.EDBObject; import org.openengsb.core.edb.api.EngineeringDatabaseService; import org.openengsb.core.ekb.common.EDBConverter; import org.openengsb.core.util.ModelUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Objects; /** * The ModelDiff class was introduced for the easier calculation and handling of the differences of two models. */ public final class ModelDiff { private static final Logger LOGGER = LoggerFactory.getLogger(ModelDiff.class); private OpenEngSBModel before; private OpenEngSBModel after; private Map<Field, ModelDiffEntry> differences; /** * Creates an instance of the ModelDiff class based on the both models which are passed to the function. It * instantiate the class and calculates the differences of this two models. */ public static ModelDiff createModelDiff(OpenEngSBModel before, OpenEngSBModel after) { ModelDiff diff = new ModelDiff(before, after); calculateDifferences(diff); return diff; } /** * Creates an instance of the ModelDiff class based on the given model. It loads the old status of the model and * calculates the differences of this two models. */ public static ModelDiff createModelDiff(OpenEngSBModel updated, String completeModelId, EngineeringDatabaseService edbService, EDBConverter edbConverter) { EDBObject queryResult = edbService.getObject(completeModelId); OpenEngSBModel old = edbConverter.convertEDBObjectToModel(updated.getClass(), queryResult); ModelDiff diff = new ModelDiff(old, updated); calculateDifferences(diff); return diff; } private ModelDiff(OpenEngSBModel before, OpenEngSBModel after) { this.before = before; this.after = after; differences = new HashMap<Field, ModelDiffEntry>(); } /** * Calculates the real differences between the two models of the given ModelDiff and saves them to the differences * field of the ModelDiff class. */ private static void calculateDifferences(ModelDiff diff) { Class<?> modelClass = diff.getBefore().getClass(); for (Field field : modelClass.getDeclaredFields()) { if (field.getName().equals(ModelUtils.MODEL_TAIL_FIELD_NAME)) { continue; } try { Object before = FieldUtils.readField(field, diff.getBefore(), true); Object after = FieldUtils.readField(field, diff.getAfter(), true); if (!Objects.equal(before, after)) { diff.addDifference(field, before, after); } } catch (IllegalAccessException e) { LOGGER.warn("Skipped field '{}' because of illegal access to it", field.getName(), e); } } } /** * Adds a difference to the list of differences of this ModelDiff instance. */ public void addDifference(Field field, Object before, Object after) { ModelDiffEntry entry = new ModelDiffEntry(); entry.setBefore(before); entry.setAfter(after); entry.setField(field); differences.put(field, entry); } /** * Returns true if one of the differences of this ModelDiff instance is an OpenEngSBForeignKey. Returns false * otherwise. */ public boolean isForeignKeyChanged() { return CollectionUtils.exists(differences.values(), new Predicate() { @Override public boolean evaluate(Object object) { return ((ModelDiffEntry) object).isForeignKey(); } }); } /** * Returns true if one of the differences of this ModelDiff instance is not an OpenEngSBForeignKey. Returns false * otherwise. */ public boolean isValueChanged() { return CollectionUtils.exists(differences.values(), new Predicate() { @Override public boolean evaluate(Object object) { return !((ModelDiffEntry) object).isForeignKey(); } }); } public OpenEngSBModel getBefore() { return before; } public OpenEngSBModel getAfter() { return after; } public Map<Field, ModelDiffEntry> getDifferences() { return differences; } }