org.nuiton.jaxx.runtime.binding.DefaultJAXXBinding Maven / Gradle / Ivy
/*
* #%L
* JAXX :: Runtime
* %%
* Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.jaxx.runtime.binding;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.nuiton.jaxx.runtime.JAXXBinding;
import org.nuiton.jaxx.runtime.JAXXObject;
import org.nuiton.jaxx.runtime.JAXXUtil;
import java.beans.PropertyChangeEvent;
/**
* A PropertyChangeListener
which processes a data binding when it receives a
* PropertyChangeEvent
.
*/
public abstract class DefaultJAXXBinding implements JAXXBinding {
/** Logger */
private static final Logger log = LogManager.getLogger(DefaultJAXXBinding.class);
/** Counter of all bindings hits */
private static long NB;
/** Counter of current binding hits */
private long nb;
/** Id of the binding */
private final String id;
/** The source of the binding. */
protected final JAXXObject source;
/**
* flag to know {@code true} : if the binding was init from a generated
* jaxx object, {@code false} otherwise.
*/
protected final boolean defaultBinding;
/**
* Internal state to reapply the binding after each fires :this is sometimes
* necessary when binding is complex. For example with this binding
*
* ui.getModel().getProperty()
*
* We need to listen two things : first listen on {@code ui} the
* modification of {@code model}, then on {@code model} the {@code property}.
*
* @since 2.4.2
*/
protected final boolean reloadAfterFire;
/**
* Creates a new Data binding which will run the given data binding
* when it receives a PropertyChangeEvent
.
*
* @param source the {@link JAXXObject} source of the binding
* @param id the name of the data binding to run
* @param defaultBinding flag to knwon if binding is coming from a generated jaxx object ({@code true}).
*/
public DefaultJAXXBinding(JAXXObject source, String id,
boolean defaultBinding) {
this(source, id, defaultBinding, false);
}
/**
* Creates a new Data binding which will run the given data binding
* when it receives a PropertyChangeEvent
.
*
* @param source the {@link JAXXObject} source of the binding
* @param id the name of the data binding to run
* @param defaultBinding flag to know if binding is coming from a generated jaxx object ({@code true}).
* @param reloadAfterFire flag to know if the binding need to be reload after each fires
*/
public DefaultJAXXBinding(JAXXObject source, String id,
boolean defaultBinding,
boolean reloadAfterFire) {
this.source = source;
this.id = id;
this.defaultBinding = defaultBinding;
this.reloadAfterFire = reloadAfterFire;
}
@Override
public String getId() {
return id;
}
@Override
public JAXXObject getSource() {
return source;
}
@Override
public boolean isDefaultBinding() {
return defaultBinding;
}
@Override
public String toString() {
return super.toString() + ":" + id;
}
private static final String LOG_START_PATTERN = ">> (hits:%1$5d, total:%2$5d) on %3$s";
private static final String LOG_END_PATTERN = "<< %4$3d (hits:%1$5d, total:%2$5d) on %3$s";
/**
* Processes the data binding in response to a PropertyChangeEvent
.
*
* When the binding is wake up, delegate the process to the source object which
* can manage re-entrant code (can not process a re-entrant event).
*
* @param e the event which triggered the binding
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
long count = NB;
if (log.isDebugEnabled()) {
log.debug(String.format(LOG_START_PATTERN, ++nb, ++NB, this));
}
//TODO-TC-20091202 perharps could we have a nicer way to process it,
// let the source deal with it to avoid re-entrant code
source.processDataBinding(id);
//TODO-20091201 Must test on a lot of cases before next release 2.0.0-beta-2
//TC-20091201 : I really don't see the point
// I comment the code, and still working fine ? Any trick
// for now, handle dependency changes by always removing & reapplying
// the binding. We should be more efficient and only do this when it's
// actually necessary
if (reloadAfterFire) {
JAXXUtil.reloadBinding(this);
}
// source.removeDataBinding(id);
// source.applyDataBinding(id);
if (log.isDebugEnabled()) {
log.debug(String.format(LOG_END_PATTERN, ++nb, ++NB, this, NB - count));
}
}
}