summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCédric Bosdonnat <cedricbosdo@openoffice.org>2011-01-28 18:25:37 +0100
committerCédric Bosdonnat <cedricbosdo@openoffice.org>2011-01-28 18:25:37 +0100
commit116ed4c41429c2ff12dbdde67869e742955f9c0d (patch)
treeffd9d1f571fc99a68d659a93d3ac6bd2c50e4bd3
parent1fc7bb030a5a5e95b4698d98470c528d58a978b4 (diff)
End of hackweek: almost all the C++ methods and fields code is generatedHEADmaster
-rw-r--r--langs/cpp/tools.tpl223
-rw-r--r--src/org/libreoffice/tools/tests/CppToolsTemplateTest.java269
-rw-r--r--src/org/libreoffice/tools/tests/TypeManagerTest.java2
-rw-r--r--src/org/libreoffice/tools/types/TypeManager.java119
4 files changed, 475 insertions, 138 deletions
diff --git a/langs/cpp/tools.tpl b/langs/cpp/tools.tpl
index a0df9f9..0a89664 100644
--- a/langs/cpp/tools.tpl
+++ b/langs/cpp/tools.tpl
@@ -1,5 +1,9 @@
<#function scopedCppName type shortname=false>
- <#local name = "::" + type?replace( ".", "::" )>
+ <#local name = "">
+ <#if !type?starts_with( "::" )>
+ <#local name = "::">
+ </#if>
+ <#local name = name + type?replace( ".", "::" )>
<#if shortname>
<#local name = name?replace( "::com::sun::star", "css" )>
</#if>
@@ -49,57 +53,68 @@
<#return flags>
</#function>
-<#function cppType unotype>
- <#local cpp = unotype>
- <#if unotype?is_string >
- <#-- Handle UNO simple types -->
- <#if unotype == "string">
- <#local cpp = "::rtl::OUString">
- <#elseif unotype == "char">
- <#local cpp = "::sal_Unicode">
- <#elseif unotype == "any">
- <#local cpp = "::com::sun::star::uno::Any">
- <#elseif unotype == "type">
- <#local cpp = "::com::sun::star::uno::Type">
- <#elseif unotype == "boolean">
- <#local cpp = "::sal_Bool">
- <#elseif unotype == "byte">
- <#local cpp = "::sal_Int8">
- <#elseif unotype == "short">
- <#local cpp = "::sal_Int16">
- <#elseif unotype == "unsigned short">
- <#local cpp = "::sal_uInt16">
- <#elseif unotype == "long">
- <#local cpp = "::sal_Int32">
- <#elseif unotype == "unsigned long">
- <#local cpp = "::sal_uInt32">
- <#elseif unotype == "hyper">
- <#local cpp = "::sal_Int64">
- <#elseif unotype == "unsigned hyper">
- <#local cpp = "::sal_uInt64">
- </#if>
- <#elseif unotype?is_hash>
- <#-- Handle UNO complex types -->
- <#local cpp = "">
- <#local levels = (unotype["nested_levels"] - 1)>
- <#if (levels > 0)>
- <#list 0..levels as i>
- <#local cpp = cpp + "::com::sun::star::uno::Sequence< ">
- </#list>
- </#if>
- <#if unotype["type"] == "interface">
- <#local cpp = cpp + "::com::sun::star::uno::Reference< " + scopedCppName( unotype["name"] ) + " >">
- </#if>
- <#if (levels > 0)>
- <#list 0..levels as i>
- <#local cpp = cpp + " >">
- </#list>
+<#function cppType unotype shortname=false>
+ <#local cpp = unotype["name"]>
+
+ <#-- Remove UNO sequence markers as we have the nested levels -->
+ <#local cpp = cpp?replace( "[]", "" )>
+
+ <#if unotype["type"] == "simple" >
+ <#if ( cpp != "void" ) && ( cpp != "double" ) && ( cpp != "float" )>
+ <#local cpp = cpp?replace( "string", "::rtl::OUString" )>
+ <#local cpp = cpp?replace( "char", "::sal_Unicode" )>
+ <#local cpp = cpp?replace( "any", "::com::sun::star::uno::Any" )>
+ <#local cpp = cpp?replace( "type", "::com::sun::star::uno::Type" )>
+ <#local cpp = cpp?replace( "boolean", "::sal_Bool" )>
+ <#local cpp = cpp?replace( "byte", "::sal_Int8" )>
+ <#local cpp = cpp?replace( "unsigned short", "::sal_uInt16" )>
+ <#local cpp = cpp?replace( "short", "::sal_Int16" )>
+ <#local cpp = cpp?replace( "unsigned long", "::sal_uInt32" )>
+ <#local cpp = cpp?replace( "long", "::sal_Int32" )>
+ <#local cpp = cpp?replace( "unsigned hyper", "::sal_uInt64" )>
+ <#local cpp = cpp?replace( "hyper", "::sal_Int64" )>
+
+ <#local cpp = scopedCppName( cpp, shortname )>
</#if>
+ <#elseif unotype["type"] == "interface">
+ <#local cpp = "::com::sun::star::uno::Reference< " + scopedCppName( cpp ) + " >">
+ </#if>
+
+ <#local levels = (unotype["nested_levels"] - 1)>
+ <#if (levels > 0)>
+ <#list 0..levels as i>
+ <#local cpp = "::com::sun::star::uno::Sequence< " + cpp + " >">
+ </#list>
+ </#if>
+
+ <#if shortname>
+ <#local name = name?replace( "::com::sun::star", "css" )>
</#if>
<#return cpp>
</#function>
-<#function printFieldSignature field setter>
+<#function defaultValue unotype>
+ <#local value = "">
+ <#if unotype["type"] == "simple">
+ <#local value = "0">
+ <#if unotype["name"] == "boolean">
+ <#local value = "sal_False">
+ <#elseif unotype["name"] == "string">
+ <#local value = "::rtl::OUString()">
+ <#elseif unotype["name"] == "double" || unotype["name"] == "float">
+ <#local value = "0.0">
+ <#elseif unotype["name"] == "void">
+ <#local value = cppType( unotype )>
+ <#elseif unotype["name"] == "any" || unotype["name"] == "type">
+ <#local value = cppType( unotype ) + "()">
+ </#if>
+ <#elseif unotype["type"] == "interface">
+ <#local value = cppType( unotype ) + "()">
+ </#if>
+ <#return value>
+</#function>
+
+<#function printFieldSignature field setter classname = "">
<#if setter>
<#local return_type = "void">
<#local name_prefix = "set">
@@ -110,41 +125,111 @@
<#local args = "" >
</#if>
- <#local result = return_type + " SAL_CALL " + name_prefix + field["name"] + "(" + args + ")" >
- <#local result = result + " throw (" + printExceptions( field["get_exceptions"] ) +")" >
+ <#local result = return_type + " SAL_CALL " + classname + name_prefix + field["name"] + "(" + args + ")" >
+ <#local result = result + " throw (">
+ <#if setter>
+ <#local result = result + printExceptions( field["set_exceptions"] ) +")" >
+ <#else>
+ <#local result = result + printExceptions( field["get_exceptions"] ) +")" >
+ </#if>
<#return result>
</#function>
-<#macro printField field print_body>
- <#if !print_body>virtual </#if>${printFieldSignature( field, false )}<#if !print_body>;<#else>
+<#macro printSetPropertyMixinBody field>
+ <#if field["bound"]>BoundListeners l;
+ </#if><#if field["set_exceptions"]?seq_contains("com.sun.star.beans.PropertyVetoException")>css::Any v;
+ <#if field["type"]["name"]?contains("com.sun.star.beans.Optional")>if ( the_value.IsPresent )
{
- // TODO Implement the body here
- }
- </#if>
-
-<#if !field["readonly"]><#if !print_body>virtual </#if>${printFieldSignature( field, true )}<#if !print_body>;<#else>
+ v <<= the_value.Value;
+ }<#else>v <<= the_value.Value;</#if>
+ prepareSet(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("${field["name"]}")),
+ css::uno::Any(), v, <#if field["bound"]>&l<#else>NULL</#if>);
+ <#else>
+ prepareSet(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("${field["name"]}")),
+ css::uno::Any(), css::uno::Any(), <#if field["bound"]>&l<#else>NULL</#if>);
+ </#if>
{
- // TODO Implement the body here
- }
-</#if></#if>
+ osl::MutexGuard g(m_aMutex);
+ m_${field["name"]} = the_value;
+ }<#if !field["bound"]><#return></#if>
+ <#if field["bound"]>l.notify();<#return></#if>
</#macro>
-<#macro printMethods intf>
- // TODO
-<#assign generated = generated + ":" + intf["name"] + ":">
-// TODO Continue
-<#if all_methods >
-<#list intf["super_types"] as super>
-<@printMethods super/>
-</#list>
-<#if intf["fields"]?size > 0 || intf["methods"]?size > 0>
- // ${intf["name"]?replace( ".", ":" )}:
+<#macro printField field print_body><#local scopedname = "">
+<#if !print_body>virtual <#else><#local scopedname = classname() + "::"></#if>${printFieldSignature( field, false, scopedname )}<#if !print_body>;<#else>
+{
+ <#if (propertyHelper?length > 0)>osl::MutexGuard g(m_aMutex);
+ </#if>return m_${field["name"]};
+}
</#if>
+
+<#if !field["readonly"]><#if !print_body>virtual </#if>${printFieldSignature( field, true, scopedname )}<#if !print_body>;<#else>
+{
+<#if (propertyHelper?length > 0)><@printSetPropertyMixinBody field /><#else> m_${field["name"]} = the_value;</#if>
+}
+</#if></#if>
+</#macro>
+
+<#function getRef unotype>
+ <#local ref = "">
+ <#if unotype["name"] == "string" || unotype["name"] == "any" || unotype["name"] == "type"
+ || (unotype["nested_levels"] > 0) || unotype["type"] == "interface">
+ <#local ref = "&">
+ </#if>
+ <#return ref>
+</#function>
+
+<#--
+ Returns the arguments list for the given method
+ * args: the list of parameters to print
+ -->
+<#function printMethodParams args>
+ <#local result = "">
+ <#list args as arg>
+ <#if !arg["flags"]?contains( "out" )>
+ <#local result = result + "const ">
+ </#if>
+ <#local result = result + cppType( arg["type"] ) + getRef( arg["type"]) + " " + arg["name"]>
+ <#if arg_has_next><#local result = result + ", "></#if>
+ </#list>
+ <#return result>
+</#function>
+
+<#--
+ Returns the interface method signature.
+ * method: the method object for which to print the signature
+ * classname: is used when printing the implementation signature
+ -->
+<#function printMethodSignature method classname = "">
+ <#local sig = cppType(method["return_type"]) + " SAL_CALL " + method["name"] + "(" + printMethodParams(method["parameters"]) + ")">
+ <#local sig = sig + " throw (" + printExceptions( method["exceptions"] ) + ")">
+ <#return sig>
+</#function>
+
+<#macro printMethod method print_body>
+<#if !print_body>virtual </#if>${printMethodSignature(method)}<#if !print_body>;<#else>
+{
+ <#if method["return_type"] != "void">// TODO: Exchange the default return implementation for "${method["name"]}"!!!
+ // Exchange the default return implementation.
+ // NOTE: Default initialized polymorphic structs can cause problems because of
+ // missing default initialization of primitive types of some C++ compilers or
+ // different Any initialization in Java and C++ polymorphic structs.
+ return ${defaultValue( method["return_type"] )};<#else>// TODO: Insert your implementation for "${method["name"]}" here.</#if>
+}
</#if>
+</#macro>
+<#macro printMethods intf><#assign generated = generated + ":" + intf["name"] + ":">
+<#if all_methods ><#list intf["super_types"] as super><@printMethods super/></#list>
+<#if (intf["fields"]?size > 0) || (intf["methods"]?size > 0)> // ${intf["name"]?replace( ".", ":" )}:</#if></#if>
<#list intf["fields"] as field>
<@printField(field, false)/>
</#list>
+<#list intf["methods"] as method>
+<@printMethod(method, false)/>
+</#list>
</#macro>
<#macro printMethodsBodies intf>
diff --git a/src/org/libreoffice/tools/tests/CppToolsTemplateTest.java b/src/org/libreoffice/tools/tests/CppToolsTemplateTest.java
index f2305b4..110eae0 100644
--- a/src/org/libreoffice/tools/tests/CppToolsTemplateTest.java
+++ b/src/org/libreoffice/tools/tests/CppToolsTemplateTest.java
@@ -2,6 +2,7 @@ package org.libreoffice.tools.tests;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
@@ -27,8 +28,16 @@ import freemarker.template.TemplateException;
public class CppToolsTemplateTest {
+ private static final String TEST_IMPLNAME = "some.test.Type";
+ private static final String TEST_SIMPLE_IMPLNAME = "Type";
+ private static final String EXPECTED_CLASSNAME = "Type";
+ private static final String EXPECTED_COMP_NAMESPACE = "::some::test::comp_Type";
+ private static final String EXPECTED_NAMESPACE = "::some::test::Type";
+
private static final String[] TEST_EXCEPTIONS = new String[]{ "some.type.Exception1", "some.type.Exception2" };
+ private static final String[] TEST_VETOABLE_EXCEPTIONS = new String[]{ "some.type.Exception1", "com.sun.star.beans.PropertyVetoException" };
private static final String EXPECTED_EXCEPTIONS = "::com::sun::star::uno::RuntimeException, ::some::type::Exception1, ::some::type::Exception2";
+ private static final String EXPECTED_VETOABLE_EXCEPTIONS = "::com::sun::star::uno::RuntimeException, ::some::type::Exception1, ::com::sun::star::beans::PropertyVetoException";
private static final String[] TEST_EXCEPTIONS_EMPTY = new String[]{ };
private static final String EXPECTED_EXCEPTIONS_EMPTY = "::com::sun::star::uno::RuntimeException";
@@ -72,33 +81,33 @@ public class CppToolsTemplateTest {
@Test
public void classnameFqdnTest( ) throws IOException, TemplateException {
HashMap<String, Object> model = new HashMap<String, Object>();
- model.put( "implname", "some.test.Type" );
+ model.put( "implname", TEST_IMPLNAME );
String result = processTemplate( "${classname()}", model );
- assertEquals( "Wrong classname", "Type", result );
+ assertEquals( "Wrong classname", EXPECTED_CLASSNAME, result );
}
@Test
public void classnameSimpleTest( ) throws IOException, TemplateException {
HashMap<String, Object> model = new HashMap<String, Object>();
- model.put( "implname", "Type" );
+ model.put( "implname", TEST_SIMPLE_IMPLNAME );
String result = processTemplate( "${classname()}", model );
- assertEquals( "Wrong classname", "Type", result );
+ assertEquals( "Wrong classname", EXPECTED_CLASSNAME, result );
}
@Test
public void generateNamespaceFqdnNoPrefixTest( ) throws IOException, TemplateException {
HashMap<String, Object> model = new HashMap<String, Object>();
- model.put( "implname", "some.test.Type" );
+ model.put( "implname", TEST_IMPLNAME );
String result = processTemplate( "${generateNamespace()}", model );
- assertEquals( "Wrong classname", "::some::test::Type", result );
+ assertEquals( "Wrong namespace", EXPECTED_NAMESPACE, result );
}
@Test
public void generateNamespaceFqdnPrefixTest( ) throws IOException, TemplateException {
HashMap<String, Object> model = new HashMap<String, Object>();
- model.put( "implname", "some.test.Type" );
+ model.put( "implname", TEST_IMPLNAME );
String result = processTemplate( "${generateNamespace( \"comp_\" )}", model );
- assertEquals( "Wrong classname", "::some::test::comp_Type", result );
+ assertEquals( "Wrong namespace", EXPECTED_COMP_NAMESPACE, result );
}
@Test
@@ -106,7 +115,7 @@ public class CppToolsTemplateTest {
HashMap<String, Object> model = new HashMap<String, Object>();
model.put( "implname", "Type" );
String result = processTemplate( "${generateNamespace()}", model );
- assertEquals( "Wrong classname", "::Type", result );
+ assertEquals( "Wrong namespace", "::Type", result );
}
@Test
@@ -161,18 +170,18 @@ public class CppToolsTemplateTest {
public void printFieldSignatureGetterTest( ) throws IOException, TemplateException {
HashMap<String, Object> model = new HashMap<String, Object>();
boolean readonly = false;
- model.put( "field", getTestField( readonly ) );
+ model.put( "field", getTestField( readonly, false, false, false ) );
String result = processTemplate( "${printFieldSignature( field, false )}", model );
- assertEquals( getFieldGetterSignature(), result );
+ assertEquals( getFieldGetterSignature( new String(), false ), result );
}
@Test
public void printFieldSignatureSetterReadwriteTest( ) throws IOException, TemplateException {
HashMap<String, Object> model = new HashMap<String, Object>();
boolean readonly = false;
- model.put( "field", getTestField( readonly ) );
+ model.put( "field", getTestField( readonly, false, false, false ) );
String result = processTemplate( "${printFieldSignature( field, true )}", model );
- assertEquals( getFieldSetterSignature( readonly ), result );
+ assertEquals( getFieldSetterSignature( new String(), readonly, false, false ), result );
}
@Test
@@ -197,11 +206,14 @@ public class CppToolsTemplateTest {
Iterator<String> it = mappings.keySet().iterator();
while ( it.hasNext() ) {
String unoType = it.next();
- String result = processTemplate( "${cppType( \"" + unoType + "\" )}", new HashMap<String, Object>() );
+ HashMap<String, Object> model = new HashMap<String, Object>();
+ model.put( "type", getTestType( unoType, TypeManager.UNO_TYPE_CLASS_SIMPLE, 0 ) );
+
+ String result = processTemplate( "${cppType( type )}", model );
assertEquals( "Wrong c++ type for UNO: " + unoType, mappings.get( unoType ), result );
}
}
-
+
@Test
public void cppTypeInterfaceTest() throws IOException, TemplateException {
@@ -223,13 +235,33 @@ public class CppToolsTemplateTest {
}
@Test
- public void cppTypeSequenceTest() throws IOException, TemplateException {
+ public void cppTypeSequenceSimpleTest() throws IOException, TemplateException {
// Populate the template model with a test interface type
HashMap<String, Object> model = new HashMap<String, Object>();
HashMap<String, Object> type = new HashMap<String, Object>();
- type.put( TypeManager.UNO_TYPE_NAME, "some.type.XType" );
+ type.put( TypeManager.UNO_TYPE_NAME, "[][]short" );
+ type.put( TypeManager.UNO_NESTED_LEVELS, 2 );
+ type.put( TypeManager.UNO_TYPE_CLASS, "simple" );
+
+ model.put( "testtype", type );
+
+ // Run the test
+ String result = processTemplate( "${cppType( testtype )}", model );
+
+ // Compare
+ assertEquals( "Wrong c++ type for sequence of simple types", "::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::sal_Int16 > >", result );
+ }
+
+ @Test
+ public void cppTypeSequenceInterfaceTest() throws IOException, TemplateException {
+
+ // Populate the template model with a test interface type
+ HashMap<String, Object> model = new HashMap<String, Object>();
+
+ HashMap<String, Object> type = new HashMap<String, Object>();
+ type.put( TypeManager.UNO_TYPE_NAME, "[][]some.type.XType" );
type.put( TypeManager.UNO_NESTED_LEVELS, 2 );
type.put( TypeManager.UNO_TYPE_CLASS, "interface" );
@@ -241,27 +273,216 @@ public class CppToolsTemplateTest {
// Compare
assertEquals( "Wrong c++ type for interfaces", "::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::some::type::XType > > >", result );
}
+
+ @Test
+ public void defaultValueSimpleTypeTest() throws IOException, TemplateException {
+
+ HashMap<String, String> mappings = new HashMap<String, String>();
+ mappings.put( "void", "void" );
+ mappings.put( "boolean", "sal_False" );
+ mappings.put( "byte", "0" );
+ mappings.put( "short", "0" );
+ mappings.put( "unsigned short", "0" );
+ mappings.put( "long", "0" );
+ mappings.put( "unsigned long", "0" );
+ mappings.put( "hyper", "0" );
+ mappings.put( "unsigned hyper", "0" );
+ mappings.put( "float", "0.0" );
+ mappings.put( "double", "0.0" );
+ mappings.put( "char", "0" );
+ mappings.put( "string", "::rtl::OUString()" );
+ mappings.put( "type", "::com::sun::star::uno::Type()" );
+ mappings.put( "any", "::com::sun::star::uno::Any()" );
+
+ Iterator<String> it = mappings.keySet().iterator();
+ while ( it.hasNext() ) {
+ String unoType = it.next();
+ HashMap<String, Object> model = new HashMap<String, Object>();
+ model.put( "type", getTestType( unoType, TypeManager.UNO_TYPE_CLASS_SIMPLE, 0 ) );
+ String result = processTemplate( "${defaultValue( type )}", model );
+ assertEquals( "Wrong c++ default value for UNO type: " + unoType, mappings.get( unoType ), result );
+ }
+ }
+
+ @Test
+ public void defaultValueInterfaceTest() throws IOException, TemplateException {
+
+ // Populate the template model with a test interface type
+ HashMap<String, Object> model = new HashMap<String, Object>();
+
+ HashMap<String, Object> type = new HashMap<String, Object>();
+ type.put( TypeManager.UNO_TYPE_NAME, "some.type.XType" );
+ type.put( TypeManager.UNO_NESTED_LEVELS, 0 );
+ type.put( TypeManager.UNO_TYPE_CLASS, "interface" );
+
+ model.put( "testtype", type );
+
+ // Run the test
+ String result = processTemplate( "${defaultValue( testtype )}", model );
+
+ // Compare
+ assertEquals( "Wrong c++ default value for interfaces", "::com::sun::star::uno::Reference< ::some::type::XType >()", result );
+ }
+
+ @Test
+ public void printFieldBodyTest() throws IOException, TemplateException {
+
+ int READONLY = 0x1;
+ int BOUND = 0x2;
+ int USEMIXIN = 0x4;
+ int OPTIONAL = 0x8;
+ int VETOABLE = 0x16;
+
+ int flags = 0;
+ int allFlags = READONLY | BOUND | USEMIXIN | OPTIONAL | VETOABLE;
+
+ while ( flags <= allFlags ) {
+ boolean readonly = ( flags & READONLY ) > 0;
+ boolean bound = ( flags & BOUND ) > 0;
+ boolean usemixin = ( flags & USEMIXIN ) > 0;
+ boolean optional = ( flags & OPTIONAL ) > 0;
+ boolean vetoable = ( flags & VETOABLE ) > 0;
+
+ HashMap<String, Object> model = new HashMap<String, Object>();
+
+ model.put( "implname", TEST_IMPLNAME );
+ model.put( "field", getTestField( readonly, bound, optional, vetoable ) );
+ model.put( "propertyHelper", usemixin ? "some.helper" : new String() );
- private Object getTestField( boolean pReadonly) {
+ String result = processTemplate( "<@printField field true/>", model );
+
+ String expected = getFieldGetterSignature( EXPECTED_CLASSNAME + "::", optional ) + "\n" + getFieldGetterBody( usemixin ) + "\n";
+ if ( !readonly ) {
+ expected += getFieldSetterSignature( EXPECTED_CLASSNAME + "::", readonly, optional, vetoable ) + "\n" + getFieldSetterBody( usemixin, bound, optional, vetoable );
+ }
+
+ String failMessage = MessageFormat.format(
+ "Unexpected field bodies for ( Readonly, Bound, UseMixin, Optional, Vetoable) = ( {0}, {1}, {2}, {3}, {4} ), ",
+ readonly, bound, usemixin, optional, vetoable );
+ assertEquals( failMessage, expected, result );
+
+ flags++;
+ }
+ }
+
+ @Test
+ public void getRefTest( ) throws IOException, TemplateException {
+ fail( "Not implemented" );
+ }
+
+ @Test
+ public void printMethodParamsTest( ) throws IOException, TemplateException {
+ fail( "Not implemented" );
+ }
+
+ @Test
+ public void printMethodSignatureTest( ) throws IOException, TemplateException {
+ fail( "Not implemented" );
+ }
+
+ @Test
+ public void printMethodTest( ) throws IOException, TemplateException {
+ fail( "Not implemented" );
+ }
+
+ private Object getTestType(String pName, String pTypeClass, int pLevels) {
+ HashMap<String, Object> model = new HashMap<String, Object>();
+
+ model.put( TypeManager.UNO_TYPE_NAME, pName );
+ model.put( TypeManager.UNO_TYPE_CLASS, pTypeClass );
+ model.put( TypeManager.UNO_NESTED_LEVELS, Integer.valueOf( pLevels ) );
+
+ return model;
+ }
+
+ private Object getTestField( boolean pReadonly, boolean pBound, boolean pOptional, boolean pVetoable ) {
HashMap<String, Object> field = new HashMap<String, Object>();
+ String typeName = "string";
+ if ( pOptional ) {
+ typeName = "com.sun.star.beans.Optional<" + typeName + ">";
+ }
+
field.put( TypeManager.FIELD_NAME, "Foo");
- field.put( TypeManager.FIELD_TYPE, "string" );
+ field.put( TypeManager.FIELD_TYPE, getTestType( typeName, TypeManager.UNO_TYPE_CLASS_SIMPLE, 0 ) );
field.put( TypeManager.FIELD_GET_EXCEPTIONS, TEST_EXCEPTIONS );
- field.put( TypeManager.FIELD_SET_EXCEPTIONS, TEST_EXCEPTIONS );
+ field.put( TypeManager.FIELD_SET_EXCEPTIONS, ( pVetoable ? TEST_VETOABLE_EXCEPTIONS : TEST_EXCEPTIONS ) );
field.put( TypeManager.FIELD_READONLY, Boolean.valueOf( pReadonly ) );
+ field.put( TypeManager.FIELD_BOUND, Boolean.valueOf( pBound ) );
return field;
}
- private Object getFieldGetterSignature() {
- return "::rtl::OUString SAL_CALL getFoo() throw (" + EXPECTED_EXCEPTIONS + ")";
+ private String getFieldGetterSignature( String pClassname, boolean pOptional ) {
+ String type = "::rtl::OUString";
+ if ( pOptional ) {
+ type = "::com::sun::star::beans::Optional<" + type + ">";
+ }
+ return type + " SAL_CALL " + pClassname + "getFoo() throw (" + EXPECTED_EXCEPTIONS + ")";
+ }
+
+ private String getFieldGetterBody( boolean pUseMixin ) {
+ StringBuffer buf = new StringBuffer();
+ buf.append( "{\n" );
+ if ( pUseMixin ) {
+ buf.append( " osl::MutexGuard g(m_aMutex);\n" );
+ }
+ buf.append( " return m_Foo;\n" );
+ buf.append( "}\n" );
+ return buf.toString();
+ }
+
+ private String getFieldSetterBody( boolean pUseMixin, boolean pBound, boolean pOptional, boolean pVetoable ) {
+ StringBuffer buf = new StringBuffer();
+ buf.append( "{\n" );
+ if ( pUseMixin ) {
+ String listener = "NULL";
+ if ( pBound ) {
+ buf.append( " BoundListeners l;\n" );
+ listener = "&l";
+ }
+ if ( pVetoable ) {
+ buf.append( " css::Any v;\n" );
+ if ( pOptional ) {
+ buf.append( " if ( the_value.IsPresent )\n" );
+ buf.append( " {\n" );
+ buf.append( " v <<= the_value.Value;\n" );
+ buf.append( " }\n" );
+ } else {
+ buf.append( " v <<= the_value.Value;\n" );
+ }
+ buf.append( " prepareSet(\n" );
+ buf.append( " rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(\"Foo\")),\n");
+ buf.append( " css::uno::Any(), v, " + listener + ");\n");
+ } else {
+ buf.append( " prepareSet(\n" );
+ buf.append( " rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(\"Foo\")),\n");
+ buf.append( " css::uno::Any(), css::uno::Any(), " + listener + ");\n");
+ }
+ buf.append( " {\n" );
+ buf.append( " osl::MutexGuard g(m_aMutex);\n");
+ buf.append( " m_Foo = the_value;\n" );
+ buf.append( " }\n" );
+
+ if ( pBound ) {
+ buf.append( " l.notify();\n" );
+ }
+ } else {
+ buf.append( " m_Foo = the_value;\n" );
+ }
+ buf.append( "}\n" );
+ return buf.toString();
}
- private Object getFieldSetterSignature( boolean pReadonly ) {
+ private String getFieldSetterSignature( String pClassname, boolean pReadonly, boolean pOptional, boolean pVetoable ) {
String result = new String();
if ( !pReadonly ) {
- result = "void SAL_CALL setFoo(::rtl::OUString the_value) throw (" + EXPECTED_EXCEPTIONS + ")";
+ String type = "::rtl::OUString";
+ if ( pOptional ) {
+ type = "::com::sun::star::beans::Optional<" + type + ">";
+ }
+ String exceptions = pVetoable ? EXPECTED_VETOABLE_EXCEPTIONS : EXPECTED_EXCEPTIONS;
+ result = "void SAL_CALL " + pClassname + "setFoo(" + type + " the_value) throw (" + exceptions + ")";
}
return result;
}
diff --git a/src/org/libreoffice/tools/tests/TypeManagerTest.java b/src/org/libreoffice/tools/tests/TypeManagerTest.java
index c9eb151..6bda834 100644
--- a/src/org/libreoffice/tools/tests/TypeManagerTest.java
+++ b/src/org/libreoffice/tools/tests/TypeManagerTest.java
@@ -109,11 +109,13 @@ public class TypeManagerTest {
assertNotNull( "Field missing", roField );
assertNotNull( "missing type", roField.get( TypeManager.FIELD_TYPE ) );
assertTrue( "Should be readonly", ((Boolean)roField.get( TypeManager.FIELD_READONLY ) ).booleanValue() );
+ assertFalse( "Shouldn't be bound", ((Boolean)roField.get( TypeManager.FIELD_BOUND ) ).booleanValue() );
Map<?, ?> simpleField = getField( fields, READWRITE_FIELD );
assertNotNull( "Field missing", simpleField );
assertNotNull( "missing type", simpleField.get( TypeManager.FIELD_TYPE ) );
assertFalse( "Shouldn't be readonly", ((Boolean)simpleField.get( TypeManager.FIELD_READONLY ) ).booleanValue() );
+ assertFalse( "Shouldn't be bound", ((Boolean)roField.get( TypeManager.FIELD_BOUND ) ).booleanValue() );
Map<?, ?> excepField = getField( fields, SETEXCEPTION_FIELD );
assertNotNull( "Field missing", excepField );
diff --git a/src/org/libreoffice/tools/types/TypeManager.java b/src/org/libreoffice/tools/types/TypeManager.java
index 89a1726..cd53b45 100644
--- a/src/org/libreoffice/tools/types/TypeManager.java
+++ b/src/org/libreoffice/tools/types/TypeManager.java
@@ -47,6 +47,7 @@ public class TypeManager {
public static final String FIELD_NAME = "name";
public static final String FIELD_TYPE = "type";
public static final String FIELD_READONLY = "readonly";
+ public static final String FIELD_BOUND = "bound";
public static final String FIELD_GET_EXCEPTIONS = "get_exceptions";
public static final String FIELD_SET_EXCEPTIONS = "set_exceptions";
@@ -54,6 +55,10 @@ public class TypeManager {
public static final String UNO_TYPE_NAME = "name";
public static final String UNO_TYPE_CLASS = "type";
public static final String UNO_NESTED_LEVELS = "nested_levels";
+
+ public static final String UNO_TYPE_CLASS_SIMPLE = "simple";
+
+ public static final String UNO_TYPE_CLASS_INTERFACE = "interface";
private String mInstallDir;
@@ -317,21 +322,11 @@ public class TypeManager {
* <tr><th>Name</th> <th>Type</th> <th>Description</th></tr>
* <tr><td>name</td><td>String</td><td>the name of the interface</td></tr>
* <tr><td>super_type</td><td>Sequence of interfaces</td><td>the base interfaces</td></tr>
- * <tr><td>fields</td><td>Sequence of fields</td><td>the interface fields model</td></tr>
+ * <tr><td>fields</td><td>Sequence of attributes</td><td>the interface attributes model</td></tr>
* <tr><td>methods</td><td>Sequence of methods</td><td>the interface methods model</td></tr>
* <tr><td>TODO name</td><td>type</td><td>description</td></tr>
* </table>
*
- * Field object:
- * <table border="1">
- * <tr><th>Name</th> <th>Type</th> <th>Description</th></tr>
- * <tr><td>name</td><td>String</td><td>the name of the field</td></tr>
- * <tr><td>type</td><td>Map</td><td>the UNO type of the field</td></tr>
- * <tr><td>get_exception</td><td>sequence of string</td><td>the names of the get exceptions or an empty list</td></tr>
- * <tr><td>set_exception</td><td>sequence of string</td><td>the names of the set exceptions or an empty list</td></tr>
- * <tr><td>TODO name</td><td>type</td><td>description</td></tr>
- * </table>
- *
* @param pIntf the name of the interface for which to get a model.
*
* @return the interface model or <code>null</code>
@@ -361,8 +356,6 @@ public class TypeManager {
// Fields and methods
for (XInterfaceMemberTypeDescription member : xIface2.getMembers() ) {
- HashMap<String, Object> memberModel = new HashMap<String, Object>();
-
XInterfaceAttributeTypeDescription2 attribute = UnoRuntime.queryInterface(
XInterfaceAttributeTypeDescription2.class, member );
XInterfaceMethodTypeDescription method = UnoRuntime.queryInterface(
@@ -370,30 +363,12 @@ public class TypeManager {
if ( attribute != null ) {
// Handle the attribute here
- memberModel.put( FIELD_NAME, attribute.getMemberName() );
- memberModel.put( FIELD_TYPE, getTypeModel( attribute.getType() ) );
- memberModel.put( FIELD_READONLY, Boolean.valueOf( attribute.isReadOnly() ) );
-
- ArrayList<String> getExceptions = new ArrayList<String>();
- XCompoundTypeDescription[] getExpt = attribute.getGetExceptions();
- for (XCompoundTypeDescription exceptionType : getExpt) {
- getExceptions.add( exceptionType.getName() );
- }
- memberModel.put( FIELD_GET_EXCEPTIONS, getExceptions );
-
- ArrayList<String> setExceptions = new ArrayList<String>();
- XCompoundTypeDescription[] setExpt = attribute.getSetExceptions();
- for (XCompoundTypeDescription exceptionType : setExpt) {
- setExceptions.add( exceptionType.getName() );
- }
- memberModel.put( FIELD_SET_EXCEPTIONS, setExceptions );
-
- fields.add( memberModel );
+ fields.add( getAttributeModel( attribute ) );
} else if ( method != null ) {
// TODO Handle the method here
- methods.add( memberModel );
+ methods.add( getMethodModel( method ) );
}
}
@@ -409,13 +384,73 @@ public class TypeManager {
}
/**
+ * Method object:
+ * <table border="1">
+ * <tr><th>Name</th> <th>Type</th> <th>Description</th></tr>
+ * <tr><td>name</td><td>String</td><td>the name of the method</td></tr>
+ * <tr><td>return_type</td><td>Map</td><td>the UNO type returned by the method</td></tr>
+ * <tr><td>parameters</td><td>sequence of Parameters</td><td>the parameters of the method or an empty list</td></tr>
+ * <tr><td>exceptions</td><td>sequence of string</td><td>the names of the exceptions or an empty list</td></tr>
+ * </table>
+ *
+ * @param pMethod the method to create the model from
+ *
+ * @return the template model object
+ */
+ private Object getMethodModel(XInterfaceMethodTypeDescription pMethod) {
+ HashMap<String, Object> model = new HashMap<String, Object>();
+
+ // TODO Complete me
+
+ return model;
+ }
+
+ /**
+ * Attribute object:
+ * <table border="1">
+ * <tr><th>Name</th> <th>Type</th> <th>Description</th></tr>
+ * <tr><td>name</td><td>String</td><td>the name of the attribute</td></tr>
+ * <tr><td>type</td><td>Map</td><td>the UNO type of the attribute</td></tr>
+ * <tr><td>get_exceptions</td><td>sequence of string</td><td>the names of the get exceptions or an empty list</td></tr>
+ * <tr><td>set_exceptions</td><td>sequence of string</td><td>the names of the set exceptions or an empty list</td></tr>
+ * </table>
+ *
+ * @param pAttribute the attribute to create the model from
+ *
+ * @return the template model object
+ */
+ public Object getAttributeModel( XInterfaceAttributeTypeDescription2 pAttribute ) {
+ HashMap<String, Object> model = new HashMap<String, Object>();
+
+ model.put( FIELD_NAME, pAttribute.getMemberName() );
+ model.put( FIELD_TYPE, getTypeModel( pAttribute.getType() ) );
+ model.put( FIELD_READONLY, Boolean.valueOf( pAttribute.isReadOnly() ) );
+ model.put( FIELD_BOUND, Boolean.valueOf( pAttribute.isBound() ) );
+
+ ArrayList<String> getExceptions = new ArrayList<String>();
+ XCompoundTypeDescription[] getExpt = pAttribute.getGetExceptions();
+ for (XCompoundTypeDescription exceptionType : getExpt) {
+ getExceptions.add( exceptionType.getName() );
+ }
+ model.put( FIELD_GET_EXCEPTIONS, getExceptions );
+
+ ArrayList<String> setExceptions = new ArrayList<String>();
+ XCompoundTypeDescription[] setExpt = pAttribute.getSetExceptions();
+ for (XCompoundTypeDescription exceptionType : setExpt) {
+ setExceptions.add( exceptionType.getName() );
+ }
+ model.put( FIELD_SET_EXCEPTIONS, setExceptions );
+
+ return model;
+ }
+
+ /**
* type object:
* <table border="1">
* <tr><th>Name</th> <th>Type</th> <th>Description</th></tr>
* <tr><td>name</td><td>String</td><td>the name of the type</td></tr>
- * <tr><td>type</td><td>String</td><td>The type of the UNO type (simple, enum or interface)</td></tr>
+ * <tr><td>type</td><td>String</td><td>The type of the UNO type (simple or interface)</td></tr>
* <tr><td>nested_levels</td><td>Integer</td><td>the number of nested sequences in the type</td></tr>
- * <tr><td>TODO name</td><td>type</td><td>description</td></tr>
* </table>
*
* @param pType the UNO type for which to get a model.
@@ -435,17 +470,11 @@ public class TypeManager {
nestedLevels ++;
testedType = xIndDescr.getReferencedType();
}
- String type = "simple";
- switch ( testedType.getTypeClass().getValue() ) {
- case TypeClass.ENUM_value:
- type = "enum";
- break;
- case TypeClass.INTERFACE_value:
- type = "interface";
- break;
- default:
- break;
+ String type = UNO_TYPE_CLASS_SIMPLE;
+ if ( testedType.getTypeClass().equals( TypeClass.INTERFACE ) ) {
+ type = UNO_TYPE_CLASS_INTERFACE;
}
+
model.put( UNO_TYPE_CLASS, type );
model.put( UNO_NESTED_LEVELS, Integer.valueOf( nestedLevels) );