Commit 80b3d23a authored by Lionel Seinturier's avatar Lionel Seinturier
Browse files

Support property promotion with different names in the promoter and promotee.

Refactor the implementation of the property controller.
parent f013bce9
Tinfi 1.3.2
-----------
* support property promotion with different names in the promoter and promotee
* support @EndsConversation methods in non @Conversational annotated interfaces
* fix proxy generation for generic methods to enable compilation with javac
......
......@@ -95,7 +95,6 @@
<adl>org.ow2.frascati.tinfi.PolicySetsHandler</adl>
<adl>org.ow2.frascati.tinfi.PolicySets</adl>
<adl>org.ow2.frascati.tinfi.Property</adl>
<adl>org.ow2.frascati.tinfi.PropertyComposite</adl>
<adl>org.ow2.frascati.tinfi.PropertyReInject</adl>
<adl>org.ow2.frascati.tinfi.ReconfigurableComponentContext</adl>
<adl>org.ow2.frascati.tinfi.ReferenceMultiple</adl>
......@@ -194,7 +193,6 @@
<!-- adl>org.ow2.frascati.tinfi.PolicySetsHandler</adl>
<adl>org.ow2.frascati.tinfi.PolicySets</adl -->
<adl>org.ow2.frascati.tinfi.Property</adl>
<adl>org.ow2.frascati.tinfi.PropertyComposite</adl>
<adl>org.ow2.frascati.tinfi.PropertyReInject</adl>
<adl>org.ow2.frascati.tinfi.ReconfigurableComponentContext</adl>
<adl>org.ow2.frascati.tinfi.ReferenceMultiple</adl>
......
......@@ -4,7 +4,15 @@
<definition name="org.ow2.frascati.tinfi.Property" >
<interface name="r" role="server" signature="org.ow2.frascati.tinfi.PropertyItf" />
<content class="org.ow2.frascati.tinfi.PropertyImpl"/>
<controller desc="scaPrimitive" />
<component name="inner" >
<interface name="r" role="server" signature="org.ow2.frascati.tinfi.PropertyItf" />
<content class="org.ow2.frascati.tinfi.PropertyImpl"/>
<controller desc="scaPrimitive" />
</component>
<binding client="this.r" server="inner.r" />
<controller desc="scaComposite" />
</definition>
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE definition PUBLIC "-//objectweb.org//DTD Fractal ADL 2.0//EN" "classpath://org/objectweb/fractal/adl/xml/standard.dtd">
<definition name="org.ow2.frascati.tinfi.PropertyComposite" >
<interface name="r" role="server" signature="org.ow2.frascati.tinfi.PropertyItf" />
<component name="inner" >
<interface name="r" role="server" signature="org.ow2.frascati.tinfi.PropertyItf" />
<content class="org.ow2.frascati.tinfi.PropertyImpl"/>
<controller desc="scaPrimitive" />
</component>
<binding client="this.r" server="inner.r" />
<controller desc="scaComposite" />
</definition>
......@@ -23,31 +23,38 @@
package org.ow2.frascati.tinfi;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.control.ContentController;
import org.objectweb.fractal.util.Fractal;
import org.ow2.frascati.tinfi.control.property.IllegalPromoterException;
import org.ow2.frascati.tinfi.control.property.SCAPropertyController;
/**
* Class for testing the use of properties on scaComposite components.
* Class for testing properties on scaComposite components.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
* @since 1.1.2
*/
public class PropertyCompositeTestCase extends PropertyTestCase {
private SCAPropertyController innerscapc;
@Before
@Override
public void setUp() throws Exception {
String adl = getClass().getPackage().getName()+".PropertyComposite";
String adl = getClass().getPackage().getName()+".Property";
String service = "r";
Component comp = TinfiDomain.getComponent(adl);
ContentController cc = Fractal.getContentController(comp);
Component[] subs = cc.getFcSubComponents();
Component inner = subs[0];
innerscapc = (SCAPropertyController)
inner.getFcInterface(SCAPropertyController.NAME);
itf = TinfiDomain.getService(comp,PropertyItf.class,service);
scapc = (SCAPropertyController)
......@@ -57,12 +64,25 @@ public class PropertyCompositeTestCase extends PropertyTestCase {
* Promote the properties from the primitive subcomponent to the
* composite.
*/
SCAPropertyController innerscapc = (SCAPropertyController)
inner.getFcInterface(SCAPropertyController.NAME);
scapc.setPromoter("mandatoryProp",innerscapc);
scapc.setPromoter("propWithDefault",innerscapc);
scapc.setPromoter("fieldPropWithDefault",innerscapc);
scapc.setPromoter("unannotatedFieldProp",innerscapc);
scapc.setPromoter("unannotatedProp",innerscapc);
}
@Test
public void testSetPromoterWithDifferentName()
throws IllegalPromoterException {
String expected = "foo";
scapc.setPromoter("top",innerscapc,"mandatoryProp");
scapc.setValue("top",expected);
Object actual = scapc.getValue("top");
Assert.assertEquals(expected,actual);
actual = innerscapc.getValue("mandatoryProp");
Assert.assertEquals(expected,actual);
}
}
......@@ -49,7 +49,7 @@ import org.ow2.frascati.tinfi.control.property.SCAPropertyController;
import org.ow2.frascati.tinfi.reflect.InjectionPoint;
/**
* Class for testing the use of properties.
* Class for testing component properties.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
*/
......@@ -113,13 +113,18 @@ public class PropertyTestCase {
}
@Before
public void setUp() throws Exception {
public void setUp() throws Exception {
String adl = getClass().getPackage().getName()+".Property";
String service = "r";
Component comp = TinfiDomain.getComponent(adl);
itf = TinfiDomain.getService(comp,PropertyItf.class,service);
ContentController cc = Fractal.getContentController(comp);
Component[] subs = cc.getFcSubComponents();
Component inner = subs[0];
itf = TinfiDomain.getService(inner,PropertyItf.class,service);
scapc = (SCAPropertyController)
comp.getFcInterface(SCAPropertyController.NAME);
inner.getFcInterface(SCAPropertyController.NAME);
}
public static class PropertyAnnotationImpl implements Property {
......
......@@ -30,168 +30,42 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.objectweb.fractal.api.control.NameController;
import org.objectweb.fractal.api.factory.InstantiationException;
import org.objectweb.fractal.julia.Controller;
import org.objectweb.fractal.julia.InitializationContext;
import org.ow2.frascati.tinfi.control.content.SCAContentController;
/**
* Mixin layer for implementing the {@link SCAPropertyController} interface for
* Implementing the {@link SCAContentController} control interface for
* scaComposite components.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
* @since 1.1.2
*/
public abstract class SCACompositePropertyControllerMixin
implements SCAPropertyController {
implements Controller, SCAPropertyController {
// -------------------------------------------------------------------------
// Private constructor
// Implementation of the Controller interface
// -------------------------------------------------------------------------
private SCACompositePropertyControllerMixin () {}
public void initFcController( InitializationContext ic )
throws InstantiationException {
_super_initFcController(ic);
}
// -------------------------------------------------------------------------
// Implementation of the SCAPropertyController interface
// -------------------------------------------------------------------------
private Map<String,Object> values = new HashMap<String,Object>();
private Map<String,Class<?>> types = new HashMap<String,Class<?>>();
private Map<String,SCAPropertyController> promoters =
new HashMap<String,SCAPropertyController>();
/**
* Set the type of the specified property. If the property type has already
* been set, the old value is lost, and the new one is recorded.
*
* The rationale for recording property types lies in the fact that complex
* properties may have a type which differs from the one of the field where
* their values will be injected. Typically, complex property values will be
* injected in fields of type Object.
*
* @param name the property name
* @param type the property type
*/
public void setType( String name, Class<?> type ) {
SCAPropertyController promoter = promoters.get(name);
if( promoter == null ) {
types.put(name,type);
}
else {
promoter.setType(name,type);
}
}
/**
* Set the value of the specified property. If the property value has
* already been set, the old value is lost, and the new one is recorded.
*
* @param name the property name
* @param value the property value
* @throws IllegalArgumentException
* if a type has been defined for the specified property with {@link
* #setValue(String, Object)} and if the specified value is not an
* instance of this type
*/
public void setValue( String name, Object value )
throws IllegalArgumentException {
SCAPropertyController promoter = promoters.get(name);
if( promoter == null ) {
// Check whether the value is of the correct type
if( types.containsKey(name) ) {
Class<?> type = types.get(name);
boolean isInstance = type.isInstance(value);
if( ! isInstance ) {
String msg =
"The type of the specified value "+value+
" is not assignable to the type "+type.getName()+
" previously defined with setType().";
throw new IllegalArgumentException(msg);
}
}
// Record the new value
values.put(name,value);
}
else {
promoter.setValue(name,value);
}
}
/**
* Return the type of the specified property. Return <code>null</code> if
* the property type has not been set.
*
* @param name the property name
* @return the property value
*/
public Class<?> getType( String name ) {
SCAPropertyController promoter = promoters.get(name);
Class<?> type =
promoter == null ?
types.get(name) :
promoter.getType(name);
return type;
}
/**
* Return the value of the specified property. Return <code>null</code> if
* the property value has not been set.
*
* @param name the property name
* @return the property value
*/
public Object getValue( String name ) {
SCAPropertyController promoter = promoters.get(name);
Object value =
promoter == null ?
values.get(name) :
promoter.getValue(name);
return value;
}
/**
* Return <code>true</code> if the specified property has been set.
*
* @param name the property name
* @return <code>true</code> if the property has been set,
* <code>false</code> otherwise
*/
public boolean containsPropertyName( String name ) {
SCAPropertyController promoter = promoters.get(name);
boolean b =
promoter == null ?
values.containsKey(name) :
promoter.containsPropertyName(name);
return b;
}
/**
* Return the names of the properties whose values have been set by invoking
* {@link #setValue(String, Object)}.
*/
public String[] getPropertyNames() {
Set<String> keys = values.keySet();
String[] names = keys.toArray( new String[keys.size()] );
return names;
}
/**
* Return <code>true</code> if the specified property can be injected in the
* content class.
*
* @param name the property name
* @return <code>true</code> if the property can be injected,
* <code>false</code> otherwise
* @since 1.1.2
*/
public boolean containsDeclaredPropertyName( String name ) {
/*
* For scaComposite components, we can only rely on properties declared
* by scaPrimitives which would promote their properties.
*/
Collection<SCAPropertyController> scapcs = promoters.values();
Collection<SCAPropertyController> scapcs = _this_promoters.values();
for (SCAPropertyController scapc : scapcs) {
if( scapc.containsDeclaredPropertyName(name) ) {
return true;
......@@ -201,10 +75,6 @@ implements SCAPropertyController {
return false;
}
/**
* Return the names of the properties which can be injected in the content
* class.
*/
public String[] getDeclaredPropertyNames() {
/*
......@@ -212,7 +82,7 @@ implements SCAPropertyController {
* by scaPrimitives which would promote their properties.
*/
Set<String> propnames = new HashSet<String>();
Collection<SCAPropertyController> scapcs = promoters.values();
Collection<SCAPropertyController> scapcs = _this_promoters.values();
for (SCAPropertyController scapc : scapcs) {
String[] s = scapc.getDeclaredPropertyNames();
propnames.addAll( Arrays.asList(s) );
......@@ -222,21 +92,13 @@ implements SCAPropertyController {
return names;
}
/**
* Return the type of the specified property, provided that this property
* can be injected in the content class.
*
* @param name the property name
* @return the property type
* @since 1.1.2
*/
public Class<?> getDeclaredPropertyType( String name ) {
/*
* For scaComposite components, we can only rely on properties declared
* by scaPrimitives which would promote their properties.
*/
Collection<SCAPropertyController> scapcs = promoters.values();
Collection<SCAPropertyController> scapcs = _this_promoters.values();
for (SCAPropertyController scapc : scapcs) {
if( scapc.containsDeclaredPropertyName(name) ) {
Class<?> type = scapc.getDeclaredPropertyType(name);
......@@ -245,52 +107,16 @@ implements SCAPropertyController {
}
return null;
}
/**
* Set the reference of the property controller which promotes the specified
* property to the current property controller.
*
* @param name the promoter property name
* @param promoter the promoter component or
* <code>null</code> to unregister the promoter
* @throws IllegalPromoterException
* thrown when attempting to set a cycle between property promoters
*/
public void setPromoter( String name, SCAPropertyController promoter )
throws IllegalPromoterException {
promoters.put(name,promoter);
if( promoter != null ) {
SCAPropertyController peer = promoter.getPromoter(name);
if( peer == this ) {
String compname = _this_weaveableOptNC.getFcName();
throw new IllegalPromoterException(compname);
}
}
}
/**
* Return the reference of the property controller which promotes the
* specified property. Return <code>null</code> if the property is managed
* locally by the current property controller.
*
* @param name the promoter property name
* @return the promoter component or <code>null</code>
*/
public SCAPropertyController getPromoter( String name ) {
return promoters.get(name);
}
}
// -------------------------------------------------------------------------
// Fields and methods required by the mixin class in the base class
// -------------------------------------------------------------------------
/**
* The {@link NameController} interface of the component to which this
* controller object belongs.
*/
public NameController _this_weaveableOptNC;
protected abstract void _super_initFcController( InitializationContext ic )
throws InstantiationException;
private Map<String,SCAPropertyController> _this_promoters =
new HashMap<String,SCAPropertyController>();
}
/***
* OW2 FraSCAti Tinfi
* Copyright (C) 2007-2010 INRIA, USTL
*
* 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: frascati@ow2.org
*
* Author: Lionel Seinturier
*/
package org.ow2.frascati.tinfi.control.property;
import org.objectweb.fractal.api.factory.InstantiationException;
import org.objectweb.fractal.julia.Controller;
import org.objectweb.fractal.julia.InitializationContext;
import org.ow2.frascati.tinfi.control.content.SCAContentController;
/**
* Implementing the {@link SCAContentController} control interface for
* scaPrimitive components.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
* @since 1.3.2
*/
public abstract class SCAPrimitivePropertyControllerMixin
implements Controller, SCAPropertyController {
// -------------------------------------------------------------------------
// Implementation of the Controller interface
// -------------------------------------------------------------------------
public void initFcController( InitializationContext ic )
throws InstantiationException {
_super_initFcController(ic);
}
// -------------------------------------------------------------------------
// Implementation of the SCAPropertyController interface
// -------------------------------------------------------------------------
public void setValue( String name, Object value )
throws IllegalArgumentException {
// Re-inject the value on current content instances
_this_weaveableSCACC.setPropertyValue(name,value);
}
public boolean containsDeclaredPropertyName( String name ) {
boolean b = _this_weaveableSCACC.containsPropertyName(name);
return b;
}
public String[] getDeclaredPropertyNames() {
String[] names = _this_weaveableSCACC.getPropertyNames();
return names;
}
public Class<?> getDeclaredPropertyType( String name ) {
Class<?> type = _this_weaveableSCACC.getPropertyType(name);
return type;
}
// -------------------------------------------------------------------------
// Fields and methods required by the mixin class in the base class
// -------------------------------------------------------------------------
protected abstract void _super_initFcController( InitializationContext ic )
throws InstantiationException;
private SCAContentController _this_weaveableSCACC;
}
......@@ -28,45 +28,53 @@ import java.util.Map;
import java.util.Set;
import org.objectweb.fractal.api.control.NameController;
import org.objectweb.fractal.api.factory.InstantiationException;
import org.objectweb.fractal.julia.InitializationContext;
import org.ow2.frascati.tinfi.control.content.SCAContentController;
/**
* Mixin layer for implementing the {@link SCAContentController} interface for
* scaPrimitive components.
* Implementing the {@link SCAContentController} control interface shared by
* scaPrimitive and scaComposite components.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
*/
public abstract class SCAPropertyControllerMixin
implements SCAPropertyController {
// -------------------------------------------------------------------------
// Private constructor
// -------------------------------------------------------------------------
private SCAPropertyControllerMixin () {}
// -------------------------------------------------------------------------
// Implementation of the SCAPropertyController interface
// -------------------------------------------------------------------------
private Map<String,Object> values = new HashMap<String,Object>();
private Map<String,Class<?>> types = new HashMap<String,Class<?>>();
/**