/* license-start * * Copyright (C) 2008 - 2013 Crispico, <http://www.crispico.com/>. * * 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 version 3. * * 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, at <http://www.gnu.org/licenses/>. * * Contributors: * Crispico - Initial API and implementation * * license-end */ package com.crispico.flower.mp.codesync.base.action; import com.crispico.flower.mp.codesync.base.CodeSyncAlgorithm; import com.crispico.flower.mp.codesync.base.IModelAdapter; import com.crispico.flower.mp.codesync.base.Match; /** * */ public abstract class MatchActionAddAbstract extends DiffAction { protected boolean processDiffs; protected abstract Object getThis(Match match); protected abstract Object getOpposite(Match match); protected abstract IModelAdapter getThisModelAdapter(Match match); protected abstract IModelAdapter getOppositeModelAdapter(Match match); protected abstract void setOpposite(Match match, Object elment); protected abstract void processDiffs(Match match); protected abstract void setChildrenModified(Match match); public MatchActionAddAbstract(boolean processDiffs) { super(); this.processDiffs = processDiffs; } @Override public ActionResult execute(Match match, int diffIndex) { processMatch(match.getParentMatch(), match, true); Object child = getThis(match); return new ActionResult(false, true, true, getThisModelAdapter(match).getMatchKey(child), true); } protected void processMatch(Match parentMatch, Match match, boolean isFirst) { Object this_ = getThis(match); if (this_ == null) // this happens when parentMatch was a 2-match-ancestor-left/right and match is 1-match-ancestor (i.e. del left & right) return; IModelAdapter oppositeParentMa = getOppositeModelAdapter(parentMatch); Object opposite = oppositeParentMa.createChildOnContainmentFeature(getOpposite(parentMatch), match.getFeature(), this_); setOpposite(match, opposite); // from 1-match-left or 1-match-right, the match became 2-match-left-right // process value features IModelAdapter thisMa = getThisModelAdapter(match); IModelAdapter oppositeMa = getOppositeModelAdapter(match); for (Object childFeature : match.getEditableResource().getModelAdapterFactorySet().getFeatureProvider(this_).getFeatures(this_)) { switch (match.getEditableResource().getModelAdapterFactorySet().getFeatureProvider(this_).getFeatureType(childFeature)) { case IModelAdapter.FEATURE_TYPE_VALUE: Object value = thisMa.getValueFeatureValue(this_, childFeature, null); Object valueOpposite = oppositeMa.getValueFeatureValue(opposite, childFeature, null); if (!CodeSyncAlgorithm.safeEquals(value, valueOpposite)) oppositeMa.setValueFeatureValue(opposite, childFeature, value); break; } } if (processDiffs) processDiffs(match); match.setChildrenConflict(false); if (!match.getSubMatches().isEmpty()) { setChildrenModified(match); // process child match for (Match childMatch : match.getSubMatches()) processMatch(match, childMatch, false); } } }