bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { // named param is one like LLView::Params::follows // unnamed param is like LLView::Params::rect - implicit const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); it != block_data.mUnnamedParams.end(); ++it) { param_handle_t param_handle = (*it)->mParamHandle; const Param* param = getParamFromHandle(param_handle); ParamDescriptor::inspect_func_t inspect_func = (*it)->mInspectFunc; if (inspect_func) { (*it)->mGeneration = parser.newParseGeneration(); name_stack.push_back(std::make_pair("", (*it)->mGeneration)); inspect_func(*param, parser, name_stack, (*it)->mMinCount, (*it)->mMaxCount); name_stack.pop_back(); } } for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it) { param_handle_t param_handle = it->second->mParamHandle; const Param* param = getParamFromHandle(param_handle); ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc; if (inspect_func) { // Ensure this param has not already been inspected bool duplicate = false; for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); it2 != block_data.mUnnamedParams.end(); ++it2) { if (param_handle == (*it2)->mParamHandle) { duplicate = true; break; } } if (!duplicate) { it->second->mGeneration = parser.newParseGeneration(); } name_stack.push_back(std::make_pair(it->first, it->second->mGeneration)); inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount); name_stack.pop_back(); } } return true; }
bool BaseBlock::submitValue(const Parser::name_stack_t& name_stack, Parser& p, bool silent) { if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()))) { if (!silent) { p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str())); } return false; } return true; }
void LLRNGWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values) { if (max_count == 0) return; name_stack_t non_empty_names; std::string attribute_name; for (name_stack_t::const_iterator it = stack.begin(); it != stack.end(); ++it) { const std::string& name = it->first; if (!name.empty()) { non_empty_names.push_back(*it); } } if (non_empty_names.empty()) return; for (name_stack_t::const_iterator it = non_empty_names.begin(); it != non_empty_names.end(); ++it) { if (!attribute_name.empty()) { attribute_name += "."; } attribute_name += it->first; } // singular attribute, e.g. <foo bar="1"/> if (non_empty_names.size() == 1 && max_count == 1) { if (mAttributesWritten.second.find(attribute_name) == mAttributesWritten.second.end()) { LLXMLNodePtr node = createCardinalityNode(mElementNode, min_count, max_count)->createChild("attribute", false); node->createChild("name", true)->setStringValue(attribute_name); node->createChild("data", false)->createChild("type", true)->setStringValue(type); mAttributesWritten.second.insert(attribute_name); } } // compound attribute else { std::string element_name; // traverse all but last element, leaving that as an attribute name name_stack_t::const_iterator end_it = non_empty_names.end(); end_it--; for (name_stack_t::const_iterator it = non_empty_names.begin(); it != end_it; ++it) { if (it != non_empty_names.begin()) { element_name += "."; } element_name += it->first; } elements_map_t::iterator found_it = mElementsWritten.find(element_name); // <choice> // <group> // <optional> // <attribute name="foo.bar"><data type="string"/></attribute> // </optional> // <optional> // <attribute name="foo.baz"><data type="integer"/></attribute> // </optional> // </group> // <element name="foo"> // <optional> // <attribute name="bar"><data type="string"/></attribute> // </optional> // <optional> // <attribute name="baz"><data type="string"/></attribute> // </optional> // </element> // <element name="outer.foo"> // <ref name="foo"/> // </element> // </choice> if (found_it != mElementsWritten.end()) { // reuse existing element LLXMLNodePtr choice_node = found_it->second.first; // attribute with this name not already written? if (found_it->second.second.find(attribute_name) == found_it->second.second.end()) { // append to <group> LLXMLNodePtr node = choice_node->mChildren->head; node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); node->createChild("name", true)->setStringValue(attribute_name); addTypeNode(node, type, possible_values); // append to <element> node = choice_node->mChildren->head->mNext->mChildren->head; node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); node->createChild("name", true)->setStringValue(non_empty_names.back().first); addTypeNode(node, type, possible_values); // append to <element> //node = choice_node->mChildren->head->mNext->mNext->mChildren->head; //node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); //node->createChild("name", true)->setStringValue(non_empty_names.back().first); //addTypeNode(node, type, possible_values); found_it->second.second.insert(attribute_name); } } else { LLXMLNodePtr choice_node = mElementNode->createChild("choice", false); LLXMLNodePtr node = choice_node->createChild("group", false); node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); node->createChild("name", true)->setStringValue(attribute_name); addTypeNode(node, type, possible_values); node = choice_node->createChild("optional", false); node = node->createChild("element", false); node->createChild("name", true)->setStringValue(element_name); node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); node->createChild("name", true)->setStringValue(non_empty_names.back().first); addTypeNode(node, type, possible_values); //node = choice_node->createChild("optional", false); //node = node->createChild("element", false); //node->createChild("name", true)->setStringValue(mDefinitionName + "." + element_name); //node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); //node->createChild("name", true)->setStringValue(non_empty_names.back().first); //addTypeNode(node, type, possible_values); attribute_data_t& attribute_data = mElementsWritten[element_name]; attribute_data.first = choice_node; attribute_data.second.insert(attribute_name); } } }
bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { // named param is one like LLView::Params::follows // unnamed param is like LLView::Params::rect - implicit const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); it != block_data.mUnnamedParams.end(); ++it) { param_handle_t param_handle = (*it)->mParamHandle; const Param* param = getParamFromHandle(param_handle); ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc; if (serialize_func) { const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; // each param descriptor remembers its serial number // so we can inspect the same param under different names // and see that it has the same number (*it)->mGeneration = parser.newParseGeneration(); name_stack.push_back(std::make_pair("", (*it)->mGeneration)); serialize_func(*param, parser, name_stack, diff_param); name_stack.pop_back(); } } for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it) { param_handle_t param_handle = it->second->mParamHandle; const Param* param = getParamFromHandle(param_handle); ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc; if (serialize_func && param->anyProvided()) { // Ensure this param has not already been serialized // Prevents <rect> from being serialized as its own tag. bool duplicate = false; for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); it2 != block_data.mUnnamedParams.end(); ++it2) { if (param_handle == (*it2)->mParamHandle) { duplicate = true; break; } } //FIXME: for now, don't attempt to serialize values under synonyms, as current parsers // don't know how to detect them if (duplicate) { continue; } if (!duplicate) { it->second->mGeneration = parser.newParseGeneration(); } name_stack.push_back(std::make_pair(it->first, it->second->mGeneration)); const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; serialize_func(*param, parser, name_stack, diff_param); name_stack.pop_back(); } } return true; }
void LLXSDWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values) { name_stack_t non_empty_names; std::string attribute_name; for (name_stack_t::const_iterator it = stack.begin(); it != stack.end(); ++it) { const std::string& name = it->first; if (!name.empty()) { non_empty_names.push_back(*it); } } for (name_stack_t::const_iterator it = non_empty_names.begin(); it != non_empty_names.end(); ++it) { if (!attribute_name.empty()) { attribute_name += "."; } attribute_name += it->first; } // only flag non-nested attributes as mandatory, nested attributes have variant syntax // that can't be properly constrained in XSD // e.g. <foo mandatory.value="bar"/> vs <foo><mandatory value="bar"/></foo> bool attribute_mandatory = min_count == 1 && max_count == 1 && non_empty_names.size() == 1; // don't bother supporting "Multiple" params as xml attributes if (max_count <= 1) { // add compound attribute to root node addAttributeToSchema(mAttributeNode, attribute_name, type, attribute_mandatory, possible_values); } // now generated nested elements for compound attributes if (non_empty_names.size() > 1 && !attribute_mandatory) { std::string element_name; // traverse all but last element, leaving that as an attribute name name_stack_t::const_iterator end_it = non_empty_names.end(); end_it--; for (name_stack_t::const_iterator it = non_empty_names.begin(); it != end_it; ++it) { if (it != non_empty_names.begin()) { element_name += "."; } element_name += it->first; } std::string short_attribute_name = non_empty_names.back().first; LLXMLNodePtr complex_type_node; // find existing element node here, starting at tail of child list if (mElementNode->mChildren.notNull()) { for(LLXMLNodePtr element = mElementNode->mChildren->tail; element.notNull(); element = element->mPrev) { std::string name; if(element->getAttributeString("name", name) && name == element_name) { complex_type_node = element->mChildren->head; break; } } } //create complex_type node // //<xs:element // maxOccurs="1" // minOccurs="0" // name="name"> // <xs:complexType> // </xs:complexType> //</xs:element> if(complex_type_node.isNull()) { complex_type_node = mElementNode->createChild("xs:element", false); complex_type_node->createChild("minOccurs", true)->setIntValue(min_count); complex_type_node->createChild("maxOccurs", true)->setIntValue(max_count); complex_type_node->createChild("name", true)->setStringValue(element_name); complex_type_node = complex_type_node->createChild("xs:complexType", false); } addAttributeToSchema(complex_type_node, short_attribute_name, type, false, possible_values); } }