/*******************************************************************************
* Copyright (c) 2008 Olivier Moises
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Olivier Moises- initial API and implementation
*******************************************************************************/
package org.eclipse.wazaabi.engine.edp.adapters;
import java.util.List;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.wazaabi.engine.edp.EDP;
import org.eclipse.wazaabi.engine.edp.PathException;
import org.eclipse.wazaabi.engine.edp.coderesolution.ExecutableAdapter;
import org.eclipse.wazaabi.engine.edp.exceptions.OperationAborted;
import org.eclipse.wazaabi.engine.edp.locationpaths.IPointersEvaluator;
import org.eclipse.wazaabi.mm.edp.EventDispatcher;
import org.eclipse.wazaabi.mm.edp.events.Event;
import org.eclipse.wazaabi.mm.edp.handlers.Binding;
import org.eclipse.wazaabi.mm.edp.handlers.EventHandler;
import org.eclipse.wazaabi.mm.edp.handlers.Parameter;
import org.eclipse.wazaabi.mm.edp.handlers.StringParameter;
public class BindingAdapter extends EventHandlerAdapter {
private static final String BINDING_LOCK_NAME = BindingAdapter.class
.getName();
public static final String SOURCE_PARAMETER_NAME = "source"; //$NON-NLS-1$
public static final String TARGET_PARAMETER_NAME = "target"; //$NON-NLS-1$
private String sourceParam = null;
private String targetParam = null;
protected void eventPathModified(Event event, String oldPath, String newPath) {
// TODO Auto-generated method stub
}
protected void eventRemoved(Event event) {
}
protected String getSourceParam() {
return sourceParam;
}
protected String getTargetParam() {
return targetParam;
}
@Override
public void setTarget(Notifier newTarget) {
super.setTarget(newTarget);
sourceParam = null;
targetParam = null;
if (newTarget != null)
for (Parameter parameter : ((Binding) newTarget).getParameters()) {
if (parameter instanceof StringParameter)
if (SOURCE_PARAMETER_NAME.equals(parameter.getName()))
sourceParam = ((StringParameter) parameter).getValue();
else if (TARGET_PARAMETER_NAME
.equals(((StringParameter) parameter).getName()))
targetParam = ((StringParameter) parameter).getValue();
if (targetParam != null && sourceParam != null)
break;
}
}
@Override
public void trigger(Event event) throws OperationAborted {
if (getEventDispatcherAdapter() != null
&& getEventDispatcherAdapter().isLocked(BINDING_LOCK_NAME))
return;
getEventDispatcherAdapter().lock(BINDING_LOCK_NAME);
try {
// TODO : may be do we need a better error management
assert getTarget() instanceof EventHandler;
EventHandler eventHandler = (EventHandler) getTarget();
assert eventHandler.eContainer() instanceof EventDispatcher;
EventDispatcher eventDispatcher = (EventDispatcher) eventHandler
.eContainer();
for (ConditionAdapter condition : getConditionAdapters()) {
boolean canExecute = false;
try {
canExecute = condition.canExecute(eventDispatcher,
eventHandler, event);
} catch (RuntimeException e) {
throw (OperationAborted) e.getCause();
}
if (!canExecute) {
return;
}
}
if (getSourceParam() != null && !"".equals(getSourceParam())
&& getTargetParam() != null && !"".equals(getTargetParam())) {
final IPointersEvaluator pointersEvaluator = getPointersEvaluator();
if (pointersEvaluator == null) {
return;
// TODO : log this
}
List<?> targetPointers = pointersEvaluator.selectPointers(
eventDispatcher, targetParam);
if (exposeData(eventDispatcher, eventHandler, event,
getSourceParam(), getTargetParam(), targetPointers)) {
for (ExecutableAdapter executable : getExecutableAdapters()) {
if (executable instanceof ConverterAdapter) {
try {
executable.trigger(eventDispatcher,
eventHandler, event);
} catch (RuntimeException e) {
throw (OperationAborted) e.getCause();
}
} else if (executable instanceof ValidatorAdapter)
executable.trigger(eventDispatcher, eventHandler,
event);
}
try {
if (eventDispatcher.get(EDP.CONVERTER_RESULT_KEY) != null)
doSet(((EventDispatcher) ((EventHandler) getTarget())
.eContainer())
.get(EDP.CONVERTER_RESULT_KEY),
targetPointers);
else
doSet(eventDispatcher.get(EDP.VALUE_SOURCE_KEY),
targetPointers);
} catch (OperationAborted e) {
System.err
.println(e.getCause() + " " + eventDispatcher);
}
cleanup(eventDispatcher);
} else
; // NOTHING TO DO, WE KEEP THIS AS PLACEHOLDER
}
} finally {
getEventDispatcherAdapter().unlock(BINDING_LOCK_NAME);
}
}
protected void cleanup(EventDispatcher eventDispatcher) {
eventDispatcher.remove(EDP.CONVERTER_RESULT_KEY);
eventDispatcher.remove(EDP.VALUE_SOURCE_KEY);
eventDispatcher.remove(EDP.VALUE_TARGET_KEY);
}
protected void doSet(Object sourceValue, List<?> targetPointers) {
final IPointersEvaluator pointersEvaluator = getPointersEvaluator();
Object targetValue = pointersEvaluator.getValue(targetPointers.get(0));
if (targetValue == null) {
if (sourceValue == null)
return;
} else if (areEquals(targetValue, sourceValue))
return;
try {
pointersEvaluator.setValue(targetPointers.get(0), sourceValue);
} catch (RuntimeException e) {
throw new OperationAborted("Binding aborted", e);
// TODO : move the catch into trigger() method in order to get more
// debug informations to give to users
}
}
public boolean areEquals(Object object1, Object object2) {
if (object1 == null)
return object2 == null;
else {
if (object1 instanceof List<?> && object2 instanceof List<?>)
return areEquals((List<?>) object1, (List<?>) object2);
else
return object1.equals(object2);
}
}
public boolean areEquals(List<?> list1, List<?> list2) {
if (list1 == null)
return list2 == null;
if (list2 == null)
return false;
if (list1.size() != list2.size())
return false;
for (int i = 0; i < list1.size(); i++) {
Object item1 = list1.get(i);
Object item2 = list2.get(i);
if (item1 == null) {
if (item2 != null)
return false;
} else if (!item1.equals(item2))
return false;
}
return true;
}
/**
* Puts in dispatcher's context the data required by the binding process and
* potential users like converter or validators.
*
* @param dispatcher
* @param eventHandler
* @param event
* @param sourceParam
* @param targetParam
* @param targetPointers
* @return
*/
protected boolean exposeData(EventDispatcher dispatcher,
EventHandler eventHandler, Event event, String sourceParam,
String targetParam, List<?> targetPointers) {
final IPointersEvaluator pointersEvaluator = getPointersEvaluator();
if (pointersEvaluator == null) {
return false;
// TODO : log this
}
try {
List<?> newSourcePointers = null;
try {
newSourcePointers = pointersEvaluator.selectPointers(
dispatcher, sourceParam);
} catch (Throwable t) {
t.printStackTrace();
}
// TODO: at the moment, we expect only one returned pointer
if (newSourcePointers.size() == 1 && targetPointers.size() == 1) {
Object newSourceValue = null;
try {
newSourceValue = pointersEvaluator
.getValue(newSourcePointers.get(0));
} catch (Throwable t) {
t.printStackTrace();
}
Object targetValue = pointersEvaluator.getValue(targetPointers
.get(0));
dispatcher.set(EDP.VALUE_SOURCE_KEY, newSourceValue);
dispatcher.set(EDP.VALUE_TARGET_KEY, targetValue);
return true;
}
} catch (PathException e) {
// TODO : log that
System.err.println(e.getMessage());
}
return false;
}
}