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_TYPE
:
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
.push_back(
136 unoidl::AccumulationBasedServiceEntity::Property(
139 (unoidl::AccumulationBasedServiceEntity::Property::
142 ? (unoidl::AccumulationBasedServiceEntity::
143 Property::ATTRIBUTE_BOUND
)
146 ? (unoidl::AccumulationBasedServiceEntity::
147 Property::ATTRIBUTE_READ_ONLY
)
149 std::vector
< OUString
>()));
154 case codemaker::UnoType::SORT_ACCUMULATION_BASED_SERVICE
:
156 rtl::Reference
< unoidl::AccumulationBasedServiceEntity
> ent2(
157 dynamic_cast< unoidl::AccumulationBasedServiceEntity
* >(
160 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
161 ent2
->getDirectMandatoryBaseServices().begin());
162 i
!= ent2
->getDirectMandatoryBaseServices().end(); ++i
)
164 checkAttributes(manager
, i
->name
, attributes
, propinterfaces
);
166 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
167 ent2
->getDirectMandatoryBaseInterfaces().begin());
168 i
!= ent2
->getDirectMandatoryBaseInterfaces().end(); ++i
)
170 checkAttributes(manager
, i
->name
, attributes
, propinterfaces
);
173 unoidl::AccumulationBasedServiceEntity::Property
>::
174 const_iterator
i(ent2
->getDirectProperties().begin());
175 i
!= ent2
->getDirectProperties().end(); ++i
)
177 if (!containsAttribute(attributes
, i
->name
)) {
178 attributes
.push_back(*i
);
184 throw CannotDumpException(
185 "unexpected entity \"" + name
186 + "\" in call to skeletonmaker::checkAttributes");
190 void checkType(rtl::Reference
< TypeManager
> const & manager
,
191 OUString
const & name
,
192 std::set
< OUString
>& interfaceTypes
,
193 std::set
< OUString
>& serviceTypes
,
194 AttributeInfo
& properties
)
196 rtl::Reference
< unoidl::Entity
> ent
;
197 switch (manager
->getSort(name
, &ent
)) {
198 case codemaker::UnoType::SORT_INTERFACE_TYPE
:
199 // com.sun.star.lang.XComponent should be also not in the list
200 // but it will be used for checking the impl helper and will be
201 // removed later if necessary.
202 if ( name
== "com.sun.star.lang.XTypeProvider" ||
203 name
== "com.sun.star.uno.XWeak" )
205 if (interfaceTypes
.find(name
) == interfaceTypes
.end()) {
206 interfaceTypes
.insert(name
);
209 case codemaker::UnoType::SORT_SINGLE_INTERFACE_BASED_SERVICE
:
210 if (serviceTypes
.find(name
) == serviceTypes
.end()) {
211 serviceTypes
.insert(name
);
212 rtl::Reference
< unoidl::SingleInterfaceBasedServiceEntity
> ent2(
213 dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity
* >(
216 if (interfaceTypes
.find(ent2
->getBase()) == interfaceTypes
.end()) {
217 interfaceTypes
.insert(ent2
->getBase());
218 // check if constructors are specified, if yes automatically
219 // support of XInitialization. We will take care of the default
220 // constructor because in this case XInitialization is not
222 if (ent2
->getConstructors().size() > 1 ||
223 (ent2
->getConstructors().size() == 1 &&
224 !ent2
->getConstructors()[0].defaultConstructor
))
226 OUString
s("com.sun.star.lang.XInitialization");
227 if (interfaceTypes
.find(s
) == interfaceTypes
.end())
228 interfaceTypes
.insert(s
);
233 case codemaker::UnoType::SORT_ACCUMULATION_BASED_SERVICE
:
234 if ( serviceTypes
.find(name
) == serviceTypes
.end() ) {
235 serviceTypes
.insert(name
);
236 rtl::Reference
< unoidl::AccumulationBasedServiceEntity
> ent2(
237 dynamic_cast< unoidl::AccumulationBasedServiceEntity
* >(
240 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
241 ent2
->getDirectMandatoryBaseServices().begin());
242 i
!= ent2
->getDirectMandatoryBaseServices().end(); ++i
)
245 manager
, i
->name
, interfaceTypes
, serviceTypes
, properties
);
247 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
248 ent2
->getDirectMandatoryBaseInterfaces().begin());
249 i
!= ent2
->getDirectMandatoryBaseInterfaces().end(); ++i
)
252 manager
, i
->name
, interfaceTypes
, serviceTypes
, properties
);
255 unoidl::AccumulationBasedServiceEntity::Property
>::
256 const_iterator
i(ent2
->getDirectProperties().begin());
257 i
!= ent2
->getDirectProperties().end(); ++i
)
259 properties
.push_back(*i
);
264 throw CannotDumpException(
265 "unexpected entity \"" + name
266 + "\" in call to skeletonmaker::checkType");
270 void checkDefaultInterfaces(
271 std::set
< OUString
>& interfaces
,
272 const std::set
< OUString
>& services
,
273 const OUString
& propertyhelper
)
275 if ( services
.empty() ) {
276 interfaces
.erase("com.sun.star.lang.XServiceInfo");
278 if (interfaces
.find("com.sun.star.lang.XServiceInfo") == interfaces
.end())
279 interfaces
.insert("com.sun.star.lang.XServiceInfo");
282 if ( propertyhelper
== "_" ) {
283 interfaces
.erase("com.sun.star.beans.XPropertySet");
284 interfaces
.erase("com.sun.star.beans.XFastPropertySet");
285 interfaces
.erase("com.sun.star.beans.XPropertyAccess");
289 bool checkServiceProperties(rtl::Reference
< TypeManager
> const & manager
,
290 OUString
const & name
)
292 rtl::Reference
< unoidl::Entity
> ent
;
293 if (manager
->getSort(name
, &ent
)
294 == codemaker::UnoType::SORT_ACCUMULATION_BASED_SERVICE
)
296 rtl::Reference
< unoidl::AccumulationBasedServiceEntity
> ent2(
297 dynamic_cast< unoidl::AccumulationBasedServiceEntity
* >(
300 if (!ent2
->getDirectProperties().empty()) {
303 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
304 ent2
->getDirectMandatoryBaseServices().begin());
305 i
!= ent2
->getDirectMandatoryBaseServices().end(); ++i
)
307 if (checkServiceProperties(manager
, i
->name
)) {
316 OUString
checkPropertyHelper(
317 ProgramOptions
const & options
,
318 rtl::Reference
< TypeManager
> const & manager
,
319 const std::set
< OUString
>& services
,
320 const std::set
< OUString
>& interfaces
,
321 AttributeInfo
& attributes
,
322 std::set
< OUString
>& propinterfaces
)
324 std::set
< OUString
>::const_iterator iter
;
325 std::set
< OUString
>::const_iterator end
;
327 if ( !services
.empty() ) {
328 iter
= services
.begin();
329 end
= services
.end();
331 iter
= interfaces
.begin();
332 end
= interfaces
.end();
335 bool oldStyleWithProperties
= false;
336 while ( iter
!= end
) {
337 rtl::Reference
< unoidl::Entity
> ent
;
338 codemaker::UnoType::Sort sort
= manager
->getSort(*iter
, &ent
);
339 if ( !services
.empty() ) {
340 if (options
.supportpropertysetmixin
342 == codemaker::UnoType::SORT_SINGLE_INTERFACE_BASED_SERVICE
))
344 rtl::Reference
< unoidl::SingleInterfaceBasedServiceEntity
>
347 unoidl::SingleInterfaceBasedServiceEntity
* >(
351 manager
, ent2
->getBase(), attributes
, propinterfaces
);
352 if (!(attributes
.empty() || propinterfaces
.empty())) {
353 return ent2
->getBase();
356 oldStyleWithProperties
= checkServiceProperties(manager
, *iter
);
359 checkAttributes(manager
, *iter
, attributes
, propinterfaces
);
360 if (!(attributes
.empty() || propinterfaces
.empty())) {
367 return oldStyleWithProperties
? OUString("_") : OUString();
370 bool checkXComponentSupport(
371 rtl::Reference
< TypeManager
> const & manager
, OUString
const & name
)
373 assert(manager
.is());
374 if (name
== "com.sun.star.lang.XComponent") {
377 rtl::Reference
< unoidl::Entity
> ent
;
378 codemaker::UnoType::Sort sort
= manager
->getSort(name
, &ent
);
379 if (sort
!= codemaker::UnoType::SORT_INTERFACE_TYPE
) {
380 throw CannotDumpException(
381 "unexpected entity \"" + name
382 + "\" in call to skeletonmaker::checkXComponentSupport");
384 rtl::Reference
< unoidl::InterfaceTypeEntity
> ent2(
385 dynamic_cast< unoidl::InterfaceTypeEntity
* >(ent
.get()));
387 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
388 ent2
->getDirectMandatoryBases().begin());
389 i
!= ent2
->getDirectMandatoryBases().end(); ++i
)
391 if (checkXComponentSupport(manager
, i
->name
)) {
399 // if XComponent is directly specified, return true and remove it from the
400 // supported interfaces list
401 bool checkXComponentSupport(rtl::Reference
< TypeManager
> const & manager
,
402 std::set
< OUString
>& interfaces
)
404 if ( interfaces
.empty() )
407 std::set
< OUString
>::const_iterator iter
= interfaces
.begin();
408 while ( iter
!= interfaces
.end() ) {
409 if ( *iter
== "com.sun.star.lang.XComponent" ) {
410 interfaces
.erase("com.sun.star.lang.XComponent");
413 if ( checkXComponentSupport(manager
, *iter
) )
421 unoidl::AccumulationBasedServiceEntity::Property::Attributes
422 checkAdditionalPropertyFlags(
423 unoidl::InterfaceTypeEntity::Attribute
const & attribute
)
426 bool getterSupportsUnknown
= false;
427 for (std::vector
< OUString
>::const_iterator
i(
428 attribute
.getExceptions
.begin());
429 i
!= attribute
.getExceptions
.end(); ++i
)
431 if (*i
== "com.sun.star.beans.UnknownPropertyException") {
432 getterSupportsUnknown
= true;
435 for (std::vector
< OUString
>::const_iterator
i(
436 attribute
.setExceptions
.begin());
437 i
!= attribute
.setExceptions
.end(); ++i
)
439 if (*i
== "com.sun.star.beans.PropertyVetoException") {
440 flags
|= unoidl::AccumulationBasedServiceEntity::Property::
441 ATTRIBUTE_CONSTRAINED
;
442 } else if (getterSupportsUnknown
443 && *i
== "com.sun.star.beans.UnknownPropertyException")
445 flags
|= unoidl::AccumulationBasedServiceEntity::Property::
449 return unoidl::AccumulationBasedServiceEntity::Property::Attributes(flags
);
452 // This function checks if the specified types for parameters and return
453 // types are allowed add-in types, for more info see the com.sun.star.sheet.AddIn
454 // service description
455 bool checkAddinType(rtl::Reference
< TypeManager
> const & manager
,
456 OUString
const & type
, bool & bLastAny
,
457 bool & bHasXPropertySet
, bool bIsReturn
)
459 assert(manager
.is());
461 codemaker::UnoType::Sort sort
= manager
->decompose(
462 type
, true, 0, &rank
, 0, 0);
464 if ( sort
== codemaker::UnoType::SORT_LONG
||
465 sort
== codemaker::UnoType::SORT_DOUBLE
||
466 sort
== codemaker::UnoType::SORT_STRING
)
468 if ( rank
== 0 || rank
==2 )
471 if ( sort
== codemaker::UnoType::SORT_ANY
)
483 if ( sort
== codemaker::UnoType::SORT_INTERFACE_TYPE
)
485 if ( bIsReturn
&& type
== "com.sun.star.sheet.XVolatileResult" )
487 if ( !bIsReturn
&& type
== "com.sun.star.table.XCellRange" )
489 if ( !bIsReturn
&& type
== "com.sun.star.beans.XPropertySet" )
491 if ( bHasXPropertySet
) {
494 bHasXPropertySet
= true;
502 void checkAddInTypes(
503 rtl::Reference
< TypeManager
> const & manager
, OUString
const & name
,
504 rtl::Reference
< unoidl::InterfaceTypeEntity
> const & entity
)
507 bool bLastAny
= false;
508 bool bHasXPropertySet
= false;
509 for (std::vector
< unoidl::InterfaceTypeEntity::Method
>::const_iterator
i(
510 entity
->getDirectMethods().begin());
511 i
!= entity
->getDirectMethods().end(); ++i
)
513 if ( !checkAddinType(
514 manager
, i
->returnType
, bLastAny
, bHasXPropertySet
, true) )
516 throw CannotDumpException(
517 "the return type of the calc add-in function '" + name
519 + "' is invalid. Please check your IDL definition.");
522 bHasXPropertySet
= false;
523 for (std::vector
< unoidl::InterfaceTypeEntity::Method::Parameter
>::
524 const_iterator
j(i
->parameters
.begin());
525 j
!= i
->parameters
.end(); ++j
)
528 if ( !checkAddinType(manager
, j
->type
,
529 bLastAny
, bHasXPropertySet
, false) ||
532 throw CannotDumpException(
533 "the type of the " + j
->name
534 + " parameter of the calc add-in function '" + name
535 + ":" + i
->name
+ "' is invalid."
538 " The type 'sequence<any>' is allowed as last"
543 " The type 'XPropertySet' is allowed only once.")
545 + " Please check your IDL definition.");
551 void generateFunctionParameterMap(std::ostream
& o
,
552 ProgramOptions
const & options
,
553 rtl::Reference
< TypeManager
> const & manager
,
554 OUString
const & name
,
555 ::codemaker::GeneratedTypeSet
& generated
,
558 if ( name
== "com.sun.star.uno.XInterface" ||
559 name
== "com.sun.star.lang.XLocalizable" ||
560 name
== "com.sun.star.lang.XServiceInfo" ||
561 // the next three checks becomes obsolete when configuration is used
562 name
== "com.sun.star.sheet.XAddIn" ||
563 name
== "com.sun.star.sheet.XCompatibilityNames" ||
564 name
== "com.sun.star.lang.XServiceName" )
569 rtl::Reference
< unoidl::Entity
> ent
;
570 codemaker::UnoType::Sort sort
= manager
->getSort(name
, &ent
);
571 if (sort
!= codemaker::UnoType::SORT_INTERFACE_TYPE
) {
572 throw CannotDumpException(
573 "unexpected entity \"" + name
574 + "\" in call to skeletonmaker::generateFunctionParameterMap");
576 rtl::Reference
< unoidl::InterfaceTypeEntity
> ent2(
577 dynamic_cast< unoidl::InterfaceTypeEntity
* >(ent
.get()));
580 // check if the specified add-in functions supports valid types
581 checkAddInTypes(manager
, name
, ent2
);
583 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
i(
584 ent2
->getDirectMandatoryBases().begin());
585 i
!= ent2
->getDirectMandatoryBases().end(); ++i
)
587 generateFunctionParameterMap(
588 o
, options
, manager
, i
->name
, generated
, bFirst
);
591 if ( generated
.contains(u2b(name
)) )
594 generated
.add(u2b(name
));
596 for (std::vector
< unoidl::InterfaceTypeEntity::Method
>::const_iterator
i(
597 ent2
->getDirectMethods().begin());
598 i
!= ent2
->getDirectMethods().end(); ++i
)
601 if (options
.language
== 2) {
602 o
<< " ParamMap fpm;\n";
605 o
<< " java.util.Hashtable< Integer, String > fpm = "
606 "new java.util.Hashtable< Integer, String >();\n";
610 if ( options
.language
== 2 ) {
611 o
<< " fpm = ParamMap();\n";
614 o
<< " fpm = new java.util.Hashtable< "
615 "Integer, String >();\n";
618 std::vector
< unoidl::InterfaceTypeEntity::Method::Parameter
>::size_type
620 for (std::vector
< unoidl::InterfaceTypeEntity::Method::Parameter
>::
621 const_iterator
j(i
->parameters
.begin());
622 j
!= i
->parameters
.end(); ++j
)
624 if ( options
.language
== 2 ) {
626 << "] = ::rtl::OUString(\""
631 o
<< " fpm.put(" << n
<< ", \""
638 if ( options
.language
== 2 ) {
639 o
<< " m_functionMap[::rtl::OUString(\""
640 << i
->name
<< "\")] = fpm;\n\n";
643 o
<< " m_functionMap.put(\"" << i
->name
<< "\", fpm);\n\n";
648 void generateFunctionParameterMap(std::ostream
& o
,
649 ProgramOptions
const & options
,
650 rtl::Reference
< TypeManager
> const & manager
,
651 const std::set
< OUString
>& interfaces
)
653 ::codemaker::GeneratedTypeSet generated
;
655 std::set
< OUString
>::const_iterator iter
= interfaces
.begin();
656 while ( iter
!= interfaces
.end() ) {
657 generateFunctionParameterMap(o
, options
, manager
, *iter
, generated
, bFirst
);
664 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */