コード例 #1
0
QString OsmAnd::ResolvedMapStyle_P::dumpRuleNodeOutputValues(
    const std::shared_ptr<const RuleNode>& ruleNode,
    const QString& prefix,
    const bool allowOverride) const
{
    QString dump;
    const auto builtinValueDefs = MapStyleBuiltinValueDefinitions::get();

    for (const auto& ruleValueEntry : rangeOf(constOf(ruleNode->values)))
    {
        const auto valueDefId = ruleValueEntry.key();
        const auto& valueDef = getValueDefinitionById(valueDefId);

        // Skip all non-Output values
        if (valueDef->valueClass != MapStyleValueDefinition::Class::Output)
            continue;

        const auto& resolvedRuleValue = ruleValueEntry.value();

        dump += prefix + QString(QLatin1String("%1 %2 = %3;\n"))
            .arg(allowOverride ? QLatin1String("setOrOverride") : QLatin1String("setIfNotSet"))
            .arg(valueDef->name)
            .arg(dumpResolvedValue(resolvedRuleValue, valueDef->dataType));
    }

    return dump;
}
コード例 #2
0
std::shared_ptr<OsmAnd::ResolvedMapStyle_P::RuleNode> OsmAnd::ResolvedMapStyle_P::resolveRuleNode(
    const std::shared_ptr<const UnresolvedMapStyle::RuleNode>& unresolvedRuleNode)
{
    const std::shared_ptr<RuleNode> resolvedRuleNode(new RuleNode(
        unresolvedRuleNode->isSwitch));

    // Resolve values
    for (const auto& itUnresolvedValueEntry : rangeOf(constOf(unresolvedRuleNode->values)))
    {
        const auto& name = itUnresolvedValueEntry.key();
        const auto& value = itUnresolvedValueEntry.value();

        // Find value definition id and object
        const auto valueDefId = getValueDefinitionIdByName(name);
        const auto& valueDef = getValueDefinitionById(valueDefId);
        if (valueDefId < 0 || !valueDef)
        {
            LogPrintf(LogSeverityLevel::Warning,
                "Ignoring unknown value '%s' = '%s'",
                qPrintable(name),
                qPrintable(value));
            continue;
        }

        // Try to resolve value
        ResolvedValue resolvedValue;
        if (!resolveValue(value, valueDef->dataType, valueDef->isComplex, resolvedValue))
        {
            LogPrintf(LogSeverityLevel::Warning,
                "Ignoring value for '%s' since '%s' can not be resolved",
                qPrintable(name),
                qPrintable(value));
            continue;
        }

        resolvedRuleNode->values[valueDefId] = resolvedValue;
    }

    // <switch>/<case> subnodes
    for (const auto& unresolvedChild : constOf(unresolvedRuleNode->oneOfConditionalSubnodes))
    {
        const auto resolvedChild = resolveRuleNode(unresolvedChild);
        if (!resolvedChild)
            return nullptr;

        resolvedRuleNode->oneOfConditionalSubnodes.push_back(resolvedChild);
    }

    // <apply> subnodes
    for (const auto& unresolvedChild : constOf(unresolvedRuleNode->applySubnodes))
    {
        const auto resolvedChild = resolveRuleNode(unresolvedChild);
        if (!resolvedChild)
            return nullptr;

        resolvedRuleNode->applySubnodes.push_back(resolvedChild);
    }

    return resolvedRuleNode;
}
コード例 #3
0
ファイル: Styler.cpp プロジェクト: biddyweb/OsmAnd-core
bool OsmAndTools::Styler::evaluate(EvaluatedMapObjects& outEvaluatedMapObjects, std::ostream& output)
#endif
{
    bool success = true;
    for (;;)
    {
        // Find style
        if (configuration.verbose)
            output << xT("Resolving style '") << QStringToStlString(configuration.styleName) << xT("'...") << std::endl;
        const auto mapStyle = configuration.stylesCollection->getResolvedStyleByName(configuration.styleName);
        if (!mapStyle)
        {
            if (configuration.verbose)
            {
                output
                    << "Failed to resolve style '"
                    << QStringToStlString(configuration.styleName)
                    << "' from collection:"
                    << std::endl;
                for (const auto& style : configuration.stylesCollection->getCollection())
                {
                    if (style->isMetadataLoaded())
                    {
                        if (style->isStandalone())
                            output << "\t" << QStringToStlString(style->name) << std::endl;
                        else
                        {
                            output
                                << "\t"
                                << QStringToStlString(style->name)
                                << "::"
                                << QStringToStlString(style->parentName)
                                << std::endl;
                        }
                    }
                    else
                        output << "\t[missing metadata]" << std::endl;
                }
            }
            else
            {
                output
                    << "Failed to resolve style '"
                    << QStringToStlString(configuration.styleName)
                    << "' from collection:"
                    << std::endl;
            }

            success = false;
            break;
        }

        // Load all map objects
        const auto mapObjectsFilterById =
            [this]
            (const std::shared_ptr<const OsmAnd::ObfMapSectionInfo>& section,
            const uint64_t mapObjectId,
            const OsmAnd::AreaI& bbox,
            const OsmAnd::ZoomLevel firstZoomLevel,
            const OsmAnd::ZoomLevel lastZoomLevel,
            const OsmAnd::ZoomLevel requestedZoom) -> bool
            {
                return configuration.mapObjectsIds.contains(mapObjectId);
            };
        if (configuration.verbose)
        {
            if (configuration.mapObjectsIds.isEmpty())
                output << xT("Going to load all available map objects...") << std::endl;
            else
                output << xT("Going to load ") << configuration.mapObjectsIds.size() << xT(" map objects...") << std::endl;
        }
        const auto obfDataInterface = configuration.obfsCollection->obtainDataInterface();
        QList< std::shared_ptr<const OsmAnd::BinaryMapObject> > mapObjects_;
        success = obfDataInterface->loadBinaryMapObjects(
            &mapObjects_,
            nullptr,
            configuration.zoom,
            nullptr,
            configuration.mapObjectsIds.isEmpty() ? OsmAnd::ObfMapSectionReader::FilterByIdFunction() : mapObjectsFilterById,
            nullptr,
            nullptr,
            nullptr,
            nullptr);
        const auto mapObjects = OsmAnd::copyAs< QList< std::shared_ptr<const OsmAnd::MapObject> > >(mapObjects_);
        if (!success)
        {
            if (configuration.verbose)
                output << xT("Failed to load map objects!") << std::endl;
            break;
        }
        if (configuration.verbose)
            output << xT("Loaded ") << mapObjects.size() << xT(" map objects") << std::endl;

        // Prepare all resources for map style evaluation
        if (configuration.verbose)
        {
            output
                << xT("Initializing map presentation environment with display density ")
                << configuration.displayDensityFactor
                << xT(", map scale ")
                << configuration.mapScale
                << xT(", symbols scale ")
                << configuration.symbolsScale
                << xT(" and locale '")
                << QStringToStlString(configuration.locale)
                << xT("'...") << std::endl;
        }
        const std::shared_ptr<OsmAnd::MapPresentationEnvironment> mapPresentationEnvironment(new OsmAnd::MapPresentationEnvironment(
            mapStyle,
            configuration.displayDensityFactor,
            configuration.mapScale,
            configuration.symbolsScale,
            configuration.locale));

        if (configuration.verbose)
            output << xT("Applying extra style settings to map presentation environment...") << std::endl;
        mapPresentationEnvironment->setSettings(configuration.styleSettings);

        // Create primitiviser
        const std::shared_ptr<OsmAnd::MapPrimitiviser> primitiviser(new OsmAnd::MapPrimitiviser(mapPresentationEnvironment));
        if (configuration.verbose)
            output << xT("Going to primitivise map objects...") << std::endl;
        OsmAnd::MapPrimitiviser_Metrics::Metric_primitiviseAllMapObjects metrics;
        const auto primitivisedData = primitiviser->primitiviseAllMapObjects(
                configuration.zoom,
                mapObjects,
                nullptr,
                nullptr,
                configuration.metrics ? &metrics : nullptr);
        if (configuration.verbose)
        {
            output
                << xT("Primitivised ")
                << primitivisedData->primitivesGroups.size()
                << xT(" groups from ")
                << mapObjects.size()
                << xT(" map objects") << std::endl;
        }

        // Obtain evaluated values for each group and print it
        for (const auto& primitivisedGroup : OsmAnd::constOf(primitivisedData->primitivesGroups))
        {
            const auto& mapObject = primitivisedGroup->sourceObject;
            const auto binaryMapObject = std::dynamic_pointer_cast<const OsmAnd::BinaryMapObject>(mapObject);
            const auto& encDecRules = mapObject->encodingDecodingRules;

            // Skip objects that were not requested
            if (!configuration.mapObjectsIds.isEmpty() &&
                binaryMapObject &&
                !configuration.mapObjectsIds.contains(binaryMapObject->id))
            {
                continue;
            }

            outEvaluatedMapObjects[mapObject] = primitivisedGroup;

            output << QStringToStlString(QString(80, QLatin1Char('-'))) << std::endl;
            output << QStringToStlString(mapObject->toString()) << std::endl;

            for (const auto& typeRuleId : OsmAnd::constOf(mapObject->typesRuleIds))
            {
                const auto itTypeRule = encDecRules->decodingRules.constFind(typeRuleId);
                if (itTypeRule != encDecRules->decodingRules.cend())
                {
                    const auto& typeRule = *itTypeRule;

                    output
                        << xT("\tType: ")
                        << QStringToStlString(typeRule.tag)
                        << xT(" = ")
                        << QStringToStlString(typeRule.value)
                        << std::endl;
                }
                else
                {
                    output << xT("\tType: #") << typeRuleId << xT(" (UNRESOLVED)") << std::endl;
                }
            }

            for (const auto& typeRuleId : OsmAnd::constOf(mapObject->additionalTypesRuleIds))
            {
                const auto itTypeRule = encDecRules->decodingRules.constFind(typeRuleId);
                if (itTypeRule != encDecRules->decodingRules.cend())
                {
                    const auto& typeRule = *itTypeRule;

                    output
                        << xT("\tExtra type: ")
                        << QStringToStlString(typeRule.tag)
                        << xT(" = ")
                        << QStringToStlString(typeRule.value)
                        << std::endl;
                }
                else
                {
                    output << xT("\tExtra type: #") << typeRuleId << xT(" (UNRESOLVED)") << std::endl;
                }
            }

            for (const auto& captionTagId : OsmAnd::constOf(mapObject->captionsOrder))
            {
                const auto& captionValue = mapObject->captions[captionTagId];

                if (encDecRules->name_encodingRuleId == captionTagId)
                    output << xT("\tCaption: ") << QStringToStlString(captionValue) << std::endl;
                else if (encDecRules->ref_encodingRuleId == captionTagId)
                    output << xT("\tRef: ") << QStringToStlString(captionValue) << std::endl;
                else
                {
                    const auto itCaptionTagAsLocalizedName = encDecRules->localizedName_decodingRules.constFind(captionTagId);
                    const auto itCaptionTagRule = encDecRules->decodingRules.constFind(captionTagId);

                    QString captionTag(QLatin1String("UNRESOLVED"));
                    if (itCaptionTagAsLocalizedName != encDecRules->localizedName_decodingRules.cend())
                        captionTag = *itCaptionTagAsLocalizedName;
                    if (itCaptionTagRule != encDecRules->decodingRules.cend())
                        captionTag = itCaptionTagRule->tag;
                    output
                        << xT("\tCaption [")
                        << QStringToStlString(captionTag)
                        << xT("]: ")
                        << QStringToStlString(captionValue)
                        << std::endl;
                }
            }

            if (!primitivisedGroup->points.isEmpty())
            {
                output << primitivisedGroup->points.size() << xT(" point(s):") << std::endl;

                unsigned int pointPrimitiveIndex = 0u;
                for (const auto& pointPrimitive : OsmAnd::constOf(primitivisedGroup->points))
                {
                    output << xT("\tPoint #") << pointPrimitiveIndex << std::endl;
                    QString ruleTag;
                    QString ruleValue;
                    const auto typeRuleResolved = mapObject->obtainTagValueByTypeRuleIndex(
                        pointPrimitive->typeRuleIdIndex,
                        ruleTag,
                        ruleValue);
                    if (typeRuleResolved)
                    {
                        output
                            << xT("\t\tTag/value: ")
                            << QStringToStlString(ruleTag)
                            << xT(" = ")
                            << QStringToStlString(ruleValue)
                            << std::endl;
                    }
                    else
                    {
                        output
                            << xT("\t\tTag/value: ")
                            << pointPrimitive->typeRuleIdIndex
                            << xT(" (failed to resolve)")
                            << std::endl;
                    }
                    output << xT("\t\tZ order: ") << pointPrimitive->zOrder << std::endl;
                    output << xT("\t\tArea*2: ") << pointPrimitive->doubledArea << std::endl;
                    const auto& values = pointPrimitive->evaluationResult.getValues();
                    for (const auto& evaluatedValueEntry : OsmAnd::rangeOf(values))
                    {
                        const auto valueDefinitionId = evaluatedValueEntry.key();
                        const auto value = evaluatedValueEntry.value();

                        const auto valueDefinition = mapStyle->getValueDefinitionById(valueDefinitionId);

                        output << xT("\t\t") << QStringToStlString(valueDefinition->name) << xT(" = ");
                        if (valueDefinition->dataType == OsmAnd::MapStyleValueDataType::Color)
                            output << QStringToStlString(OsmAnd::ColorARGB(value.toUInt()).toString());
                        else
                            output << QStringToStlString(value.toString());
                        output << std::endl;
                    }

                    pointPrimitiveIndex++;
                }
            }

            if (!primitivisedGroup->polylines.isEmpty())
            {
                output << primitivisedGroup->polylines.size() << xT(" polyline(s):") << std::endl;

                unsigned int polylinePrimitiveIndex = 0u;
                for (const auto& polylinePrimitive : OsmAnd::constOf(primitivisedGroup->polylines))
                {
                    output << xT("\tPolyline #") << polylinePrimitiveIndex << std::endl;
                    QString ruleTag;
                    QString ruleValue;
                    const auto typeRuleResolved = mapObject->obtainTagValueByTypeRuleIndex(
                        polylinePrimitive->typeRuleIdIndex,
                        ruleTag,
                        ruleValue);
                    if (typeRuleResolved)
                    {
                        output
                            << xT("\t\tTag/value: ")
                            << QStringToStlString(ruleTag)
                            << xT(" = ")
                            << QStringToStlString(ruleValue) << std::endl;
                    }
                    else
                    {
                        output
                            << xT("\t\tTag/value: ")
                            << polylinePrimitive->typeRuleIdIndex
                            << xT(" (failed to resolve)")
                            << std::endl;
                    }
                    output << xT("\t\tZ order: ") << polylinePrimitive->zOrder << std::endl;
                    output << xT("\t\tArea*2: ") << polylinePrimitive->doubledArea << std::endl;
                    const auto& values = polylinePrimitive->evaluationResult.getValues();
                    for (const auto& evaluatedValueEntry : OsmAnd::rangeOf(values))
                    {
                        const auto valueDefinitionId = evaluatedValueEntry.key();
                        const auto value = evaluatedValueEntry.value();

                        const auto valueDefinition = mapStyle->getValueDefinitionById(valueDefinitionId);

                        output << xT("\t\t") << QStringToStlString(valueDefinition->name) << xT(" = ");
                        if (valueDefinition->dataType == OsmAnd::MapStyleValueDataType::Color)
                            output << QStringToStlString(OsmAnd::ColorARGB(value.toUInt()).toString());
                        else
                            output << QStringToStlString(value.toString());
                        output << std::endl;
                    }

                    polylinePrimitiveIndex++;
                }
            }

            if (!primitivisedGroup->polygons.isEmpty())
            {
                output << primitivisedGroup->polygons.size() << xT(" polygon(s):") << std::endl;

                unsigned int polygonPrimitiveIndex = 0u;
                for (const auto& polygonPrimitive : OsmAnd::constOf(primitivisedGroup->polygons))
                {
                    output << xT("\tPolygon #") << polygonPrimitiveIndex << std::endl;
                    QString ruleTag;
                    QString ruleValue;
                    const auto typeRuleResolved = mapObject->obtainTagValueByTypeRuleIndex(
                        polygonPrimitive->typeRuleIdIndex,
                        ruleTag,
                        ruleValue);
                    if (typeRuleResolved)
                    {
                        output
                            << xT("\t\tTag/value: ")
                            << QStringToStlString(ruleTag)
                            << xT(" = ")
                            << QStringToStlString(ruleValue)
                            << std::endl;
                    }
                    else
                    {
                        output
                            << xT("\t\tTag/value: ")
                            << polygonPrimitive->typeRuleIdIndex
                            << xT(" (failed to resolve)")
                            << std::endl;
                    }
                    output << xT("\t\tZ order: ") << polygonPrimitive->zOrder << std::endl;
                    output << xT("\t\tArea*2: ") << polygonPrimitive->doubledArea << std::endl;
                    const auto& values = polygonPrimitive->evaluationResult.getValues();
                    for (const auto& evaluatedValueEntry : OsmAnd::rangeOf(values))
                    {
                        const auto valueDefinitionId = evaluatedValueEntry.key();
                        const auto value = evaluatedValueEntry.value();

                        const auto valueDefinition = mapStyle->getValueDefinitionById(valueDefinitionId);

                        output << xT("\t\t") << QStringToStlString(valueDefinition->name) << xT(" = ");
                        if (valueDefinition->dataType == OsmAnd::MapStyleValueDataType::Color)
                            output << QStringToStlString(OsmAnd::ColorARGB(value.toUInt()).toString());
                        else
                            output << QStringToStlString(value.toString());
                        output << std::endl;
                    }

                    polygonPrimitiveIndex++;
                }
            }

            const auto itSymbolsGroup = primitivisedData->symbolsGroups.constFind(mapObject);
            if (itSymbolsGroup != primitivisedData->symbolsGroups.cend())
            {
                const auto& symbolsGroup = *itSymbolsGroup;

                output << symbolsGroup->symbols.size() << xT(" symbol(s):") << std::endl;

                unsigned int symbolIndex = 0u;
                for (const auto& symbol : OsmAnd::constOf(symbolsGroup->symbols))
                {
                    const auto textSymbol = std::dynamic_pointer_cast<const OsmAnd::MapPrimitiviser::TextSymbol>(symbol);
                    const auto iconSymbol = std::dynamic_pointer_cast<const OsmAnd::MapPrimitiviser::IconSymbol>(symbol);

                    output << xT("\tSymbol #") << symbolIndex;
                    if (textSymbol)
                        output << xT(" (text)");
                    else if (iconSymbol)
                        output << xT(" (icon)");
                    output << std::endl;

                    auto primitiveIndex = -1;
                    if (primitiveIndex == -1)
                    {
                        primitiveIndex = primitivisedGroup->points.indexOf(symbol->primitive);
                        if (primitiveIndex >= 0)
                            output << xT("\t\tPrimitive: Point #") << primitiveIndex << std::endl;
                    }
                    if (primitiveIndex == -1)
                    {
                        primitiveIndex = primitivisedGroup->polylines.indexOf(symbol->primitive);
                        if (primitiveIndex >= 0)
                            output << xT("\t\tPrimitive: Polyline #") << primitiveIndex << std::endl;
                    }
                    if (primitiveIndex == -1)
                    {
                        primitiveIndex = primitivisedGroup->polygons.indexOf(symbol->primitive);
                        if (primitiveIndex >= 0)
                            output << xT("\t\tPrimitive: Polygon #") << primitiveIndex << std::endl;
                    }

                    output << xT("\t\tPosition31: ") << symbol->location31.x << xT("x") << symbol->location31.y << std::endl;
                    output << xT("\t\tOrder: ") << symbol->order << std::endl;
                    output << xT("\t\tDraw along path: ") << (symbol->drawAlongPath ? xT("yes") : xT("no")) << std::endl;
                    output
                        << xT("\t\tIntersects with: ")
                        << QStringToStlString(QStringList(symbol->intersectsWith.toList()).join(QLatin1String(", ")))
                        << std::endl;
                    output << xT("\t\tMinDistance: ") << symbol->minDistance << std::endl;
                    if (textSymbol)
                    {
                        output << xT("\t\tText: ") << QStringToStlString(textSymbol->value) << std::endl;
                        output << xT("\t\tLanguage: ");
                        switch (textSymbol->languageId)
                        {
                            case OsmAnd::LanguageId::Invariant:
                                output << xT("invariant");
                                break;
                            case OsmAnd::LanguageId::Native:
                                output << xT("native");
                                break;
                            case OsmAnd::LanguageId::Localized:
                                output << xT("localized");
                                break;
                        }
                        output << std::endl;
                        output << xT("\t\tDraw text on path: ") << (textSymbol->drawOnPath ? xT("yes") : xT("no")) << std::endl;
                        output << xT("\t\tText vertical offset: ") << textSymbol->verticalOffset << std::endl;
                        output << xT("\t\tText color: ") << QStringToStlString(textSymbol->color.toString()) << std::endl;
                        output << xT("\t\tText size: ") << textSymbol->size << std::endl;
                        output << xT("\t\tText shadow radius: ") << textSymbol->shadowRadius << std::endl;
                        output
                            << xT("\t\tText shadow color: ")
                            << QStringToStlString(textSymbol->shadowColor.toString())
                            << std::endl;
                        output << xT("\t\tText wrap width: ") << textSymbol->wrapWidth << std::endl;
                        output << xT("\t\tText is bold: ") << (textSymbol->isBold ? xT("yes") : xT("no")) << std::endl;
                        output << xT("\t\tText is italic: ") << (textSymbol->isItalic ? xT("yes") : xT("no")) << std::endl;
                        output
                            << xT("\t\tShield resource name: ")
                            << QStringToStlString(textSymbol->shieldResourceName)
                            << std::endl;
                    }
                    else if (iconSymbol)
                    {
                        output << xT("\t\tIcon resource name: ") << QStringToStlString(iconSymbol->resourceName) << std::endl;
                        for (const auto& overlayResoucreName : iconSymbol->overlayResourceNames)
                            output << xT("\t\tOverlay resource name: ") << QStringToStlString(overlayResoucreName) << std::endl;
                        output
                            << xT("\t\tShield resource name: ")
                            << QStringToStlString(iconSymbol->shieldResourceName)
                            << std::endl;
                        output << xT("\t\tIntersection size: ") << iconSymbol->intersectionSize << std::endl;
                    }

                    symbolIndex++;
                }
            }
        }

        if (configuration.metrics)
        {
            output
                << xT("Metrics:\n")
                << QStringToStlString(metrics.toString(false, QLatin1String("\t")))
                << std::endl;
        }

        break;
    }

    return success;
}
コード例 #4
0
QString OsmAnd::ResolvedMapStyle_P::dumpRuleNode(
    const std::shared_ptr<const RuleNode>& ruleNode,
    const bool rejectSupported,
    const QString& prefix) const
{
    QString dump;
    const auto builtinValueDefs = MapStyleBuiltinValueDefinitions::get();

    bool hasInputValueTests = false;
    bool hasDisable = false;
    for (const auto& ruleValueEntry : rangeOf(constOf(ruleNode->values)))
    {
        const auto valueDefId = ruleValueEntry.key();
        const auto& valueDef = getValueDefinitionById(valueDefId);

        if (valueDef->valueClass == MapStyleValueDefinition::Class::Input)
            hasInputValueTests = true;
        else if (valueDef->valueClass == MapStyleValueDefinition::Class::Output && valueDef->name == QLatin1String("disable"))
            hasDisable = true;

        if (hasInputValueTests && hasDisable)
            break;
    }

    if (hasInputValueTests)
    {
        dump += prefix + QLatin1String("local testPassed = true;\n");
        for (const auto& ruleValueEntry : rangeOf(constOf(ruleNode->values)))
        {
            const auto valueDefId = ruleValueEntry.key();
            const auto& valueDef = getValueDefinitionById(valueDefId);

            // Test only input values
            if (valueDef->valueClass != MapStyleValueDefinition::Class::Input)
                continue;

            const auto& resolvedRuleValue = ruleValueEntry.value();

            //bool evaluationResult = false;
            if (valueDefId == builtinValueDefs->id_INPUT_MINZOOM)
            {
                dump += prefix + QString(QLatin1String("if (testPassed) testPassed = (%1 <= %2);\n"))
                    .arg(dumpResolvedValue(resolvedRuleValue, MapStyleValueDataType::Integer))
                    .arg(valueDef->name);
            }
            else if (valueDefId == builtinValueDefs->id_INPUT_MAXZOOM)
            {
                dump += prefix + QString(QLatin1String("if (testPassed) testPassed = (%1 >= %2);\n"))
                    .arg(dumpResolvedValue(resolvedRuleValue, MapStyleValueDataType::Integer))
                    .arg(valueDef->name);
            }
            else if (valueDefId == builtinValueDefs->id_INPUT_ADDITIONAL)
            {
                dump += prefix + QString(QLatin1String("if (testPassed and inputMapObject) testPassed = (inputMapObject contains %1);\n"))
                    .arg(dumpResolvedValue(resolvedRuleValue, MapStyleValueDataType::String));
            }
            else if (valueDefId == builtinValueDefs->id_INPUT_TEST)
            {
                dump += prefix + QString(QLatin1String("if (testPassed) testPassed = (%1 == 1);\n"))
                    .arg(valueDef->name);
            }
            else if (valueDef->dataType == MapStyleValueDataType::Float)
            {
                dump += prefix + QString(QLatin1String("if (testPassed) testPassed = (%1 == %2);\n"))
                    .arg(dumpResolvedValue(resolvedRuleValue, MapStyleValueDataType::Float))
                    .arg(valueDef->name);
            }
            else if (valueDef->dataType == MapStyleValueDataType::Integer)
            {
                dump += prefix + QString(QLatin1String("if (testPassed) testPassed = (%1 == %2);\n"))
                    .arg(dumpResolvedValue(resolvedRuleValue, MapStyleValueDataType::Integer))
                    .arg(valueDef->name);
            }
            else if (valueDef->dataType == MapStyleValueDataType::Boolean)
            {
                dump += prefix + QString(QLatin1String("if (testPassed) testPassed = (%1 == %2);\n"))
                    .arg(dumpResolvedValue(resolvedRuleValue, MapStyleValueDataType::Boolean))
                    .arg(valueDef->name);
            }
            else if (valueDef->dataType == MapStyleValueDataType::String)
            {
                dump += prefix + QString(QLatin1String("if (testPassed) testPassed = (%1 == %2);\n"))
                    .arg(dumpResolvedValue(resolvedRuleValue, MapStyleValueDataType::String))
                    .arg(valueDef->name);
            }
            else
            {
                dump += prefix + QString(QLatin1String("// Unknown condition with '%1'\n"))
                    .arg(valueDef->name);
            }
        }
        if (rejectSupported)
            dump += prefix + QLatin1String("if (not testPassed) reject;\n");
        else
            dump += prefix + QLatin1String("if (not testPassed) exit;\n");
        dump += prefix + QLatin1String("\n");
    }

    if (hasDisable)
    {
        if (rejectSupported)
            dump += prefix + QLatin1String("if (disable) reject;\n");
        else
            dump += prefix + QLatin1String("if (disable) exit;\n");
        dump += prefix + QLatin1String("\n");
    }

    if (!ruleNode->isSwitch)
        dump += dumpRuleNodeOutputValues(ruleNode, prefix, true);

    if (!ruleNode->oneOfConditionalSubnodes.isEmpty())
    {
        dump += prefix + QLatin1String("local atLeastOneConditionalMatched = false;\n");
        for (const auto& oneOfConditionalSubnode : constOf(ruleNode->oneOfConditionalSubnodes))
        {
            dump += prefix + QLatin1String("if (not atLeastOneConditionalMatched):\n");
            dump += dumpRuleNode(oneOfConditionalSubnode, false, prefix + QLatin1String("\t"));
            dump += prefix + QLatin1String("\tatLeastOneConditionalMatched = true;\n");
        }
        if (ruleNode->isSwitch)
        {
            if (rejectSupported)
                dump += prefix + QLatin1String("if (not atLeastOneConditionalMatched) reject;\n");
            else
                dump += prefix + QLatin1String("if (not atLeastOneConditionalMatched) exit;\n");
        }
        dump += prefix + QLatin1String("\n");
    }

    if (ruleNode->isSwitch)
        dump += dumpRuleNodeOutputValues(ruleNode, prefix, false);
    
    if (!ruleNode->applySubnodes.isEmpty())
    {
        for (const auto& applySubnode : constOf(ruleNode->applySubnodes))
        {
            dump += prefix + QLatin1String("apply:\n");
            dump += dumpRuleNode(applySubnode, false, prefix + QLatin1String("\t"));
        }
        dump += prefix + QLatin1String("\n");
    }

    return dump;
}