13 #include <QCoreApplication>
27 if (sEnumName.isEmpty())
34 if (sEnumName.count(
'.') != 1 )
37 QStringList lstTypeParts = sEnumName.split(
'.' );
43 QString sParentFQN = lstTypeParts[0];
44 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
50 if (nParentId == QMetaType::UnknownType)
52 QString sFQN = sParentFQN +
"*";
61 if (nParentId == QMetaType::UnknownType)
63 QString sFQN =
"DTC::" + sParentFQN +
"*";
67 const QMetaObject *pMetaObject = QMetaType::metaObjectForType(nParentId);
69 QMetaType metaType = QMetaType::fromName( sParentFQN.toUtf8() );
70 if (metaType.id() == QMetaType::UnknownType)
71 metaType = QMetaType::fromName( sParentFQN.toUtf8() +
"*" );
72 if (metaType.id() == QMetaType::UnknownType)
73 metaType = QMetaType::fromName(
"DTC::" + sParentFQN.toUtf8() +
"*" );
74 if (metaType.id() == QMetaType::UnknownType)
76 const QMetaObject *pMetaObject = metaType.metaObject();
79 if (pMetaObject ==
nullptr)
86 int nEnumIdx = pMetaObject->indexOfEnumerator( lstTypeParts[1].toUtf8() );
91 QMetaEnum metaEnum = pMetaObject->enumerator( nEnumIdx );
120 appendChild( createProcessingInstruction(
"xml-stylesheet",
121 R
"(type="text/xsl" href="/xslt/enum.xslt")" ));
128 QDomElement oTypeNode = createElement(
"xs:simpleType" );
129 QDomElement oRestrictNode = createElement(
"xs:restriction" );
131 oTypeNode .setAttribute(
"name", sEnumName );
132 oRestrictNode.setAttribute(
"base",
"xs:string" );
134 oTypeNode.appendChild( oRestrictNode );
136 for(
int nIdx = 0; nIdx < metaEnum.keyCount(); nIdx++)
138 QDomElement oEnum = createElement(
"xs:enumeration" );
140 oEnum.setAttribute(
"value", metaEnum.key( nIdx ));
146 QDomElement oAnn = createElement(
"xs:annotation" );
147 QDomElement oApp = createElement(
"xs:appinfo" );
148 QDomElement oEnumVal = createElement(
"EnumerationValue" );
149 QDomElement oEnumDesc = createElement(
"EnumerationDesc" );
152 oEnumVal.setAttribute(
"xmlns",
"http://schemas.microsoft.com/2003/10/Serialization/");
154 oEnum.appendChild( oAnn );
155 oAnn .appendChild( oApp );
156 oApp .appendChild( oEnumVal );
157 oApp .appendChild( oEnumDesc );
159 QString sFQNKey = sEnumName +
"." + metaEnum.key( nIdx );
161 oEnumVal .appendChild( createTextNode( QString::number( metaEnum.value( nIdx ))));
162 oEnumDesc.appendChild( createTextNode( QCoreApplication::translate(
"Enums",
163 sFQNKey.toUtf8() )));
165 oRestrictNode.appendChild( oEnum );
170 QDomElement oElementNode = createElement(
"xs:element" );
172 oElementNode.setAttribute(
"name" , sEnumName );
173 oElementNode.setAttribute(
"type" ,
"tns:" + sEnumName );
174 oElementNode.setAttribute(
"nillable",
"true" );
182 oRoot.appendChild( oTypeNode );
183 oRoot.appendChild( oElementNode );
185 appendChild( oRoot );
206 bool bIsArray =
false;
209 if (sTypeName.isEmpty())
216 if (sTypeName.startsWith(
"ArrayOf" ))
219 sTypeName = sTypeName.mid( 7 );
222 if (sTypeName.startsWith(
"MapOfString" ))
225 sTypeName = sTypeName.mid( 11 );
232 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
238 if (
id == QMetaType::UnknownType)
240 QString sFQN = sTypeName +
"*";
249 if (
id == QMetaType::UnknownType)
251 QString sFQN =
"DTC::" + sTypeName +
"*";
255 QMetaType metaType = QMetaType::fromName( sTypeName.toUtf8() );
256 if (metaType.id() == QMetaType::UnknownType)
257 metaType = QMetaType::fromName( sTypeName.toUtf8() +
"*" );
258 if (metaType.id() == QMetaType::UnknownType)
259 metaType = QMetaType::fromName(
"DTC::" + sTypeName.toUtf8() +
"*" );
260 if (metaType.id() == QMetaType::UnknownType)
262 int id = metaType.id();
269 if (!(bIsArray || bIsMap) && (
id < QMetaType::User))
276 bool bHandled =
false;
284 appendChild( createProcessingInstruction(
"xml-stylesheet",
285 R
"(type="text/xsl" href="/xslt/class.xslt")" ));
290 bHandled =
RenderArrayXSD( pRequest, sTypeName,
id >= QMetaType::User );
296 id >= QMetaType::User );
300 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
301 const QMetaObject *pMetaObject = QMetaType::metaObjectForType(
id);
303 const QMetaObject *pMetaObject = metaType.metaObject();
307 QObject* pClass = pMetaObject->newInstance();
308 if (pClass !=
nullptr)
309 bHandled =
RenderXSD( pRequest, pClass );
344 const QMetaObject *pMetaObject = pClass->metaObject();
349 QMap<QString, TypeInfo> typesToInclude;
355 QDomElement oTypeNode = createElement(
"xs:complexType" );
356 QDomElement oSeqNode = createElement(
"xs:sequence" );
358 oTypeNode.setAttribute(
"name", sClassName );
360 oTypeNode.appendChild( oSeqNode );
372 int nCount = pMetaObject->propertyCount();
374 for (
int nIdx=0; nIdx < nCount; ++nIdx )
376 QMetaProperty metaProperty = pMetaObject->property( nIdx );
378 if (metaProperty.isDesignable())
380 const char *pszPropName = metaProperty.name();
381 QString sPropName( pszPropName );
383 if ( sPropName.compare(
"objectName" ) == 0)
390 QDomElement oNode = createElement(
"xs:element" );
391 QString sType = metaProperty.typeName();
392 bool bCustomType =
false;
393 QString sCustomAttr =
"type";
394 QString sContentName = QString();
395 QString sContentType = QString();
397 LOG(VB_UPNP, LOG_DEBUG, QString(
"Type: %1").arg( sType ));
403 if (sType ==
"QObject*")
405 QVariant val = metaProperty.read( pClass );
406 const QObject *pObject = val.value< QObject* >();
408 sType = pObject->metaObject()->className();
411 else if ((sType ==
"QVariantList" ) || (sType ==
"QVariantMap"))
417 if (sContentType.startsWith(
'Q'))
418 sContentType = sContentType.mid( 1 );
420 sContentType.remove(
"DTC::" );
421 sContentType.remove( QChar(
'*') );
423 if (sType ==
"QVariantMap")
429 if (sContentName.isEmpty())
430 sContentName = sContentType;
432 sType =
"MapOfString" + sContentName;
435 sType =
"ArrayOf" + sContentType;
440 else if (sType ==
"QStringList")
442 sType =
"ArrayOfString";
445 else if (
IsEnum( metaProperty, sType ))
447 sCustomAttr =
"enum";
449 sType.remove(
"DTC::" );
453 if (sType.contains(
"::" ))
454 sType = sType.replace(
"::",
"." );
456 sType = sClassName +
"." + sType;
461 QString sNewPropName( metaProperty.name() );
464 oNode.setAttribute(
"nillable" ,
static_cast<int>(
true) );
468 TypeInfo info = { sCustomAttr, sContentType };
469 typesToInclude.insert( sType, info );
472 oNode.setAttribute(
"type" , (bCustomType ?
"tns:" :
"xs:") +
475 oNode.setAttribute(
"name" , sNewPropName );
476 oNode.setAttribute(
"minOccurs", 0 );
478 oSeqNode.appendChild( oNode );
488 QDomElement oElementNode = createElement(
"xs:element" );
490 oElementNode.setAttribute(
"type" ,
"tns:" + sClassName );
491 oElementNode.setAttribute(
"nillable",
"true" );
492 oElementNode.setAttribute(
"name" , sClassName );
498 appendChild( oRoot );
500 if (typesToInclude.count() > 0)
508 QString sBaseUri =
"http://" + pRequest->
GetLastHeader(
"host" ) +
511 QMap<QString, TypeInfo >::const_iterator it = typesToInclude.constBegin();
512 while( it != typesToInclude.constEnd())
514 QDomElement oIncNode = createElement(
"xs:include" );
515 QString sType = it.key();
517 sType.remove(
"DTC::" );
521 QString sValue = QString(
"%1?%2=%3" ).arg( sBaseUri,
528 oIncNode.setAttribute(
"schemaLocation", sValue );
530 oRoot.appendChild( oIncNode );
535 oRoot.appendChild( oTypeNode );
536 oRoot.appendChild( oElementNode );
551 bool Xsd::IsEnum(
const QMetaProperty &metaProperty,
const QString & )
553 return (metaProperty.isEnumType() || metaProperty.isFlagType() );
578 const QString &sClassName,
581 QString sArrayName =
"ArrayOf" + sClassName;
585 sType =
"tns:" + sClassName;
595 QDomElement oTypeNode = createElement(
"xs:complexType" );
596 QDomElement oSeqNode = createElement(
"xs:sequence" );
600 oTypeNode.setAttribute(
"name", sArrayName );
601 oTypeNode.appendChild( oSeqNode );
603 QDomElement oNode = createElement(
"xs:element" );
605 oNode.setAttribute(
"type" , sType );
606 oNode.setAttribute(
"nillable" ,
"true" );
607 oNode.setAttribute(
"name" , sClassName );
608 oNode.setAttribute(
"maxOccurs" ,
"unbounded" );
609 oNode.setAttribute(
"minOccurs" ,
"0" );
611 oSeqNode.appendChild( oNode );
617 QDomElement oElementNode = createElement(
"xs:element" );
619 oElementNode.setAttribute(
"type" ,
"tns:" + sArrayName );
620 oElementNode.setAttribute(
"nillable",
"true" );
621 oElementNode.setAttribute(
"name" , sArrayName );
627 appendChild( oRoot );
631 QDomElement oIncNode = createElement(
"xs:include" );
633 QString sBaseUri =
"http://" + pRequest->
GetLastHeader(
"host" ) +
636 oIncNode.setAttribute(
"schemaLocation", sBaseUri + sClassName );
638 oRoot.appendChild( oIncNode );
641 oRoot.appendChild( oTypeNode );
642 oRoot.appendChild( oElementNode );
689 const QString &sClassName,
692 QString sArrayName =
"MapOfString" + sClassName;
693 QString sMapItemName = pRequest->
m_mapParams[
"name" ];
696 if (sMapItemName.isEmpty())
697 sMapItemName = sClassName;
700 sType =
"tns:" + sMapItemName;
710 QDomElement oTypeNode = createElement(
"xs:complexType" );
711 QDomElement oSeqNode = createElement(
"xs:sequence" );
712 QDomElement oAnno = createElement(
"xs:annotation" );
713 QDomElement oAppInfo = createElement(
"xs:appinfo" );
715 QDomElement oNode = createElement(
"IsDictionary" );
716 oNode.setAttribute(
"xmlns",
"http://schemas.microsoft.com/2003/10/Serialization/" );
717 oNode.appendChild( createTextNode(
"true" ));
719 oTypeNode.appendChild( oAnno );
720 oAnno .appendChild( oAppInfo );
721 oAppInfo .appendChild( oNode );
729 oTypeNode.setAttribute(
"name", sArrayName );
730 oTypeNode.appendChild( oSeqNode );
736 QDomElement oInnerNode = createElement(
"xs:element" );
738 oInnerNode.setAttribute(
"name" , sClassName );
739 oInnerNode.setAttribute(
"maxOccurs" ,
"unbounded" );
740 oInnerNode.setAttribute(
"minOccurs" ,
"0" );
742 oSeqNode.appendChild( oInnerNode );
747 oNode = createElement(
"xs:complexType" );
749 oInnerNode.appendChild( oNode );
755 QDomElement oInnerSeq = createElement(
"xs:sequence" );
757 oNode.appendChild( oInnerSeq );
763 oNode = createElement(
"xs:element" );
765 oNode.setAttribute(
"type" ,
"xs:string" );
766 oNode.setAttribute(
"nillable" ,
"true" );
767 oNode.setAttribute(
"name" ,
"Key" );
769 oInnerSeq.appendChild( oNode );
775 oNode = createElement(
"xs:element" );
777 oNode.setAttribute(
"type" , sType );
778 oNode.setAttribute(
"nillable" ,
"true" );
779 oNode.setAttribute(
"name" ,
"Value" );
781 oInnerSeq.appendChild( oNode );
787 QDomElement oElementNode = createElement(
"xs:element" );
789 oElementNode.setAttribute(
"type" ,
"tns:" + sArrayName );
790 oElementNode.setAttribute(
"nillable",
"true" );
791 oElementNode.setAttribute(
"name" , sArrayName );
797 appendChild( oRoot );
801 QDomElement oIncNode = createElement(
"xs:include" );
805 oIncNode.setAttribute(
"schemaLocation", sBaseUri + sClassName );
807 oRoot.appendChild( oIncNode );
810 oRoot.appendChild( oTypeNode );
811 oRoot.appendChild( oElementNode );
833 QString sTargetNamespace =
"http://mythtv.org";
835 QDomElement oRoot = createElement(
"xs:schema" );
837 oRoot.setAttribute(
"xmlns:xs" ,
"http://www.w3.org/2001/XMLSchema");
838 oRoot.setAttribute(
"xmlns:tns" , sTargetNamespace );
839 oRoot.setAttribute(
"targetNamespace" , sTargetNamespace );
840 oRoot.setAttribute(
"elementFormDefault" ,
"qualified" );
841 oRoot.setAttribute(
"attributeFormDefault",
"unqualified" );
851 if (sType.startsWith(
"DTC::"))
854 if (sType ==
"QDateTime")
857 if (sType ==
"QDate")
860 if (sType ==
"QTime")
872 if (bCustomType || sType.startsWith(
"DTC::"))
874 QString sTypeName( sType );
876 sTypeName.remove(
"DTC::" );
877 sTypeName.remove( QChar(
'*') );
879 if (sType ==
"QStringList" )
880 return "ArrayOfString";
885 if (sType ==
"QDateTime")
888 if (sType ==
"QDate")
891 if (sType ==
"QTime")
898 return "unsignedInt";
900 if (sType ==
"qlonglong" )
903 if (sType ==
"long long" )
906 if (sType ==
"QFileInfo" )
909 if (sType.startsWith(
'Q'))
910 return sType.mid( 1 ).toLower();
912 return sType.toLower();
921 const QMetaObject *pMeta = pObject->metaObject();
926 nIdx = pMeta->indexOfClassInfo( sPropName.toUtf8() );
930 QString sMetadata = pMeta->classInfo( nIdx ).value();
931 QStringList sOptions = sMetadata.split(
';' );
933 QString sFullKey = sKey +
"=";
935 for (
const QString& option : qAsConst(sOptions))
937 if (option.startsWith( sFullKey ))
938 return option.mid( sFullKey.length() );