1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <codemaker/codemaker.hxx>
23 #include <codemaker/commoncpp.hxx>
24 #include <codemaker/global.hxx>
25 
26 #include "skeletoncommon.hxx"
27 #include "skeletoncpp.hxx"
28 
29 #include <algorithm>
30 
31 using namespace ::codemaker::cpp;
32 
33 namespace skeletonmaker { namespace cpp {
34 
printType(std::ostream & o,ProgramOptions const & options,rtl::Reference<TypeManager> const & manager,codemaker::UnoType::Sort sort,OUString const & nucleus,sal_Int32 rank,std::vector<OUString> const & arguments,rtl::Reference<unoidl::Entity> const & entity,short referenceType,bool defaultvalue)35 static void printType(
36     std::ostream & o, ProgramOptions const & options,
37     rtl::Reference< TypeManager > const & manager,
38     codemaker::UnoType::Sort sort, OUString const & nucleus, sal_Int32 rank,
39     std::vector< OUString > const & arguments,
40     rtl::Reference< unoidl::Entity > const & entity, short referenceType,
41     bool defaultvalue)
42 {
43     if (defaultvalue && rank == 0 && sort <= codemaker::UnoType::Sort::Char) {
44         switch (sort) {
45         case codemaker::UnoType::Sort::Boolean:
46             o << "sal_False";
47             return;
48         case codemaker::UnoType::Sort::Char:
49         case codemaker::UnoType::Sort::Byte:
50         case codemaker::UnoType::Sort::Short:
51         case codemaker::UnoType::Sort::UnsignedShort:
52         case codemaker::UnoType::Sort::Long:
53         case codemaker::UnoType::Sort::UnsignedLong:
54         case codemaker::UnoType::Sort::Hyper:
55         case codemaker::UnoType::Sort::UnsignedHyper:
56         case codemaker::UnoType::Sort::Float:
57         case codemaker::UnoType::Sort::Double:
58             o << "0";
59             return;
60         default:
61             break;
62         }
63     }
64 
65     if (defaultvalue && referenceType == 16) {
66         if (sort == codemaker::UnoType::Sort::Enum) {
67             auto pEnumTypeEntity(dynamic_cast<unoidl::EnumTypeEntity *>(entity.get()));
68             assert(pEnumTypeEntity);
69             o << nucleus.copy(nucleus.lastIndexOf('.') + 1) << "_"
70               << pEnumTypeEntity->getMembers()[0].name;
71         }
72         return;
73     }
74     bool bReference = false;
75     if (((sort > codemaker::UnoType::Sort::Char ||
76           rank > 0) && referenceType != 8 &&
77          !(sort == codemaker::UnoType::Sort::Enum && referenceType == 4 && rank == 0)) ||
78         (sort <= codemaker::UnoType::Sort::Char && referenceType == 2))
79     {
80         bReference = true;
81     }
82 
83     if (bReference && referenceType == 4)
84         o << "const ";
85 
86     for (sal_Int32 i = 0; i < rank; ++i) {
87         o << ((options.shortnames) ? "css::uno::Sequence< " :
88               "::com::sun::star::uno::Sequence< ");
89     }
90     if (sort == codemaker::UnoType::Sort::Interface && referenceType > 0) {
91         o << ((options.shortnames) ? "css::uno::Reference< " :
92               "::com::sun::star::uno::Reference< ");
93     }
94 
95     o << scopedCppName(codemaker::cpp::translateUnoToCppType(sort, nucleus),
96                        options.shortnames && referenceType > 0);
97 
98     if (sort == codemaker::UnoType::Sort::Interface && referenceType > 0)
99         o << " >";
100 
101     if (!arguments.empty()) {
102         o << "< ";
103         for (std::vector< OUString >::const_iterator i(arguments.begin());
104              i != arguments.end(); ++i)
105         {
106             if (i != arguments.begin())
107                 o << ", ";
108 
109             printType(o, options, manager, *i, 1);
110         }
111         o << " >";
112     }
113 
114     for (sal_Int32 i = 0; i < rank; ++i)
115         o << " >";
116 
117     if (bReference && referenceType > 1)
118         o << " &";
119 
120     if (referenceType == 8 && (sort > codemaker::UnoType::Sort::Char || rank > 0))
121         o << "()";
122 }
123 
printType(std::ostream & o,ProgramOptions const & options,rtl::Reference<TypeManager> const & manager,OUString const & name,short referenceType,bool defaultvalue)124 void printType(
125     std::ostream & o, ProgramOptions const & options,
126     rtl::Reference< TypeManager > const & manager, OUString const & name,
127     short referenceType, bool defaultvalue)
128 {
129     OUString nucleus;
130     sal_Int32 rank;
131     std::vector< OUString > arguments;
132     rtl::Reference< unoidl::Entity > entity;
133     codemaker::UnoType::Sort sort = manager->decompose(
134         name, true, &nucleus, &rank, &arguments, &entity);
135     printType(
136         o, options, manager, sort, nucleus, rank, arguments, entity,
137         referenceType, defaultvalue);
138 }
139 
printConstructorParameters(std::ostream & o,ProgramOptions const & options,rtl::Reference<TypeManager> const & manager,codemaker::UnoType::Sort sort,rtl::Reference<unoidl::Entity> const & entity,OUString const & name,std::vector<OUString> const & arguments)140 static bool printConstructorParameters(
141     std::ostream & o, ProgramOptions const & options,
142     rtl::Reference< TypeManager > const & manager,
143     codemaker::UnoType::Sort sort,
144     rtl::Reference< unoidl::Entity > const & entity, OUString const & name,
145     std::vector< OUString > const & arguments)
146 {
147     bool previous = false;
148     switch (sort) {
149     case codemaker::UnoType::Sort::PlainStruct:
150         {
151             rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
152                 dynamic_cast< unoidl::PlainStructTypeEntity * >(entity.get()));
153             assert(ent2.is());
154             if (!ent2->getDirectBase().isEmpty()) {
155                 rtl::Reference< unoidl::Entity > baseEnt;
156                 codemaker::UnoType::Sort baseSort = manager->getSort(
157                     ent2->getDirectBase(), &baseEnt);
158                 previous = printConstructorParameters(
159                     o, options, manager, baseSort, baseEnt,
160                     ent2->getDirectBase(), std::vector< OUString >());
161             }
162             for (const auto& rMember : ent2->getDirectMembers())
163             {
164                 if (previous) {
165                     o << ", ";
166                 }
167                 previous = true;
168                 printType(o, options, manager, rMember.type, 4);
169                 o << ' '
170                   << codemaker::cpp::translateUnoToCppIdentifier(
171                       u2b(rMember.name), "param");
172             }
173             break;
174         }
175     case codemaker::UnoType::Sort::PolymorphicStructTemplate:
176         {
177             rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > ent2(
178                 dynamic_cast< unoidl::PolymorphicStructTypeTemplateEntity * >(
179                     entity.get()));
180             assert(ent2.is());
181             for (const auto& rMember : ent2->getMembers())
182             {
183                 if (previous) {
184                     o << ", ";
185                 }
186                 previous = true;
187                 if (rMember.parameterized) {
188                     o << rMember.type;
189                 } else {
190                     printType(o, options, manager, rMember.type, 4);
191                 }
192                 o << ' '
193                   << codemaker::cpp::translateUnoToCppIdentifier(
194                       u2b(rMember.name), "param");
195             }
196             break;
197         }
198     case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
199         {
200             rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > ent2(
201                 dynamic_cast< unoidl::PolymorphicStructTypeTemplateEntity * >(
202                     entity.get()));
203             assert(ent2.is());
204             for (const auto& rMember : ent2->getMembers())
205             {
206                 if (previous) {
207                     o << ", ";
208                 }
209                 previous = true;
210                 if (rMember.parameterized) {
211                     auto j = std::find(ent2->getTypeParameters().begin(),
212                         ent2->getTypeParameters().end(), rMember.type);
213                     if (j != ent2->getTypeParameters().end()) {
214                         o << arguments[j - ent2->getTypeParameters().begin()];
215                     }
216                 } else {
217                     printType(o, options, manager, rMember.type, 4);
218                 }
219                 o << ' '
220                   << codemaker::cpp::translateUnoToCppIdentifier(
221                       u2b(rMember.name), "param");
222             }
223             break;
224         }
225     case codemaker::UnoType::Sort::Exception:
226         {
227             rtl::Reference< unoidl::ExceptionTypeEntity > ent2(
228                 dynamic_cast< unoidl::ExceptionTypeEntity * >(entity.get()));
229             assert(ent2.is());
230             if (!ent2->getDirectBase().isEmpty()) {
231                 rtl::Reference< unoidl::Entity > baseEnt;
232                 codemaker::UnoType::Sort baseSort = manager->getSort(
233                     ent2->getDirectBase(), &baseEnt);
234                 previous = printConstructorParameters(
235                     o, options, manager, baseSort, baseEnt,
236                     ent2->getDirectBase(), std::vector< OUString >());
237             }
238             for (const auto& rMember : ent2->getDirectMembers())
239             {
240                 if (previous) {
241                     o << ", ";
242                 }
243                 previous = true;
244                 printType(o, options, manager, rMember.type, 4);
245                 o << ' '
246                   << codemaker::cpp::translateUnoToCppIdentifier(
247                       u2b(rMember.name), "param");
248             }
249             break;
250         }
251     default:
252         throw CannotDumpException(
253             "unexpected entity \"" + name
254             + "\" in call to skeletonmaker::cpp::printConstructorParameters");
255     }
256     return previous;
257 }
258 
printConstructor(std::ostream & o,ProgramOptions const & options,rtl::Reference<TypeManager> const & manager,codemaker::UnoType::Sort sort,rtl::Reference<unoidl::Entity> const & entity,OUString const & name,std::vector<OUString> const & arguments)259 static void printConstructor(
260     std::ostream & o, ProgramOptions const & options,
261     rtl::Reference< TypeManager > const & manager,
262     codemaker::UnoType::Sort sort,
263     rtl::Reference< unoidl::Entity > const & entity, OUString const & name,
264     std::vector< OUString > const & arguments)
265 {
266     o << "public " << name.copy(name.lastIndexOf('.') + 1) << '(';
267     printConstructorParameters(
268         o, options, manager, sort, entity, name, arguments);
269     o << ");\n";
270 }
271 
printMethodParameters(std::ostream & o,ProgramOptions const & options,rtl::Reference<TypeManager> const & manager,std::vector<unoidl::InterfaceTypeEntity::Method::Parameter> const & parameters,bool withType)272 static void printMethodParameters(
273     std::ostream & o, ProgramOptions const & options,
274     rtl::Reference< TypeManager > const & manager,
275     std::vector< unoidl::InterfaceTypeEntity::Method::Parameter > const &
276         parameters,
277     bool withType)
278 {
279     for (std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >::
280              const_iterator i(parameters.begin());
281          i != parameters.end(); ++i)
282     {
283         if (i != parameters.begin()) {
284             o << ", ";
285         }
286         if (withType) {
287             short referenceType;
288             if (i->direction
289                 == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
290             {
291                 referenceType = 4;
292             } else {
293                 referenceType = 2;
294             }
295             printType(o, options, manager, i->type, referenceType);
296             o << ' ';
297         }
298         o << codemaker::cpp::translateUnoToCppIdentifier(u2b(i->name), "param");
299     }
300 }
301 
printExceptionSpecification(std::ostream & o,ProgramOptions const & options,rtl::Reference<TypeManager> const & manager,std::vector<OUString> const & exceptions)302 static void printExceptionSpecification(
303     std::ostream & o,
304     ProgramOptions const & options,
305     rtl::Reference< TypeManager > const & manager,
306     std::vector< OUString > const & exceptions)
307 {
308     o << ((options.shortnames) ? " throw (css::uno::RuntimeException" :
309           " throw (::com::sun::star::uno::RuntimeException");
310     for (const auto& rException : exceptions)
311     {
312         o << ", ";
313         printType(o, options, manager, rException, 1);
314     }
315     o << ")";
316 }
317 
printSetPropertyMixinBody(std::ostream & o,unoidl::InterfaceTypeEntity::Attribute const & attribute)318 static void printSetPropertyMixinBody(
319     std::ostream & o, unoidl::InterfaceTypeEntity::Attribute const & attribute)
320 {
321     unoidl::AccumulationBasedServiceEntity::Property::Attributes propFlags
322         = checkAdditionalPropertyFlags(attribute);
323 
324     o << "\n{\n";
325 
326     if (attribute.bound)
327         o << "    BoundListeners l;\n";
328 
329     if (propFlags & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_CONSTRAINED) {
330         OString fieldtype = codemaker::convertString(attribute.type);
331 
332         sal_Int32 index = fieldtype.lastIndexOf('<');
333         sal_Int32 nPos=0;
334         bool single = true;
335         bool optional = false;
336         OStringBuffer buffer1(64);
337         OStringBuffer buffer2(64);
338         do
339         {
340             OString s(fieldtype.getToken(0, '<', nPos));
341             OString t = s.copy(s.lastIndexOf('/')+1);
342 
343             if (t == "Optional") {
344                 optional=true;
345                 if (single) {
346                     single=false;
347                     buffer1.append("the_value.IsPresent");
348                     buffer2.append("the_value.Value");
349                 } else {
350                     buffer1.insert(0, t);
351                     buffer1.append(".IsPresent");
352                     buffer2.insert(0, t);
353                     buffer2.append(".Value");
354                 }
355             } else {
356                 if (single) {
357                     single=false;
358                     if (!optional)
359                         buffer1.append("the_value.Value");
360 
361                     buffer2.append("the_value.Value");
362                 } else {
363                     if (!optional) {
364                         buffer1.insert(0, t);
365                         buffer1.append(".Value");
366                     }
367                     buffer2.insert(0, t);
368                     buffer2.append(".Value");
369                 }
370             }
371         } while( nPos <= index );
372 
373         o << "    css::uno::Any v;\n";
374         if (optional) {
375             o << "    if(" << buffer1.makeStringAndClear() << ")\n    {\n        v <<= " << buffer2.makeStringAndClear() << ";\n    }\n";
376         } else {
377             o << "    v <<= " << buffer2.makeStringAndClear() << ";\n\n";
378         }
379 
380         o << "    prepareSet(\n        OUString(\""
381           << attribute.name << "\"),\n        css::uno::Any(), v, ";
382     } else {
383         o << "    prepareSet(\n        OUString(\""
384           << attribute.name << "\"),\n        css::uno::Any(), css::uno::Any(), ";
385     }
386 
387     if (attribute.bound)
388         o << "&l);\n";
389     else
390         o << "0);\n";
391 
392     o << "    {\n        osl::MutexGuard g(m_aMutex);\n        m_"
393       << attribute.name << " = the_value;\n    }\n";
394 
395     if (attribute.bound)
396         o << "    l.notify();\n";
397 
398     o  << "}\n\n";
399 }
400 
printMethods(std::ostream & o,ProgramOptions const & options,rtl::Reference<TypeManager> const & manager,OUString const & name,codemaker::GeneratedTypeSet & generated,OString const & delegate,OString const & classname,OString const & indentation,bool defaultvalue,OUString const & propertyhelper)401 void printMethods(std::ostream & o,
402     ProgramOptions const & options, rtl::Reference< TypeManager > const & manager,
403     OUString const & name, codemaker::GeneratedTypeSet & generated,
404     OString const & delegate, OString const & classname,
405     OString const & indentation, bool defaultvalue,
406     OUString const & propertyhelper)
407 {
408     if (generated.contains(u2b(name)) || name == "com.sun.star.uno.XInterface" ||
409         (defaultvalue &&
410          ( name == "com.sun.star.lang.XComponent" ||
411            name == "com.sun.star.lang.XTypeProvider" ||
412            name == "com.sun.star.uno.XWeak" ) ) )
413     {
414         return;
415     }
416 
417     static OString sd("_");
418     bool body = !delegate.isEmpty();
419     bool defaultbody = delegate == sd;
420 
421     if (body && propertyhelper.getLength() > 1) {
422         if (name == "com.sun.star.beans.XPropertySet") {
423             generated.add(u2b(name));
424             generateXPropertySetBodies(
425                 o, classname, scopedCppName(u2b(propertyhelper)));
426             return;
427         } else if (name == "com.sun.star.beans.XFastPropertySet") {
428             generated.add(u2b(name));
429             generateXFastPropertySetBodies(
430                 o, classname, scopedCppName(u2b(propertyhelper)));
431             return;
432         } else if (name == "com.sun.star.beans.XPropertyAccess") {
433             generated.add(u2b(name));
434             generateXPropertyAccessBodies(
435                 o, classname, scopedCppName(u2b(propertyhelper)));
436             return;
437         }
438     }
439 
440     if (body && options.componenttype == 2) {
441         if (name == "com.sun.star.lang.XServiceName") {
442             o << "// ::com::sun::star::lang::XServiceName:\n"
443                 "OUString SAL_CALL " << classname << "getServiceName() "
444                 "throw (css::uno::RuntimeException)\n{\n    "
445                 "return OUString("
446                 "sADDIN_SERVICENAME);\n}\n";
447             generated.add(u2b(name));
448             return;
449         } else if (name == "com.sun.star.sheet.XAddIn") {
450             generateXAddInBodies(o, classname);
451             generated.add(u2b(name));
452 
453             // special handling of XLocalizable -> parent of XAddIn
454             if (!generated.contains("com.sun.star.lang.XLocalizable")) {
455                 generateXLocalizable(o, classname);
456                 generated.add("com.sun.star.lang.XLocalizable");
457             }
458             return;
459         } else if (name == "com.sun.star.lang.XLocalizable") {
460             generateXLocalizable(o, classname);
461             generated.add(u2b(name));
462             return;
463         } else if (name == "com.sun.star.sheet.XCompatibilityNames") {
464             generateXCompatibilityNamesBodies(o, classname);
465             generated.add(u2b(name));
466             return;
467         }
468     }
469 
470     if (body && options.componenttype == 3) {
471         if (name == "com.sun.star.lang.XInitialization") {
472             generateXInitialization(o, classname);
473             generated.add(u2b(name));
474             return;
475         } else if (name == "com.sun.star.frame.XDispatch") {
476             generateXDispatch(o, classname, options.protocolCmdMap);
477             generated.add(u2b(name));
478             return;
479         } else if (name == "com.sun.star.frame.XDispatchProvider") {
480             generateXDispatchProvider(o, classname, options.protocolCmdMap);
481             generated.add(u2b(name));
482             return;
483         }
484     }
485 
486     generated.add(u2b(name));
487     rtl::Reference< unoidl::Entity > ent;
488     if (manager->getSort(name, &ent) != codemaker::UnoType::Sort::Interface)
489     {
490         throw CannotDumpException(
491             "unexpected entity \"" + name
492             + "\" in call to skeletonmaker::cpp::printMethods");
493     }
494     rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
495         dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()));
496     assert(ent2.is());
497     if (options.all || defaultvalue) {
498         for (const auto& rBase : ent2->getDirectMandatoryBases())
499         {
500             printMethods(
501                 o, options, manager, rBase.name, generated, delegate, classname,
502                 indentation, defaultvalue, propertyhelper);
503         }
504         if (!(ent2->getDirectAttributes().empty()
505               && ent2->getDirectMethods().empty()))
506         {
507             o << indentation << "// ";
508             printType(o, options, manager, name, 0);
509             o << ":\n";
510         }
511     }
512     for (const auto& rAttr : ent2->getDirectAttributes())
513     {
514         o << indentation;
515         if (!body)
516             o << "virtual ";
517 
518         printType(o, options, manager, rAttr.type, 1);
519         o << " SAL_CALL ";
520         if (!classname.isEmpty())
521             o << classname;
522 
523         o << "get" << rAttr.name << "()";
524         printExceptionSpecification(o, options, manager, rAttr.getExceptions);
525         if (body) {
526             if (defaultbody) {
527                 if (!propertyhelper.isEmpty()) {
528                     o << "\n{\n    osl::MutexGuard g(m_aMutex);\n    return m_"
529                       << rAttr.name << ";\n}\n\n";
530                 } else {
531                     o << "\n{\n    return ";
532                     if (options.componenttype == 1) {
533                         o << "m_" << rAttr.name;
534                     } else {
535                         printType(o, options, manager, rAttr.type, 8, true);
536                     }
537                     o << ";\n}\n\n";
538                 }
539             } else {
540                 o << "\n" << indentation << "{\n" << indentation << "    return "
541                   << delegate << "get" << rAttr.name << "();\n"
542                   << indentation << "}\n\n";
543             }
544         } else {
545             o << ";\n";
546         }
547 
548         if (!rAttr.readOnly) {
549             o << indentation;
550             if (!body)
551                 o << "virtual ";
552 
553             o << "void SAL_CALL ";
554             if (!classname.isEmpty())
555                 o << classname;
556 
557             o << "set" << rAttr.name << '(';
558             printType(o, options, manager, rAttr.type, 4);
559             o << " the_value)";
560             printExceptionSpecification(o, options, manager, rAttr.setExceptions);
561             if (body) {
562                 if (defaultbody) {
563                     if (!propertyhelper.isEmpty()) {
564                         printSetPropertyMixinBody(o, rAttr);
565                     } else {
566                         if (options.componenttype == 1) {
567                             o << "\n{\n    m_" << rAttr.name
568                               << " = the_value;\n}\n\n";
569                         } else {
570                             o << "\n{\n\n}\n\n";
571                         }
572                     }
573                 } else {
574                     o << "\n" << indentation << "{\n" << indentation << "    "
575                       << delegate << "set" << rAttr.name
576                       << "(the_value);\n" << indentation << "}\n\n";
577                 }
578             } else {
579                 o << ";\n";
580             }
581         }
582     }
583     for (const auto& rMethod : ent2->getDirectMethods())
584     {
585         o << indentation;
586         if (!body)
587             o << "virtual ";
588 
589         printType(o, options, manager, rMethod.returnType, 1);
590         o << " SAL_CALL ";
591         if (!classname.isEmpty())
592             o << classname;
593 
594         o << rMethod.name << '(';
595         printMethodParameters(o, options, manager, rMethod.parameters, true);
596         o << ')';
597         printExceptionSpecification(o, options, manager, rMethod.exceptions);
598         if (body) {
599             if (defaultbody) {
600                 o << "\n{\n";
601                 if (rMethod.returnType != "void") {
602                     o << "    // TODO: Exchange the default return implementation for \""
603                       << rMethod.name << "\" !!!\n";
604                     o << "    // Exchange the default return implementation.\n"
605                         "    // NOTE: Default initialized polymorphic structs "
606                         "can cause problems because of\n    // missing default "
607                         "initialization of primitive types of some C++ compilers or"
608                         "\n    // different Any initialization in Java and C++ "
609                         "polymorphic structs.\n    return ";
610                     printType(o, options, manager, rMethod.returnType, 8, true);
611                     o << ";";
612                 } else {
613                     o << "    // TODO: Insert your implementation for \""
614                       << rMethod.name << "\" here.";
615                 }
616                 o << "\n}\n\n";
617             } else {
618                 o << "\n" << indentation << "{\n" << indentation << "    ";
619                 if (rMethod.returnType != "void")
620                     o << "return ";
621 
622                 o << delegate << rMethod.name << '(';
623                 printMethodParameters(
624                     o, options, manager, rMethod.parameters, false);
625                 o << ");\n" << indentation << "}\n\n";
626             }
627         } else {
628             o << ";\n";
629         }
630     }
631 
632     if (!body)
633         o << "\n";
634 }
635 
printConstructors(std::ostream & o,ProgramOptions const & options,rtl::Reference<TypeManager> const & manager,OUString const & name)636 static void printConstructors(
637     std::ostream & o, ProgramOptions const & options,
638     rtl::Reference< TypeManager > const & manager, OUString const & name)
639 {
640     rtl::Reference< unoidl::Entity > ent;
641     if (manager->getSort(name, &ent)
642         != codemaker::UnoType::Sort::SingleInterfaceBasedService)
643     {
644         throw CannotDumpException(
645             "unexpected entity \"" + name
646             + "\" in call to skeletonmaker::java::printConstructors");
647     }
648     rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > ent2(
649         dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity * >(ent.get()));
650     assert(ent2.is());
651     for (const auto& rConstructor : ent2->getConstructors())
652     {
653         o << "static ";
654         printType(o, options, manager, ent2->getBase(), 1);
655         o << ' ';
656         if (rConstructor.defaultConstructor) {
657             o << "create";
658         } else {
659             o << codemaker::cpp::translateUnoToCppIdentifier(
660                 u2b(rConstructor.name), "method");
661         }
662         o << ((options.shortnames) ? "(css::uno::Reference< css" :
663               "(::com::sun::star::uno::Reference< ::com::sun::star")
664           << "::uno::XComponentContext > const & the_context";
665         for (const auto& rParam : rConstructor.parameters)
666         {
667             o << ", ";
668             printType(o, options, manager, rParam.type, 4);
669             o << ' '
670               << codemaker::cpp::translateUnoToCppIdentifier(
671                   u2b(rParam.name), "param");
672         }
673         o << ')';
674         printExceptionSpecification(o, options, manager, rConstructor.exceptions);
675         o << ";\n";
676     }
677 }
678 
printServiceMembers(std::ostream & o,ProgramOptions const & options,rtl::Reference<TypeManager> const & manager,OUString const & name,rtl::Reference<unoidl::AccumulationBasedServiceEntity> const & entity,OString const & delegate)679 static void printServiceMembers(
680     std::ostream & o, ProgramOptions const & options,
681     rtl::Reference< TypeManager > const & manager,
682     OUString const & name,
683     rtl::Reference< unoidl::AccumulationBasedServiceEntity > const & entity,
684     OString const & delegate)
685 {
686     assert(entity.is());
687     for (const auto& rService : entity->getDirectMandatoryBaseServices())
688     {
689         o << "\n// exported service " << rService.name << "\n";
690         generateDocumentation(o, options, manager, u2b(rService.name), delegate);
691         o << "\n// end of exported service " << rService.name << "\n";
692     }
693     for (const auto& rIface : entity->getDirectMandatoryBaseInterfaces())
694     {
695         o << "\n// supported interface " << rIface.name << "\n";
696         generateDocumentation(o, options, manager, u2b(rIface.name), delegate);
697     }
698     if (delegate.isEmpty()) {
699         o << "\n// properties of service \""<< name << "\"\n";
700         for (const auto& rProp : entity->getDirectProperties())
701         {
702             o << "// private ";
703             printType(o, options, manager, rProp.type, 1);
704             o << " "
705               << codemaker::cpp::translateUnoToCppIdentifier(
706                   u2b(rProp.name), "property")
707               << ";\n";
708         }
709     }
710 }
711 
printMapsToCppType(std::ostream & o,ProgramOptions const & options,rtl::Reference<TypeManager> const & manager,codemaker::UnoType::Sort sort,OUString const & nucleus,sal_Int32 rank,std::vector<OUString> const & arguments,rtl::Reference<unoidl::Entity> const & entity,const char * cppTypeSort)712 static void printMapsToCppType(
713     std::ostream & o, ProgramOptions const & options,
714     rtl::Reference< TypeManager > const & manager,
715     codemaker::UnoType::Sort sort, OUString const & nucleus, sal_Int32 rank,
716     std::vector< OUString > const & arguments,
717     rtl::Reference< unoidl::Entity > const & entity, const char * cppTypeSort)
718 {
719     o << "maps to C++ ";
720     if (cppTypeSort != nullptr)
721         o << cppTypeSort << ' ';
722 
723     o << "type \"";
724     if (rank == 0 && nucleus == "com.sun.star.uno.XInterface") {
725         o << "Reference< com::sun::star::uno::XInterface >";
726     } else {
727         printType(
728             o, options, manager, sort, nucleus, rank, arguments, entity, 0,
729             false);
730     }
731     o << '"';
732 }
733 
generateDocumentation(std::ostream & o,ProgramOptions const & options,rtl::Reference<TypeManager> const & manager,OString const & type,OString const & delegate)734 void generateDocumentation(std::ostream & o,
735     ProgramOptions const & options, rtl::Reference< TypeManager > const & manager,
736     OString const & type, OString const & delegate)
737 {
738     OUString nucleus;
739     sal_Int32 rank;
740     codemaker::UnoType::Sort sort = manager->decompose(
741         b2u(type), false, &nucleus, &rank, nullptr, nullptr);
742 
743     bool comment = true;
744     if (!delegate.isEmpty()) {
745         if (sort != codemaker::UnoType::Sort::Interface &&
746             sort != codemaker::UnoType::Sort::SingleInterfaceBasedService &&
747             sort != codemaker::UnoType::Sort::AccumulationBasedService )
748         {
749             return;
750         }
751         comment = false;
752     }
753 
754     if (comment) {
755         o << "\n// UNO";
756         if (rank != 0) {
757             o << " sequence type";
758         } else if (sort <= codemaker::UnoType::Sort::Any) {
759             o << " simple type";
760         } else {
761             switch (sort) {
762             case codemaker::UnoType::Sort::Interface:
763                 o << " interface type";
764                 break;
765 
766             case codemaker::UnoType::Sort::Module:
767                 o << "IDL module";
768                 break;
769 
770             case codemaker::UnoType::Sort::PlainStruct:
771                 o << " simple struct type";
772                 break;
773 
774             case codemaker::UnoType::Sort::PolymorphicStructTemplate:
775                 o << " polymorphic struct type template";
776                 break;
777 
778             case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
779                 o << " instantiated polymorphic struct type";
780                 break;
781 
782             case codemaker::UnoType::Sort::Enum:
783                 o << " enum type";
784                 break;
785 
786             case codemaker::UnoType::Sort::Exception:
787                 o << " exception type";
788                 break;
789 
790             case codemaker::UnoType::Sort::Typedef:
791                 o << "IDL typedef";
792                 break;
793 
794             case codemaker::UnoType::Sort::SingleInterfaceBasedService:
795                 o << " single-inheritance--based service";
796                 break;
797 
798             case codemaker::UnoType::Sort::AccumulationBasedService:
799                 o << "IDL accumulation-based service";
800                 break;
801 
802             case codemaker::UnoType::Sort::InterfaceBasedSingleton:
803                 o << " inheritance-based singleton";
804                 break;
805 
806             case codemaker::UnoType::Sort::ServiceBasedSingleton:
807                 o << "IDL service-based singleton";
808                 break;
809 
810             case codemaker::UnoType::Sort::ConstantGroup:
811                 o << "IDL constant group";
812                 break;
813 
814             default:
815                 OSL_ASSERT(false);
816                 break;
817             }
818         }
819         o << " \"" << type << "\" ";
820     }
821     std::vector< OUString > arguments;
822     rtl::Reference< unoidl::Entity > entity;
823     sort = manager->decompose(
824         b2u(type), true, &nucleus, &rank, &arguments, &entity);
825     if (rank != 0) {
826         if (comment) {
827             printMapsToCppType(
828                 o, options, manager, sort, nucleus, rank, arguments, entity,
829                 "array");
830             o << '\n';
831         }
832     } else if (sort <= codemaker::UnoType::Sort::Any) {
833         if (comment) {
834             printMapsToCppType(
835                 o, options, manager, sort, nucleus, rank, arguments, entity, nullptr);
836             o << '\n';
837         }
838     } else {
839         switch (sort) {
840         case codemaker::UnoType::Sort::Interface:
841             if (comment)
842                 printMapsToCppType(
843                     o, options, manager, sort, nucleus, rank, arguments, entity,
844                     "interface");
845             if (nucleus == "com.sun.star.uno.XInterface") {
846                 if (comment)
847                     o << '\n';
848             } else {
849                 if (comment)
850                     o << "; " << (options.all ? "all" : "direct") << " methods:\n";
851 
852                 codemaker::GeneratedTypeSet generated;
853                 printMethods(
854                     o, options, manager, nucleus, generated, delegate,
855                     options.implname, "");
856             }
857             break;
858 
859         case codemaker::UnoType::Sort::Module:
860             printMapsToCppType(
861                 o, options, manager, sort, nucleus, rank, arguments, entity,
862                 "namespace");
863             o << '\n';
864             break;
865 
866         case codemaker::UnoType::Sort::PlainStruct:
867             printMapsToCppType(
868                 o, options, manager, sort, nucleus, rank, arguments, entity,
869                 "class");
870             o << "; full constructor:\n";
871             printConstructor(
872                 o, options, manager, codemaker::UnoType::Sort::PlainStruct,
873                 entity, nucleus, arguments);
874             break;
875 
876         case codemaker::UnoType::Sort::PolymorphicStructTemplate:
877             printMapsToCppType(
878                 o, options, manager, sort, nucleus, rank, arguments, entity,
879                 "class template");
880             o << "; full constructor:\n";
881             printConstructor(
882                 o, options, manager,
883                 codemaker::UnoType::Sort::PolymorphicStructTemplate,
884                 entity, nucleus, arguments);
885             break;
886 
887         case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
888             printMapsToCppType(
889                 o, options, manager, sort, nucleus, rank, arguments, entity,
890                 "class template instantiation");
891             o << "; full constructor:\n";
892             printConstructor(
893                 o, options, manager,
894                 codemaker::UnoType::Sort::InstantiatedPolymorphicStruct,
895                 entity, nucleus, arguments);
896             break;
897 
898         case codemaker::UnoType::Sort::Enum:
899             printMapsToCppType(
900                 o, options, manager, sort, nucleus, rank, arguments, entity,
901                 "enum");
902             o << '\n';
903             break;
904 
905         case codemaker::UnoType::Sort::ConstantGroup:
906             printMapsToCppType(
907                 o, options, manager, sort, nucleus, rank, arguments, entity,
908                 "namespace");
909             o << '\n';
910             break;
911 
912         case codemaker::UnoType::Sort::Exception:
913             printMapsToCppType(
914                 o, options, manager, sort, nucleus, rank, arguments, entity,
915                 "exception class");
916             o << "; full constructor:\n";
917             printConstructor(
918                 o, options, manager, codemaker::UnoType::Sort::Exception,
919                 entity, nucleus, arguments);
920             break;
921 
922         case codemaker::UnoType::Sort::SingleInterfaceBasedService:
923             if (comment) {
924                 printMapsToCppType(
925                     o, options, manager, sort, nucleus, rank, arguments, entity,
926                     "class");
927                 o << "; construction methods:\n";
928                 printConstructors(o, options, manager, nucleus);
929             }
930             generateDocumentation(
931                 o, options, manager,
932                 u2b(dynamic_cast<unoidl::SingleInterfaceBasedServiceEntity&>(*entity)
933                     .getBase()),
934                 delegate);
935             break;
936 
937         case codemaker::UnoType::Sort::AccumulationBasedService:
938             if (comment)
939                 o << ("does not map to C++\n"
940                       "// the service members are generated instead\n");
941             printServiceMembers(
942                 o, options, manager, nucleus,
943                 dynamic_cast< unoidl::AccumulationBasedServiceEntity * >(
944                     entity.get()),
945                 delegate);
946             break;
947 
948         case codemaker::UnoType::Sort::InterfaceBasedSingleton:
949             printMapsToCppType(
950                 o, options, manager, sort, nucleus, rank, arguments, entity,
951                 "class");
952             o << "; get method:\nstatic ";
953             printType(
954                 o, options, manager,
955                 dynamic_cast< unoidl::InterfaceBasedSingletonEntity * >(
956                     entity.get())->getBase(),
957                 1);
958             o << " get(::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & context);\n";
959             break;
960 
961         case codemaker::UnoType::Sort::ServiceBasedSingleton:
962             o << "does not map to C++\n";
963             break;
964 
965         default:
966             OSL_ASSERT(false);
967             break;
968         }
969     }
970 }
971 
972 } }
973 
974 
975 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
976