Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / unodevtools / source / skeletonmaker / skeletoncommon.cxx
blobb0dc9333c687176ec4506cdc6fe0d21943163f15
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
30 #include <cassert>
31 #include <iostream>
33 using namespace ::codemaker::cpp;
35 namespace skeletonmaker {
37 void printLicenseHeader(std::ostream& o, rtl::OString const & filename)
39 sal_Int32 index;
40 #ifdef SAL_UNX
41 index = filename.lastIndexOf('/');
42 #else
43 index = filename.lastIndexOf('\\');
44 #endif
45 OString shortfilename(filename);
46 if ( index != -1 )
47 shortfilename = filename.copy(index+1);
49 o << "/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n"
50 "/*\n"
51 " * This file is part of the LibreOffice project.\n"
52 " *\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"
56 " */\n\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") )
68 bStandardout = true;
69 *ppOutputStream = &std::cout;
70 return bStandardout;
73 targetSourceFileName = createFileNameFromType(
74 options.outputpath, options.implname.replace('.','/'), extension);
76 OString tmpDir = getTempDir(targetSourceFileName);
77 FileStream file;
78 file.createTempFile(tmpDir);
80 if( !file.isValid() )
82 throw CannotDumpException(
83 "cannot open " + b2u(targetSourceFileName) + " for writing");
84 } else {
85 tmpSourceFileName = file.getName();
87 file.close();
88 *ppOutputStream = new std::ofstream(tmpSourceFileName.getStr(),
89 std::ios_base::binary);
91 return bStandardout;
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 ) {
99 return true;
102 return false;
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()));
123 assert(ent2.is());
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(
136 i->name, i->type,
137 (unoidl::AccumulationBasedServiceEntity::Property::
138 Attributes(
139 ((i->bound
140 ? (unoidl::AccumulationBasedServiceEntity::
141 Property::ATTRIBUTE_BOUND)
142 : 0)
143 | (i->readOnly
144 ? (unoidl::AccumulationBasedServiceEntity::
145 Property::ATTRIBUTE_READ_ONLY)
146 : 0)))),
147 std::vector< OUString >());
150 break;
152 case codemaker::UnoType::Sort::AccumulationBasedService:
154 rtl::Reference< unoidl::AccumulationBasedServiceEntity > ent2(
155 dynamic_cast< unoidl::AccumulationBasedServiceEntity * >(
156 ent.get()));
157 assert(ent2.is());
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);
170 for (std::vector<
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);
179 break;
181 default:
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" )
202 return;
203 if (interfaceTypes.find(name) == interfaceTypes.end()) {
204 interfaceTypes.insert(name);
206 break;
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 * >(
212 ent.get()));
213 assert(ent2.is());
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
219 // called.
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);
230 break;
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 * >(
236 ent.get()));
237 assert(ent2.is());
238 for (std::vector< unoidl::AnnotatedReference >::const_iterator i(
239 ent2->getDirectMandatoryBaseServices().begin());
240 i != ent2->getDirectMandatoryBaseServices().end(); ++i)
242 checkType(
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)
249 checkType(
250 manager, i->name, interfaceTypes, serviceTypes, properties);
252 for (std::vector<
253 unoidl::AccumulationBasedServiceEntity::Property >::
254 const_iterator i(ent2->getDirectProperties().begin());
255 i != ent2->getDirectProperties().end(); ++i)
257 properties.push_back(*i);
260 break;
261 default:
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");
275 } else {
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 * >(
296 ent.get()));
297 assert(ent2.is());
298 if (!ent2->getDirectProperties().empty()) {
299 return true;
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)) {
306 return true;
310 return false;
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();
328 } else {
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
339 && (sort
340 == codemaker::UnoType::Sort::SingleInterfaceBasedService))
342 rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity >
343 ent2(
344 dynamic_cast<
345 unoidl::SingleInterfaceBasedServiceEntity * >(
346 ent.get()));
347 assert(ent2.is());
348 checkAttributes(
349 manager, ent2->getBase(), attributes, propinterfaces);
350 if (!(attributes.empty() || propinterfaces.empty())) {
351 return ent2->getBase();
353 } else {
354 oldStyleWithProperties = checkServiceProperties(manager, *iter);
356 } else {
357 checkAttributes(manager, *iter, attributes, propinterfaces);
358 if (!(attributes.empty() || propinterfaces.empty())) {
359 return *iter;
362 ++iter;
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") {
373 return true;
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()));
384 assert(ent2.is());
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)) {
390 return true;
393 return false;
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() )
403 return false;
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");
409 return true;
411 if ( checkXComponentSupport(manager, *iter) )
412 return true;
413 ++iter;
416 return false;
419 unoidl::AccumulationBasedServiceEntity::Property::Attributes
420 checkAdditionalPropertyFlags(
421 unoidl::InterfaceTypeEntity::Attribute const & attribute)
423 int flags = 0;
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::
444 ATTRIBUTE_OPTIONAL;
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());
458 sal_Int32 rank;
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 )
467 return true;
469 if ( sort == codemaker::UnoType::Sort::Any )
471 if ( rank <= 2 ) {
472 if ( rank ==1 ) {
473 if ( bIsReturn )
474 return false;
475 bLastAny = true;
478 return true;
481 if ( sort == codemaker::UnoType::Sort::Interface )
483 if ( bIsReturn && type == "com.sun.star.sheet.XVolatileResult" )
484 return true;
485 if ( !bIsReturn && type == "com.sun.star.table.XCellRange" )
486 return true;
487 if ( !bIsReturn && type == "com.sun.star.beans.XPropertySet" )
489 if ( bHasXPropertySet ) {
490 return false;
491 } else {
492 bHasXPropertySet = true;
493 return true;
497 return false;
500 void checkAddInTypes(
501 rtl::Reference< TypeManager > const & manager, OUString const & name,
502 rtl::Reference< unoidl::InterfaceTypeEntity > const & entity)
504 assert(entity.is());
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
516 + ":" + i->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)
525 bLastAny = false;
526 if ( !checkAddinType(manager, j->type,
527 bLastAny, bHasXPropertySet, false) ||
528 bLastAny )
530 throw CannotDumpException(
531 "the type of the " + j->name
532 + " parameter of the calc add-in function '" + name
533 + ":" + i->name + "' is invalid."
534 + (bLastAny
535 ? OUString(
536 " The type 'sequence<any>' is allowed as last"
537 " parameter only.")
538 : OUString())
539 + (bHasXPropertySet
540 ? OUString(
541 " The type 'XPropertySet' is allowed only once.")
542 : OUString())
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,
554 bool bFirst)
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" )
564 return;
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()));
576 assert(ent2.is());
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)) )
590 return;
591 else
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)
598 if ( bFirst ) {
599 if (options.language == 2) {
600 o << " ParamMap fpm;\n";
602 else {
603 o << " java.util.Hashtable< Integer, String > fpm = "
604 "new java.util.Hashtable< Integer, String >();\n";
606 bFirst = false;
607 } else
608 if ( options.language == 2 ) {
609 o << " fpm = ParamMap();\n";
611 else {
612 o << " fpm = new java.util.Hashtable< "
613 "Integer, String >();\n";
616 std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >::size_type
617 n = 0;
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 ) {
623 o << " fpm[" << n
624 << "] = ::rtl::OUString(\""
625 << j->name
626 << "\");\n";
628 else {
629 o << " fpm.put(" << n << ", \""
630 << j->name
631 << "\");\n";
633 ++n;
636 if ( options.language == 2 ) {
637 o << " m_functionMap[::rtl::OUString(\""
638 << i->name << "\")] = fpm;\n\n";
640 else {
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;
652 bool bFirst = true;
653 std::set< OUString >::const_iterator iter = interfaces.begin();
654 while ( iter != interfaces.end() ) {
655 generateFunctionParameterMap(o, options, manager, *iter, generated, bFirst);
656 ++iter;
662 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */