1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "osl/thread.hxx"
22 #include "codemaker/commonjava.hxx"
23 #include "codemaker/commoncpp.hxx"
24 #include "codemaker/generatedtypeset.hxx"
25 #include "codemaker/global.hxx"
26 #include "unoidl/unoidl.hxx"
28 #include "skeletoncommon.hxx"
33 using namespace ::codemaker::cpp
;
35 namespace skeletonmaker
{
37 void printLicenseHeader(std::ostream
& o
, rtl::OString
const & filename
)
41 index
= filename
.lastIndexOf('/');
43 index
= filename
.lastIndexOf('\\');
45 OString
shortfilename(filename
);
47 shortfilename
= filename
.copy(index
+1);
49 o
<< "/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n"
51 " * This file is part of the LibreOffice project.\n"
53 " * This Source Code Form is subject to the terms of the Mozilla Public\n"
54 " * License, v. 2.0. If a copy of the MPL was not distributed with this\n"
55 " * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n"
59 bool getOutputStream(ProgramOptions
const & options
,
60 OString
const & extension
,
61 std::ostream
** ppOutputStream
,
62 OString
& targetSourceFileName
,
63 OString
& tmpSourceFileName
)
65 bool bStandardout
= false;
66 if ( options
.outputpath
.equals("stdout") )
69 *ppOutputStream
= &std::cout
;
73 targetSourceFileName
= createFileNameFromType(
74 options
.outputpath
, options
.implname
.replace('.','/'), extension
);
76 OString tmpDir
= getTempDir(targetSourceFileName
);
78 file
.createTempFile(tmpDir
);
82 throw CannotDumpException(
83 "cannot open " + b2u(targetSourceFileName
) + " for writing");
85 tmpSourceFileName
= file
.getName();
88 *ppOutputStream
= new std::ofstream(tmpSourceFileName
.getStr(),
89 std::ios_base::binary
);
94 bool containsAttribute(AttributeInfo
& attributes
, OUString
const & attrname
)
96 for ( AttributeInfo::const_iterator
i(attributes
.begin());
97 i
!= attributes
.end(); ++i
) {
98 if ( (*i
).name
== attrname
) {
105 // collect attributes including inherited attributes
106 void checkAttributes(rtl::Reference
< TypeManager
> const & manager
,
107 OUString
const & name
,
108 AttributeInfo
& attributes
,
109 std::set
< OUString
>& propinterfaces
)
111 if ( name
== "com.sun.star.beans.XPropertySet" ||
112 name
== "com.sun.star.beans.XFastPropertySet" ||
113 name
== "com.sun.star.beans.XPropertyAccess" )
115 propinterfaces
.insert(name
);
117 rtl::Reference
< unoidl::Entity
> ent
;
118 switch (manager
->getSort(name
, &ent
)) {
119 case codemaker::UnoType::Sort::Interface
:
121 rtl::Reference
< unoidl::InterfaceTypeEntity
> ent2(
122 dynamic_cast< unoidl::InterfaceTypeEntity
* >(ent
.get()));
124 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
125 ent2
->getDirectMandatoryBases().begin());
126 i
!= ent2
->getDirectMandatoryBases().end(); ++i
)
128 checkAttributes(manager
, i
->name
, attributes
, propinterfaces
);
130 for (std::vector
< unoidl::InterfaceTypeEntity::Attribute
>::
131 const_iterator
i(ent2
->getDirectAttributes().begin());
132 i
!= ent2
->getDirectAttributes().end(); ++i
)
134 if (!containsAttribute(attributes
, i
->name
)) {
135 attributes
.emplace_back(
137 (unoidl::AccumulationBasedServiceEntity::Property::
140 ? (unoidl::AccumulationBasedServiceEntity::
141 Property::ATTRIBUTE_BOUND
)
144 ? (unoidl::AccumulationBasedServiceEntity::
145 Property::ATTRIBUTE_READ_ONLY
)
147 std::vector
< OUString
>());
152 case codemaker::UnoType::Sort::AccumulationBasedService
:
154 rtl::Reference
< unoidl::AccumulationBasedServiceEntity
> ent2(
155 dynamic_cast< unoidl::AccumulationBasedServiceEntity
* >(
158 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
159 ent2
->getDirectMandatoryBaseServices().begin());
160 i
!= ent2
->getDirectMandatoryBaseServices().end(); ++i
)
162 checkAttributes(manager
, i
->name
, attributes
, propinterfaces
);
164 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
165 ent2
->getDirectMandatoryBaseInterfaces().begin());
166 i
!= ent2
->getDirectMandatoryBaseInterfaces().end(); ++i
)
168 checkAttributes(manager
, i
->name
, attributes
, propinterfaces
);
171 unoidl::AccumulationBasedServiceEntity::Property
>::
172 const_iterator
i(ent2
->getDirectProperties().begin());
173 i
!= ent2
->getDirectProperties().end(); ++i
)
175 if (!containsAttribute(attributes
, i
->name
)) {
176 attributes
.push_back(*i
);
182 throw CannotDumpException(
183 "unexpected entity \"" + name
184 + "\" in call to skeletonmaker::checkAttributes");
188 void checkType(rtl::Reference
< TypeManager
> const & manager
,
189 OUString
const & name
,
190 std::set
< OUString
>& interfaceTypes
,
191 std::set
< OUString
>& serviceTypes
,
192 AttributeInfo
& properties
)
194 rtl::Reference
< unoidl::Entity
> ent
;
195 switch (manager
->getSort(name
, &ent
)) {
196 case codemaker::UnoType::Sort::Interface
:
197 // com.sun.star.lang.XComponent should be also not in the list
198 // but it will be used for checking the impl helper and will be
199 // removed later if necessary.
200 if ( name
== "com.sun.star.lang.XTypeProvider" ||
201 name
== "com.sun.star.uno.XWeak" )
203 if (interfaceTypes
.find(name
) == interfaceTypes
.end()) {
204 interfaceTypes
.insert(name
);
207 case codemaker::UnoType::Sort::SingleInterfaceBasedService
:
208 if (serviceTypes
.find(name
) == serviceTypes
.end()) {
209 serviceTypes
.insert(name
);
210 rtl::Reference
< unoidl::SingleInterfaceBasedServiceEntity
> ent2(
211 dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity
* >(
214 if (interfaceTypes
.find(ent2
->getBase()) == interfaceTypes
.end()) {
215 interfaceTypes
.insert(ent2
->getBase());
216 // check if constructors are specified, if yes automatically
217 // support of XInitialization. We will take care of the default
218 // constructor because in this case XInitialization is not
220 if (ent2
->getConstructors().size() > 1 ||
221 (ent2
->getConstructors().size() == 1 &&
222 !ent2
->getConstructors()[0].defaultConstructor
))
224 OUString
s("com.sun.star.lang.XInitialization");
225 if (interfaceTypes
.find(s
) == interfaceTypes
.end())
226 interfaceTypes
.insert(s
);
231 case codemaker::UnoType::Sort::AccumulationBasedService
:
232 if ( serviceTypes
.find(name
) == serviceTypes
.end() ) {
233 serviceTypes
.insert(name
);
234 rtl::Reference
< unoidl::AccumulationBasedServiceEntity
> ent2(
235 dynamic_cast< unoidl::AccumulationBasedServiceEntity
* >(
238 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
239 ent2
->getDirectMandatoryBaseServices().begin());
240 i
!= ent2
->getDirectMandatoryBaseServices().end(); ++i
)
243 manager
, i
->name
, interfaceTypes
, serviceTypes
, properties
);
245 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
246 ent2
->getDirectMandatoryBaseInterfaces().begin());
247 i
!= ent2
->getDirectMandatoryBaseInterfaces().end(); ++i
)
250 manager
, i
->name
, interfaceTypes
, serviceTypes
, properties
);
253 unoidl::AccumulationBasedServiceEntity::Property
>::
254 const_iterator
i(ent2
->getDirectProperties().begin());
255 i
!= ent2
->getDirectProperties().end(); ++i
)
257 properties
.push_back(*i
);
262 throw CannotDumpException(
263 "unexpected entity \"" + name
264 + "\" in call to skeletonmaker::checkType");
268 void checkDefaultInterfaces(
269 std::set
< OUString
>& interfaces
,
270 const std::set
< OUString
>& services
,
271 const OUString
& propertyhelper
)
273 if ( services
.empty() ) {
274 interfaces
.erase("com.sun.star.lang.XServiceInfo");
276 if (interfaces
.find("com.sun.star.lang.XServiceInfo") == interfaces
.end())
277 interfaces
.insert("com.sun.star.lang.XServiceInfo");
280 if ( propertyhelper
== "_" ) {
281 interfaces
.erase("com.sun.star.beans.XPropertySet");
282 interfaces
.erase("com.sun.star.beans.XFastPropertySet");
283 interfaces
.erase("com.sun.star.beans.XPropertyAccess");
287 bool checkServiceProperties(rtl::Reference
< TypeManager
> const & manager
,
288 OUString
const & name
)
290 rtl::Reference
< unoidl::Entity
> ent
;
291 if (manager
->getSort(name
, &ent
)
292 == codemaker::UnoType::Sort::AccumulationBasedService
)
294 rtl::Reference
< unoidl::AccumulationBasedServiceEntity
> ent2(
295 dynamic_cast< unoidl::AccumulationBasedServiceEntity
* >(
298 if (!ent2
->getDirectProperties().empty()) {
301 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
302 ent2
->getDirectMandatoryBaseServices().begin());
303 i
!= ent2
->getDirectMandatoryBaseServices().end(); ++i
)
305 if (checkServiceProperties(manager
, i
->name
)) {
314 OUString
checkPropertyHelper(
315 ProgramOptions
const & options
,
316 rtl::Reference
< TypeManager
> const & manager
,
317 const std::set
< OUString
>& services
,
318 const std::set
< OUString
>& interfaces
,
319 AttributeInfo
& attributes
,
320 std::set
< OUString
>& propinterfaces
)
322 std::set
< OUString
>::const_iterator iter
;
323 std::set
< OUString
>::const_iterator end
;
325 if ( !services
.empty() ) {
326 iter
= services
.begin();
327 end
= services
.end();
329 iter
= interfaces
.begin();
330 end
= interfaces
.end();
333 bool oldStyleWithProperties
= false;
334 while ( iter
!= end
) {
335 rtl::Reference
< unoidl::Entity
> ent
;
336 codemaker::UnoType::Sort sort
= manager
->getSort(*iter
, &ent
);
337 if ( !services
.empty() ) {
338 if (options
.supportpropertysetmixin
340 == codemaker::UnoType::Sort::SingleInterfaceBasedService
))
342 rtl::Reference
< unoidl::SingleInterfaceBasedServiceEntity
>
345 unoidl::SingleInterfaceBasedServiceEntity
* >(
349 manager
, ent2
->getBase(), attributes
, propinterfaces
);
350 if (!(attributes
.empty() || propinterfaces
.empty())) {
351 return ent2
->getBase();
354 oldStyleWithProperties
= checkServiceProperties(manager
, *iter
);
357 checkAttributes(manager
, *iter
, attributes
, propinterfaces
);
358 if (!(attributes
.empty() || propinterfaces
.empty())) {
365 return oldStyleWithProperties
? OUString("_") : OUString();
368 bool checkXComponentSupport(
369 rtl::Reference
< TypeManager
> const & manager
, OUString
const & name
)
371 assert(manager
.is());
372 if (name
== "com.sun.star.lang.XComponent") {
375 rtl::Reference
< unoidl::Entity
> ent
;
376 codemaker::UnoType::Sort sort
= manager
->getSort(name
, &ent
);
377 if (sort
!= codemaker::UnoType::Sort::Interface
) {
378 throw CannotDumpException(
379 "unexpected entity \"" + name
380 + "\" in call to skeletonmaker::checkXComponentSupport");
382 rtl::Reference
< unoidl::InterfaceTypeEntity
> ent2(
383 dynamic_cast< unoidl::InterfaceTypeEntity
* >(ent
.get()));
385 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
386 ent2
->getDirectMandatoryBases().begin());
387 i
!= ent2
->getDirectMandatoryBases().end(); ++i
)
389 if (checkXComponentSupport(manager
, i
->name
)) {
397 // if XComponent is directly specified, return true and remove it from the
398 // supported interfaces list
399 bool checkXComponentSupport(rtl::Reference
< TypeManager
> const & manager
,
400 std::set
< OUString
>& interfaces
)
402 if ( interfaces
.empty() )
405 std::set
< OUString
>::const_iterator iter
= interfaces
.begin();
406 while ( iter
!= interfaces
.end() ) {
407 if ( *iter
== "com.sun.star.lang.XComponent" ) {
408 interfaces
.erase("com.sun.star.lang.XComponent");
411 if ( checkXComponentSupport(manager
, *iter
) )
419 unoidl::AccumulationBasedServiceEntity::Property::Attributes
420 checkAdditionalPropertyFlags(
421 unoidl::InterfaceTypeEntity::Attribute
const & attribute
)
424 bool getterSupportsUnknown
= false;
425 for (std::vector
< OUString
>::const_iterator
i(
426 attribute
.getExceptions
.begin());
427 i
!= attribute
.getExceptions
.end(); ++i
)
429 if (*i
== "com.sun.star.beans.UnknownPropertyException") {
430 getterSupportsUnknown
= true;
433 for (std::vector
< OUString
>::const_iterator
i(
434 attribute
.setExceptions
.begin());
435 i
!= attribute
.setExceptions
.end(); ++i
)
437 if (*i
== "com.sun.star.beans.PropertyVetoException") {
438 flags
|= unoidl::AccumulationBasedServiceEntity::Property::
439 ATTRIBUTE_CONSTRAINED
;
440 } else if (getterSupportsUnknown
441 && *i
== "com.sun.star.beans.UnknownPropertyException")
443 flags
|= unoidl::AccumulationBasedServiceEntity::Property::
447 return unoidl::AccumulationBasedServiceEntity::Property::Attributes(flags
);
450 // This function checks if the specified types for parameters and return
451 // types are allowed add-in types, for more info see the com.sun.star.sheet.AddIn
452 // service description
453 bool checkAddinType(rtl::Reference
< TypeManager
> const & manager
,
454 OUString
const & type
, bool & bLastAny
,
455 bool & bHasXPropertySet
, bool bIsReturn
)
457 assert(manager
.is());
459 codemaker::UnoType::Sort sort
= manager
->decompose(
460 type
, true, nullptr, &rank
, nullptr, nullptr);
462 if ( sort
== codemaker::UnoType::Sort::Long
||
463 sort
== codemaker::UnoType::Sort::Double
||
464 sort
== codemaker::UnoType::Sort::String
)
466 if ( rank
== 0 || rank
==2 )
469 if ( sort
== codemaker::UnoType::Sort::Any
)
481 if ( sort
== codemaker::UnoType::Sort::Interface
)
483 if ( bIsReturn
&& type
== "com.sun.star.sheet.XVolatileResult" )
485 if ( !bIsReturn
&& type
== "com.sun.star.table.XCellRange" )
487 if ( !bIsReturn
&& type
== "com.sun.star.beans.XPropertySet" )
489 if ( bHasXPropertySet
) {
492 bHasXPropertySet
= true;
500 void checkAddInTypes(
501 rtl::Reference
< TypeManager
> const & manager
, OUString
const & name
,
502 rtl::Reference
< unoidl::InterfaceTypeEntity
> const & entity
)
505 bool bLastAny
= false;
506 bool bHasXPropertySet
= false;
507 for (std::vector
< unoidl::InterfaceTypeEntity::Method
>::const_iterator
i(
508 entity
->getDirectMethods().begin());
509 i
!= entity
->getDirectMethods().end(); ++i
)
511 if ( !checkAddinType(
512 manager
, i
->returnType
, bLastAny
, bHasXPropertySet
, true) )
514 throw CannotDumpException(
515 "the return type of the calc add-in function '" + name
517 + "' is invalid. Please check your IDL definition.");
520 bHasXPropertySet
= false;
521 for (std::vector
< unoidl::InterfaceTypeEntity::Method::Parameter
>::
522 const_iterator
j(i
->parameters
.begin());
523 j
!= i
->parameters
.end(); ++j
)
526 if ( !checkAddinType(manager
, j
->type
,
527 bLastAny
, bHasXPropertySet
, false) ||
530 throw CannotDumpException(
531 "the type of the " + j
->name
532 + " parameter of the calc add-in function '" + name
533 + ":" + i
->name
+ "' is invalid."
536 " The type 'sequence<any>' is allowed as last"
541 " The type 'XPropertySet' is allowed only once.")
543 + " Please check your IDL definition.");
549 void generateFunctionParameterMap(std::ostream
& o
,
550 ProgramOptions
const & options
,
551 rtl::Reference
< TypeManager
> const & manager
,
552 OUString
const & name
,
553 ::codemaker::GeneratedTypeSet
& generated
,
556 if ( name
== "com.sun.star.uno.XInterface" ||
557 name
== "com.sun.star.lang.XLocalizable" ||
558 name
== "com.sun.star.lang.XServiceInfo" ||
559 // the next three checks becomes obsolete when configuration is used
560 name
== "com.sun.star.sheet.XAddIn" ||
561 name
== "com.sun.star.sheet.XCompatibilityNames" ||
562 name
== "com.sun.star.lang.XServiceName" )
567 rtl::Reference
< unoidl::Entity
> ent
;
568 codemaker::UnoType::Sort sort
= manager
->getSort(name
, &ent
);
569 if (sort
!= codemaker::UnoType::Sort::Interface
) {
570 throw CannotDumpException(
571 "unexpected entity \"" + name
572 + "\" in call to skeletonmaker::generateFunctionParameterMap");
574 rtl::Reference
< unoidl::InterfaceTypeEntity
> ent2(
575 dynamic_cast< unoidl::InterfaceTypeEntity
* >(ent
.get()));
578 // check if the specified add-in functions supports valid types
579 checkAddInTypes(manager
, name
, ent2
);
581 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
582 ent2
->getDirectMandatoryBases().begin());
583 i
!= ent2
->getDirectMandatoryBases().end(); ++i
)
585 generateFunctionParameterMap(
586 o
, options
, manager
, i
->name
, generated
, bFirst
);
589 if ( generated
.contains(u2b(name
)) )
592 generated
.add(u2b(name
));
594 for (std::vector
< unoidl::InterfaceTypeEntity::Method
>::const_iterator
i(
595 ent2
->getDirectMethods().begin());
596 i
!= ent2
->getDirectMethods().end(); ++i
)
599 if (options
.language
== 2) {
600 o
<< " ParamMap fpm;\n";
603 o
<< " java.util.Hashtable< Integer, String > fpm = "
604 "new java.util.Hashtable< Integer, String >();\n";
608 if ( options
.language
== 2 ) {
609 o
<< " fpm = ParamMap();\n";
612 o
<< " fpm = new java.util.Hashtable< "
613 "Integer, String >();\n";
616 std::vector
< unoidl::InterfaceTypeEntity::Method::Parameter
>::size_type
618 for (std::vector
< unoidl::InterfaceTypeEntity::Method::Parameter
>::
619 const_iterator
j(i
->parameters
.begin());
620 j
!= i
->parameters
.end(); ++j
)
622 if ( options
.language
== 2 ) {
624 << "] = ::rtl::OUString(\""
629 o
<< " fpm.put(" << n
<< ", \""
636 if ( options
.language
== 2 ) {
637 o
<< " m_functionMap[::rtl::OUString(\""
638 << i
->name
<< "\")] = fpm;\n\n";
641 o
<< " m_functionMap.put(\"" << i
->name
<< "\", fpm);\n\n";
646 void generateFunctionParameterMap(std::ostream
& o
,
647 ProgramOptions
const & options
,
648 rtl::Reference
< TypeManager
> const & manager
,
649 const std::set
< OUString
>& interfaces
)
651 ::codemaker::GeneratedTypeSet generated
;
653 std::set
< OUString
>::const_iterator iter
= interfaces
.begin();
654 while ( iter
!= interfaces
.end() ) {
655 generateFunctionParameterMap(o
, options
, manager
, *iter
, generated
, bFirst
);
662 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */