
org.objectweb.fractal.julia.control.binding.OptimizedCompositeBindingMixin Maven / Gradle / Ivy
/***
* Julia: France Telecom's implementation of the Fractal API
* Copyright (C) 2001-2010 France Telecom R&D
* Copyright (C) 2007-2010 INRIA
*
* This library 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 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: [email protected]
*
* Author: Eric Bruneton
*
* Contributor: Philippe Merle
*
* $Id: OptimizedCompositeBindingMixin.java 10563 2010-01-20 19:17:47Z seintur $
*/
package org.objectweb.fractal.julia.control.binding;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.Interface;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.BindingController;
import org.objectweb.fractal.api.control.ContentController;
import org.objectweb.fractal.api.control.IllegalBindingException;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.api.type.InterfaceType;
import org.objectweb.fractal.julia.ComponentInterface;
import org.objectweb.fractal.julia.Interceptor;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.ArrayList;
/**
* Provides optimized {@link ComponentInterface} management to a {@link
* BindingController}. This mixin uses shortcut links between component
* interfaces where possible, i.e. when some interfaces do not have associated
* interceptors.
*
*
* Requirements
*
* - the component to which this controller object belongs must provide the
* {@link Component} and {@link ContentController} interfaces.
* - TODO.
*
*/
public abstract class OptimizedCompositeBindingMixin
implements BindingController
{
// -------------------------------------------------------------------------
// Private constructor
// -------------------------------------------------------------------------
private OptimizedCompositeBindingMixin () {
}
// -------------------------------------------------------------------------
// Fields and methods added and overriden by the mixin class
// -------------------------------------------------------------------------
/**
* Sets the shortcuts for the given binding and then calls the overriden
* method.
*
* @param clientItfType the type of the clientItfName interface.
* @param clientItfName the name of a client interface of the component to
* which this interface belongs.
* @param serverItf a server interface.
* @throws NoSuchInterfaceException if there is no such client interface.
* @throws IllegalBindingException if the binding cannot be created.
* @throws IllegalLifeCycleException if this component has a {@link
* org.objectweb.fractal.api.control.LifeCycleController} interface, but
* it is not in an appropriate state to perform this operation.
*/
public void bindFc (
final InterfaceType clientItfType,
final String clientItfName,
final Object serverItf)
throws
NoSuchInterfaceException,
IllegalBindingException,
IllegalLifeCycleException
{
_super_bindFc(clientItfType, clientItfName, serverItf);
setFcShortcuts(clientItfType, clientItfName, serverItf);
}
/**
* Updates the shortcuts for the given binding and then calls the overriden
* method.
*
* @param clientItfType the type of the clientItfName interface.
* @param clientItfName the name of a client interface of the component to
* which this interface belongs.
* @throws NoSuchInterfaceException if there is no such client interface.
* @throws IllegalBindingException if the binding cannot be removed.
* @throws IllegalLifeCycleException if this component has a {@link
* org.objectweb.fractal.api.control.LifeCycleController} interface, but
* it is not in an appropriate state to perform this operation.
*/
public void unbindFc (
final InterfaceType clientItfType,
final String clientItfName)
throws
NoSuchInterfaceException,
IllegalBindingException,
IllegalLifeCycleException
{
_super_unbindFc(clientItfType, clientItfName);
setFcShortcuts(clientItfType, clientItfName, null);
}
// -------------------------------------------------------------------------
// Utility methods: algorithm to compute of shortcut links
// -------------------------------------------------------------------------
/**
* Creates the given binding and updates the shortcuts links accordingly.
*
* @param clientItfType the type of the 'clientItfName' interface.
* @param clientItfName a client interface name.
* @param serverItf the server interface to which the client interface must
* be bound, or null if it must be unbound.
* @throws NoSuchInterfaceException if there is no client interface whose name
* is equal to 'clientItfName'.
* @throws IllegalBindingException if a problem occurs.
*/
public void setFcShortcuts (
final InterfaceType clientItfType,
final String clientItfName,
final Object serverItf)
throws
NoSuchInterfaceException,
IllegalBindingException
{
Interface clientItf;
if (clientItfType.isFcClientItf()) {
clientItf =
(Interface)_this_weaveableC.getFcInterface(clientItfName);
} else {
clientItf =
(Interface)_this_weaveableCC.getFcInternalInterface(clientItfName);
}
Set visited = new HashSet();
List shortcutItfs = new ArrayList();
List shortcutImpls = new ArrayList();
// 'forward' step
Object itf = serverItf;
while (true) {
ComponentInterface citf;
if (itf instanceof ComponentInterface) {
citf = (ComponentInterface)itf;
} else {
break;
}
if (citf.getFcItfImpl() instanceof Interceptor) {
break;
}
try {
Component owner = citf.getFcItfOwner();
owner.getFcInterface("content-controller");
BindingController bc =
(BindingController)owner.getFcInterface("binding-controller");
itf = bc.lookupFc(citf.getFcItfName());
} catch (NoSuchInterfaceException e) {
break;
}
}
Object impl;
if (itf == null) {
impl = null;
} else {
if (itf instanceof ComponentInterface) {
impl = ((ComponentInterface)itf).getFcItfImpl();
} else {
// cannot create complete shortcut: uses itf as 'impl'
impl = itf;
}
}
// 'backward' step : creates the shortcuts
try {
setFcClientShortcuts(clientItf, impl, visited, shortcutItfs, shortcutImpls);
} catch (Exception e) {
Interface sItf;
sItf = serverItf instanceof Interface ? (Interface)serverItf : null;
throw new ChainedIllegalBindingException(
e,
clientItf.getFcItfOwner(),
sItf == null ? null : sItf.getFcItfOwner(),
clientItf.getFcItfName(),
sItf == null ? null : sItf.getFcItfName(),
"Cannot create shortcut links");
}
// sets the shortcuts
for (int i = 0; i < shortcutItfs.size(); ++i) {
Interface shortcutItf = (Interface)shortcutItfs.get(i);
Object shortcutImpl = shortcutImpls.get(i);
Component c = shortcutItf.getFcItfOwner();
ContentController cc;
try {
cc = (ContentController)c.getFcInterface("content-controller");
} catch (NoSuchInterfaceException e) {
cc = null;
}
if (cc != null) {
ComponentInterface cShortcutItf = (ComponentInterface)shortcutItf;
if (cShortcutItf.hasFcInterceptor()) {
Object newImpl = cShortcutItf.getFcItfImpl();
((Interceptor)newImpl).setFcItfDelegate(shortcutImpl);
} else {
cShortcutItf.setFcItfImpl(shortcutImpl);
}
} else {
BindingController bc;
try {
bc = (BindingController)c.getFcInterface("binding-controller");
} catch (NoSuchInterfaceException e) {
continue;
}
try {
String itfName = shortcutItf.getFcItfName();
Object o = bc.lookupFc(itfName);
// following code not needed if refresh done in lookup
if (o != null) {
bc.unbindFc(itfName);
bc.bindFc(itfName, o);
}
} catch (Exception e) {
Interface sItf;
sItf = serverItf instanceof Interface ? (Interface)serverItf : null;
throw new ChainedIllegalBindingException(
e,
clientItf.getFcItfOwner(),
sItf == null ? null : sItf.getFcItfOwner(),
clientItf.getFcItfName(),
sItf == null ? null : sItf.getFcItfName(),
"Cannot create shortcut links");
}
}
}
}
/**
* Finds the shortcut links to be updated by following the bindings backwards
* from the given client interface.
*
* @param clientItf the client interface from which the bindings must be
* followed backward.
* @param impl the object to be used to update the shortcut links with {@link
* ComponentInterface#getFcItfImpl getFcItfImpl}.
* @param visited the already visited interfaces.
* @param shortcutItfs the interfaces whose shortcut links must be updated.
* @param shortcutImpls the values to be used to update the shortcut links.
* @throws Exception if a problem occurs.
*/
public void setFcClientShortcuts (
final Interface clientItf,
final Object impl,
final Set visited,
final List shortcutItfs,
final List shortcutImpls) throws Exception
{
Component clientComp = clientItf.getFcItfOwner();
ContentController cc;
try {
cc = (ContentController)clientComp.getFcInterface("content-controller");
} catch (NoSuchInterfaceException e) {
cc = null;
}
if (cc != null) {
ComponentInterface itf;
try {
String name = clientItf.getFcItfName();
if (clientItf.isFcInternalItf()) {
// clientItf is an internal client interface: continue to follow the
// bindings backwards from the corresponding external server interface
itf = (ComponentInterface)clientComp.getFcInterface(name);
} else {
// clientItf is an external client interface: continue to follow the
// bindings backwards from the corresponding internal server interface
itf = (ComponentInterface)cc.getFcInternalInterface(name);
}
} catch (NoSuchInterfaceException e) {
throw new Exception("Cannot create shortcut links: No such interface exception "+e.getMessage());
} catch (ClassCastException e) {
// Thrown when clientItf was not created by Julia but by another
// Fractal implementation that does not support ComponentInterface.
// Then no shortcut link can be created.
itf = null;
}
if (itf != null && !visited.contains(itf)) {
visited.add(itf);
shortcutItfs.add(itf);
shortcutImpls.add(impl);
if (itf.hasFcInterceptor()) {
Object newImpl = itf.getFcItfImpl();
setFcServerShortcuts(itf, newImpl, visited, shortcutItfs, shortcutImpls);
} else {
setFcServerShortcuts(itf, impl, visited, shortcutItfs, shortcutImpls);
}
}
} else if (!visited.contains(clientItf)) {
visited.add(clientItf);
shortcutItfs.add(clientItf);
shortcutImpls.add(impl);
}
}
/**
* Finds the shortcut links to be updated by followng the bindings backwards
* from the given server interface.
*
* @param serverItf the server interface from which the bindings must be
* followed backward.
* @param impl the object to be used to update the shortcut links with {@link
* ComponentInterface#getFcItfImpl getFcItfImpl}.
* @param visited the already visited interfaces.
* @param shortcutItfs the interfaces whose shortcut links must be updated.
* @param shortcutImpls the values to be used to update the shortcut links.
* @throws Exception if a problem occurs.
*/
public void setFcServerShortcuts (
final Interface serverItf,
final Object impl,
final Set visited,
final List shortcutItfs,
final List shortcutImpls) throws Exception
{
Object[] comps = Util.getFcPotentialClientsOf(serverItf).toArray();
for (int i = 0; i < comps.length; ++i) {
Component comp = (Component)comps[i];
List clientItfs = Util.getFcClientItfsBoundTo(comp, serverItf);
for (int j = 0; j < clientItfs.size(); ++j) {
setFcClientShortcuts(
(Interface)clientItfs.get(j),
impl,
visited,
shortcutItfs,
shortcutImpls);
}
}
}
// -------------------------------------------------------------------------
// Fields and methods required by the mixin class in the base class
// -------------------------------------------------------------------------
/**
* The weaveableC field required by this mixin. This field is
* supposed to reference the {@link Component} interface of the component to
* which this controller object belongs.
*/
public Component _this_weaveableC;
/**
* The weaveableCC field required by this mixin. This field is
* supposed to reference the {@link ContentController} interface of the
* component to which this controller object belongs.
*/
public ContentController _this_weaveableCC;
/**
* The {@link TypeBindingMixin#bindFc(InterfaceType,String,Object) bindFc}
* method overriden by this mixin.
*
* @param clientItfType the type of the clientItfName interface.
* @param clientItfName the name of a client interface of the component to
* which this interface belongs.
* @param serverItf a server interface.
* @throws NoSuchInterfaceException if there is no such client interface.
* @throws IllegalBindingException if the binding cannot be created.
* @throws IllegalLifeCycleException if this component has a {@link
* org.objectweb.fractal.api.control.LifeCycleController} interface, but
* it is not in an appropriate state to perform this operation.
*/
public abstract void _super_bindFc (
InterfaceType clientItfType,
String clientItfName,
Object serverItf)
throws
NoSuchInterfaceException,
IllegalBindingException,
IllegalLifeCycleException;
/**
* The {@link TypeBindingMixin#unbindFc(InterfaceType,String) unbindFc}
* method overriden by this mixin.
*
* @param clientItfType the type of the clientItfName interface.
* @param clientItfName the name of a client interface of the component to
* which this interface belongs.
* @throws NoSuchInterfaceException if there is no such client interface.
* @throws IllegalBindingException if the binding cannot be removed.
* @throws IllegalLifeCycleException if this component has a {@link
* org.objectweb.fractal.api.control.LifeCycleController} interface, but
* it is not in an appropriate state to perform this operation.
*/
public abstract void _super_unbindFc (
InterfaceType clientItfType,
String clientItfName)
throws
NoSuchInterfaceException,
IllegalBindingException,
IllegalLifeCycleException;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy