/**
* Get more info at : www.jrebirth.org .
* Copyright JRebirth.org © 2011-2013
* Contact : sebastien.bordes@jrebirth.org
*
* Licensed 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.jrebirth.af.core.component.behavior;
import org.jrebirth.af.api.annotation.SkipAnnotation;
import org.jrebirth.af.api.component.basic.Component;
import org.jrebirth.af.api.component.behavior.Behavior;
import org.jrebirth.af.api.component.behavior.BehaviorData;
import org.jrebirth.af.api.component.behavior.BehavioredComponent;
import org.jrebirth.af.api.key.UniqueKey;
import org.jrebirth.af.api.log.JRLogger;
import org.jrebirth.af.core.component.basic.AbstractComponent;
import org.jrebirth.af.core.key.Key;
import org.jrebirth.af.core.link.LinkMessages;
import org.jrebirth.af.core.log.JRLoggerFactory;
import org.jrebirth.af.core.util.MultiMap;
/**
*
* The class <strong>AbstractBehavioredComponent</strong> is the base class to add Behavior support for {@link Component}.
*
* This is the base class for all EnhancedComponent that want to use Behavior features.<br />
*
* @author Sébastien Bordes
*
* @param <C> the class type of the subclass
*/
@SkipAnnotation(false)
public abstract class AbstractBehavioredComponent<C extends BehavioredComponent<C>> extends AbstractComponent<C> implements BehavioredComponent<C>, LinkMessages {
/** The class logger. */
private static final JRLogger LOGGER = JRLoggerFactory.getLogger(AbstractBehavioredComponent.class);
/** A map that store one or many behavior implementations by their type. */
private MultiMap<Class<? extends Behavior<?>>, Behavior<?>> behaviors;
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
protected void manageOptionalData() {
// Parse optional data provided to search Behavior Class or BehaviorData
for (final Object data : getKey().getOptionalData()) {
if (data instanceof BehaviorData) {
addBehavior((BehaviorData) data);
} else if (data instanceof Class && ((Class<?>) data).isAssignableFrom(Behavior.class)) {
addBehavior((Class<Behavior<BehaviorData>>) data);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasBehavior(final Class<Behavior<?>> behaviorClass) {
return this.behaviors != null && this.behaviors.containsKey(behaviorClass);
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
public <BD extends BehaviorData, B extends Behavior<BD>> C addBehavior(final Class<B> behaviorClass) {
final UniqueKey<B> key = Key.create(behaviorClass, new Object[] { this }, getKey());
final B behavior = getLocalFacade().getGlobalFacade().getBehaviorFacade().retrieve(key);
addBehavior(behavior);
return (C) this;
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
public <BD extends BehaviorData> C addBehavior(final BD data) {
for (final Class<? extends Behavior<?>> behaviorClass : data.getBehaviors()) {
final Object[] optionalData = new Object[] { data, this };
final UniqueKey<? extends Behavior<?>> key = Key.create(behaviorClass, optionalData, getKey());
addBehavior(getLocalFacade().getGlobalFacade().getBehaviorFacade().retrieve(key));
}
return (C) this;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
private <B extends Behavior<?>> void addBehavior(final B behavior) {
if (this.behaviors == null) {
this.behaviors = new MultiMap<Class<? extends Behavior<?>>, Behavior<?>>();
}
LOGGER.log(ADD_BEHAVIOR, behavior.getClass().getCanonicalName(), this.getClass().getCanonicalName());
this.behaviors.add((Class<Behavior<?>>) behavior.getClass(), behavior);
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
public <BD extends BehaviorData, B extends Behavior<BD>> B getBehavior(final Class<B> behaviorClass) {
return this.behaviors == null ? null : (B) this.behaviors.get(behaviorClass);
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
public <BD extends BehaviorData, B extends Behavior<BD>> BD getBehaviorData(final Class<B> behaviorClass) {
return this.behaviors == null ? null : (BD) this.behaviors.get(behaviorClass).get(0).getData();
}
}