/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo 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.
*
* OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.antar.binding;
import java.lang.reflect.Type;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.antar.binding.BindingDefinition.BindingDefinitionType;
import org.openflexo.antar.expr.EvaluationType;
public abstract class StaticBinding<T> extends AbstractBinding {
@SuppressWarnings("hiding")
static final Logger logger = Logger.getLogger(StaticBinding.class.getPackage().getName());
public StaticBinding() {
super();
}
public StaticBinding(BindingDefinition bindingDefinition, Bindable owner) {
super(bindingDefinition, owner);
}
public String getSerializationRepresentation() {
return "$" + getStringRepresentation();
}
// ==========================================================
// ================= Serialization stuff ====================
// ==========================================================
public static StaticBinding makeStaticBinding(String value, Bindable owner) {
if (owner != null) {
StaticBindingFactory factory = owner.getBindingFactory().getStaticBindingFactory();
StaticBinding returned = factory.convertFromString(value, owner);
returned.setOwner(owner);
return returned;
}
return null;
}
public StaticBinding getStaticBindingFromString(String aValue) {
return getConverter().convertFromString(aValue);
}
@Override
public StaticBindingFactory getConverter() {
if (getOwner() != null) {
return getOwner().getBindingFactory().getStaticBindingFactory();
}
return null;
// return staticBindingConverter;
}
public abstract EvaluationType getEvaluationType();
public abstract T getValue();
public abstract void setValue(T aValue);
@Override
public void setsWith(AbstractBinding aValue) {
super.setsWith(aValue);
if (aValue != null) {
if (aValue instanceof StaticBinding) {
Object value = ((StaticBinding) aValue).getValue();
try {
setValue((T) value);
} catch (ClassCastException e) {
logger.warning("setsWith() with mismatched types !!!");
}
} else {
logger.warning("setsWith called with mismatched type " + aValue.getClass().getSimpleName() + ", expected StaticBinding");
}
}
}
@Override
public boolean equals(Object object) {
if (object == null) {
return false;
}
if (object instanceof StaticBinding) {
StaticBinding sb = (StaticBinding) object;
if (getBindingDefinition() == null) {
if (sb.getBindingDefinition() != null) {
return false;
}
} else {
if (!getBindingDefinition().equals(sb.getBindingDefinition())) {
return false;
}
}
return _owner == sb._owner && sb.getValue() != null && getValue().equals(sb.getValue());
} else {
return super.equals(object);
}
}
protected Type accessedType = null;
@Override
public Type getAccessedType() {
if (accessedType == null) {
accessedType = getStaticBindingClass();
}
return accessedType;
}
public abstract Class<T> getStaticBindingClass();
@Override
public boolean isBindingValid() {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Is StaticBinding " + this + " valid ?");
}
if (getAccessedType() == null) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Invalid binding because accessed type is null");
}
return false;
}
if (getBindingDefinition() == null) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Invalid binding because binding definition is null");
}
return false;
} else if (getBindingDefinition().getIsSettable()) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Invalid binding because binding definition is declared as settable");
}
return false;
} else if (getBindingDefinition().getBindingDefinitionType() == BindingDefinitionType.EXECUTE) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Invalid binding because binding definition is declared as executable");
}
return false;
}
if (getAccessedType().equals(Object.class)) {
return true;
}
if (_areTypesMatching()) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Valid binding");
}
return true;
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("Invalid binding because types doesn't match: " + getAccessedType() + " cannot be assigned to "
+ getBindingDefinition().getType());
}
return false;
}
@Override
public String invalidBindingReason() {
// logger.setLevel(Level.FINE);
if (getAccessedType() == null) {
return "Invalid binding " + this + " because accessed type is null";
}
if (getBindingDefinition() == null) {
return "Invalid binding because binding definition is null";
} else if (getBindingDefinition().getIsSettable()) {
return "Invalid binding because binding definition is declared as settable for a constant value";
} else if (getBindingDefinition().getBindingDefinitionType() == BindingDefinitionType.EXECUTE) {
return "Invalid binding because binding definition is declared as executable for a constant value";
}
return "Invalid binding because types doesn't match: " + getAccessedType() + " cannot be assigned to "
+ getBindingDefinition().getType();
}
@Override
public boolean debugIsBindingValid() {
logger.info("Is StaticBinding " + this + " valid ?");
if (getAccessedType() == null) {
logger.info("Invalid binding because accessed type is null");
return false;
}
if (getBindingDefinition() == null) {
logger.info("Invalid binding because binding definition is null");
return false;
} else if (getBindingDefinition().getIsSettable()) {
logger.info("Invalid binding because binding definition is declared as settable");
return false;
} else if (getBindingDefinition().getBindingDefinitionType() == BindingDefinitionType.EXECUTE) {
logger.info("Invalid binding because binding definition is declared as executable");
return false;
}
if (getAccessedType().equals(Object.class)) {
logger.info("Valid binding since accessed type is Object");
return true;
}
if (_areTypesMatching()) {
logger.info("Valid binding");
return true;
}
logger.info("Invalid binding because types doesn't match: " + getAccessedType() + " cannot be assigned to "
+ getBindingDefinition().getType());
return false;
}
protected boolean _areTypesMatching() {
return TypeUtils.isTypeAssignableFrom(getBindingDefinition().getType(), getAccessedType(), true);
}
@Override
public boolean isStaticValue() {
return true;
}
@Override
public abstract StaticBinding<T> clone();
@Override
public T getBindingValue(BindingEvaluationContext context) {
return getValue();
}
@Override
public void setBindingValue(Object value, BindingEvaluationContext context) {
logger.warning("Binding " + getStringRepresentation() + " is not settable");
}
@Override
public boolean isSettable() {
return false;
}
/**
* Build and return a list of objects (the current object path computed from supplied context)
*
* @param context
* @return
*/
@Override
public List<Object> getConcernedObjects(BindingEvaluationContext context) {
return null;
}
/**
* Build and return a list of target objects (the current object path computed from supplied context)
*
* @param context
* @return
*/
@Override
public List<TargetObject> getTargetObjects(BindingEvaluationContext context) {
return null;
}
}