bump product version to 5.0.4.1
[LibreOffice.git] / unodevtools / source / skeletonmaker / skeletoncommon.cxx
blob3569638d3b2a5a6ead19374e3f5e15bece72dd80
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 = -1;
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_TYPE:
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.push_back(
136 unoidl::AccumulationBasedServiceEntity::Property(
137 i->name,
138 i->type,
139 (unoidl::AccumulationBasedServiceEntity::Property::
140 Attributes(
141 ((i->bound
142 ? (unoidl::AccumulationBasedServiceEntity::
143 Property::ATTRIBUTE_BOUND)
144 : 0)
145 | (i->readOnly
146 ? (unoidl::AccumulationBasedServiceEntity::
147 Property::ATTRIBUTE_READ_ONLY)
148 : 0)))),
149 std::vector< OUString >()));
152 break;
154 case codemaker::UnoType::SORT_ACCUMULATION_BASED_SERVICE:
156 rtl::Reference< unoidl::AccumulationBasedServiceEntity > ent2(
157 dynamic_cast< unoidl::AccumulationBasedServiceEntity * >(
158 ent.get()));
159 assert(ent2.is());
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);
172 for (std::vector<
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);
181 break;
183 default:
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" )
204 return;
205 if (interfaceTypes.find(name) == interfaceTypes.end()) {
206 interfaceTypes.insert(name);
208 break;
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 * >(
214 ent.get()));
215 assert(ent2.is());
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
221 // called.
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);
232 break;
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 * >(
238 ent.get()));
239 assert(ent2.is());
240 for (std::vector< unoidl::AnnotatedReference >::const_iterator i(
241 ent2->getDirectMandatoryBaseServices().begin());
242 i != ent2->getDirectMandatoryBaseServices().end(); ++i)
244 checkType(
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)
251 checkType(
252 manager, i->name, interfaceTypes, serviceTypes, properties);
254 for (std::vector<
255 unoidl::AccumulationBasedServiceEntity::Property >::
256 const_iterator i(ent2->getDirectProperties().begin());
257 i != ent2->getDirectProperties().end(); ++i)
259 properties.push_back(*i);
262 break;
263 default:
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");
277 } else {
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 * >(
298 ent.get()));
299 assert(ent2.is());
300 if (!ent2->getDirectProperties().empty()) {
301 return true;
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)) {
308 return true;
312 return false;
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();
330 } else {
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
341 && (sort
342 == codemaker::UnoType::SORT_SINGLE_INTERFACE_BASED_SERVICE))
344 rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity >
345 ent2(
346 dynamic_cast<
347 unoidl::SingleInterfaceBasedServiceEntity * >(
348 ent.get()));
349 assert(ent2.is());
350 checkAttributes(
351 manager, ent2->getBase(), attributes, propinterfaces);
352 if (!(attributes.empty() || propinterfaces.empty())) {
353 return ent2->getBase();
355 } else {
356 oldStyleWithProperties = checkServiceProperties(manager, *iter);
358 } else {
359 checkAttributes(manager, *iter, attributes, propinterfaces);
360 if (!(attributes.empty() || propinterfaces.empty())) {
361 return *iter;
364 ++iter;
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") {
375 return true;
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()));
386 assert(ent2.is());
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)) {
392 return true;
395 return false;
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() )
405 return false;
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");
411 return true;
413 if ( checkXComponentSupport(manager, *iter) )
414 return true;
415 ++iter;
418 return false;
421 unoidl::AccumulationBasedServiceEntity::Property::Attributes
422 checkAdditionalPropertyFlags(
423 unoidl::InterfaceTypeEntity::Attribute const & attribute)
425 int flags = 0;
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::
446 ATTRIBUTE_OPTIONAL;
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());
460 sal_Int32 rank;
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 )
469 return true;
471 if ( sort == codemaker::UnoType::SORT_ANY )
473 if ( rank <= 2 ) {
474 if ( rank ==1 ) {
475 if ( bIsReturn )
476 return false;
477 bLastAny = true;
480 return true;
483 if ( sort == codemaker::UnoType::SORT_INTERFACE_TYPE )
485 if ( bIsReturn && type == "com.sun.star.sheet.XVolatileResult" )
486 return true;
487 if ( !bIsReturn && type == "com.sun.star.table.XCellRange" )
488 return true;
489 if ( !bIsReturn && type == "com.sun.star.beans.XPropertySet" )
491 if ( bHasXPropertySet ) {
492 return false;
493 } else {
494 bHasXPropertySet = true;
495 return true;
499 return false;
502 void checkAddInTypes(
503 rtl::Reference< TypeManager > const & manager, OUString const & name,
504 rtl::Reference< unoidl::InterfaceTypeEntity > const & entity)
506 assert(entity.is());
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
518 + ":" + i->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)
527 bLastAny = false;
528 if ( !checkAddinType(manager, j->type,
529 bLastAny, bHasXPropertySet, false) ||
530 bLastAny )
532 throw CannotDumpException(
533 "the type of the " + j->name
534 + " parameter of the calc add-in function '" + name
535 + ":" + i->name + "' is invalid."
536 + (bLastAny
537 ? OUString(
538 " The type 'sequence<any>' is allowed as last"
539 " parameter only.")
540 : OUString())
541 + (bHasXPropertySet
542 ? OUString(
543 " The type 'XPropertySet' is allowed only once.")
544 : OUString())
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,
556 bool bFirst)
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" )
566 return;
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()));
578 assert(ent2.is());
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)) )
592 return;
593 else
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)
600 if ( bFirst ) {
601 if (options.language == 2) {
602 o << " ParamMap fpm;\n";
604 else {
605 o << " java.util.Hashtable< Integer, String > fpm = "
606 "new java.util.Hashtable< Integer, String >();\n";
608 bFirst = false;
609 } else
610 if ( options.language == 2 ) {
611 o << " fpm = ParamMap();\n";
613 else {
614 o << " fpm = new java.util.Hashtable< "
615 "Integer, String >();\n";
618 std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >::size_type
619 n = 0;
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 ) {
625 o << " fpm[" << n
626 << "] = ::rtl::OUString(\""
627 << j->name
628 << "\");\n";
630 else {
631 o << " fpm.put(" << n << ", \""
632 << j->name
633 << "\");\n";
635 ++n;
638 if ( options.language == 2 ) {
639 o << " m_functionMap[::rtl::OUString(\""
640 << i->name << "\")] = fpm;\n\n";
642 else {
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;
654 bool bFirst = true;
655 std::set< OUString >::const_iterator iter = interfaces.begin();
656 while ( iter != interfaces.end() ) {
657 generateFunctionParameterMap(o, options, manager, *iter, generated, bFirst);
658 ++iter;
664 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */