/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* $Rev$ $Date$ */ #ifndef tuscany_element_hpp #define tuscany_element_hpp /** * Functions to help represent data as lists of elements and attributes. */ #include "list.hpp" #include "value.hpp" namespace tuscany { /** * Tags used to tag lists of elements and attributes. */ const value attribute("attribute"); const value element("element"); const string atsign("@"); /** * Returns true if a value is an element. */ inline const bool isElement(const value& v) { if (!isList(v) || isNull(v) || element != car(v)) return false; return true; } /** * Returns true if a value is an attribute. */ inline const bool isAttribute(const value& v) { if (!isList(v) || isNull(v) || attribute != car(v)) return false; return true; } /** * Returns the name of an attribute. */ inline const value attributeName(const list& l) { return cadr(l); } /** * Returns the value of an attribute. */ inline const value attributeValue(const list& l) { return caddr(l); } /** * Returns the name of an element. */ inline const value elementName(const list& l) { return cadr(l); } /** * Returns true if an element has children. */ inline const bool elementHasChildren(const list& l) { return !isNull(cddr(l)); } /** * Returns the children of an element. */ inline const list elementChildren(const list& l) { return cddr(l); } /** * Returns true if an element has a value. */ inline const bool elementHasValue(const list& l) { const list r = reverse(l); if (isSymbol(car(r))) return false; if(isList(car(r)) && !isNull((list)car(r)) && isSymbol(car(car(r)))) return false; return true; } /** * Returns the value of an element. */ inline const value elementValue(const list& l) { return car(reverse(l)); } /** * Convert an element to a value. */ inline const bool elementToValueIsList(const value& v) { if (!isList(v)) return false; const list l = v; return (isNull(l) || !isSymbol(car(l))); } inline const value elementToValue(const value& t) { const list elementsToValues(const list& e); // Convert an attribute if (isTaggedList(t, attribute)) return mklist(c_str(atsign + (string)attributeName(t)), attributeValue(t)); // Convert an element if (isTaggedList(t, element)) { // Convert an element's value if (elementHasValue(t)) { // Convert a single value if (!elementToValueIsList(elementValue(t))) return mklist(elementName(t), elementValue(t)); // Convert a list value return cons(elementName(t), mklist(elementsToValues(elementValue(t)))); } // Convert an element's children return cons(elementName(t), elementsToValues(elementChildren(t))); } // Convert a value if (!isList(t)) return t; return elementsToValues(t); } /** * Convert a list of elements to a list of values. */ inline const bool elementToValueIsSymbol(const value& v) { if (!isList(v)) return false; const list l = v; if (isNull(l)) return false; if (!isSymbol(car(l))) return false; return true; } inline const list elementToValueGroupValues(const value& v, const list& l) { if (isNull(l) || !elementToValueIsSymbol(v) || !elementToValueIsSymbol(car(l))) return cons(v, l); if (car(car(l)) != car(v)) return cons(v, l); if (!elementToValueIsList(cadr(car(l)))) { const value g = mklist(car(v), mklist(isList(cadr(v))? (value)cdr(v) : cadr(v), isList(cadr(car(l)))? (value)cdr(car(l)) : cadr(car(l)))); return elementToValueGroupValues(g, cdr(l)); } const value g = mklist(car(v), cons(isList(cadr(v))? (value)cdr(v) : cadr(v), (list)cadr(car(l)))); return elementToValueGroupValues(g, cdr(l)); } inline const list elementsToValues(const list& e) { if (isNull(e)) return e; return elementToValueGroupValues(elementToValue(car(e)), elementsToValues(cdr(e))); } /** * Convert a value to an element. */ inline const value valueToElement(const value& t) { const list valuesToElements(const list& l); // Convert a name value pair if (isList(t) && !isNull((list)t) && isSymbol(car(t))) { const value n = car(t); const value v = isNull(cdr(t))? nilValue : cadr(t); // Convert a single value to an attribute or an element if (!isList(v)) { if (substr(n, 0, 1) == atsign) return mklist(attribute, c_str(substr(n, 1)), v); return mklist(element, n, v); } // Convert a list value if (isNull((list)v) || !isSymbol(car(v))) return cons(element, cons(n, mklist(valuesToElements(v)))); // Convert a nested name value pair value return cons(element, cons(n, valuesToElements(cdr(t)))); } // Convert a value if (!isList(t)) return t; return valuesToElements(t); } /** * Convert a list of values to a list of elements. */ inline const list valuesToElements(const list& l) { if (isNull(l)) return l; return cons(valueToElement(car(l)), valuesToElements(cdr(l))); } /** * Returns the value of the attribute with the given name. */ inline const value attributeValue(const value& name, const list& l) { const list f = filter([name](const value& v) { return isAttribute(v) && attributeName((list)v) == name; }, l); if (isNull(f)) return nilValue; return caddr(car(f)); } /** * Returns child elements with the given name. */ inline const list elementChildren(const value& name, const list& l) { return filter([name](const value& v) { return isElement(v) && elementName((list)v) == name; }, l); } /** * Return the child element with the given name. */ inline const value elementChild(const value& name, const list& l) { const list f = elementChildren(name, l); if (isNull(f)) return nilValue; return car(f); } } #endif /* tuscany_element_hpp */