/* * 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. */ bool isElement(const value& v) { if (!isList(v) || isNil(v) || element != car(v)) return false; return true; } /** * Returns true if a value is an attribute. */ bool isAttribute(const value& v) { if (!isList(v) || isNil(v) || attribute != car(v)) return false; return true; } /** * Returns the name of an attribute. */ const value attributeName(const list& l) { return cadr(l); } /** * Returns the value of an attribute. */ const value attributeValue(const list& l) { return caddr(l); } /** * Returns the name of an element. */ const value elementName(const list& l) { return cadr(l); } /** * Returns true if an element has children. */ const bool elementHasChildren(const list& l) { return !isNil(cddr(l)); } /** * Returns the children of an element. */ const list elementChildren(const list& l) { return cddr(l); } /** * Returns true if an element has a value. */ const bool elementHasValue(const list& l) { const list r = reverse(l); if (isSymbol(car(r))) return false; if(isList(car(r)) && !isNil((list)car(r)) && isSymbol(car(car(r)))) return false; return true; } /** * Returns the value of an element. */ const value elementValue(const list& l) { return car(reverse(l)); } /** * Convert an element to a value. */ const bool elementToValueIsList(const value& v) { if (!isList(v)) return false; const list l = v; return (isNil(l) || !isSymbol(car(l))); } const value elementToValue(const value& t) { const list elementsToValues(const list& e); // Convert an attribute if (isTaggedList(t, attribute)) return mklist(c_str(atsign + 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. */ const bool elementToValueIsSymbol(const value& v) { if (!isList(v)) return false; const list l = v; if (isNil(l)) return false; if (!isSymbol(car(l))) return false; return true; } const list elementToValueGroupValues(const value& v, const list& l) { if (isNil(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(cdr(v), cdr(car(l)))); return elementToValueGroupValues(g, cdr(l)); } const value g = mklist(car(v), cons(cdr(v), (list)cadr(car(l)))); return elementToValueGroupValues(g, cdr(l)); } const list elementsToValues(const list& e) { if (isNil(e)) return e; return elementToValueGroupValues(elementToValue(car(e)), elementsToValues(cdr(e))); } /** * Convert a value to an element. */ const value valueToElement(const value& t) { const list valuesToElements(const list& l); // Convert a name value pair if (isList(t) && !isNil((list)t) && isSymbol(car(t))) { const value n = car(t); const value v = isNil(cdr(t))? value() : cadr(t); // Convert a single value to an attribute or an element if (!isList(v)) { if (substr(n, 0, 1) == atsign) return mklist(attribute, substr(n, 1), v); return mklist(element, n, v); } // Convert a list value if (isNil((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. */ const list valuesToElements(const list& l) { if (isNil(l)) return l; return cons(valueToElement(car(l)), valuesToElements(cdr(l))); } /** * Returns a selector lambda function which can be used to filter * elements against the given element pattern. */ struct selectorLambda { const list select; selectorLambda(const list& s) : select(s) { } const bool evalSelect(const list& s, const list v) const { if (isNil(s)) return true; if (isNil(v)) return false; if (car(s) != car(v)) return false; return evalSelect(cdr(s), cdr(v)); } const bool operator()(const value& v) const { if (!isList(v)) return false; return evalSelect(select, v); } }; const lambda selector(const list s) { return selectorLambda(s); } /** * Returns the value of the attribute with the given name. */ struct filterAttribute { const value name; filterAttribute(const value& n) : name(n) { } const bool operator()(const value& v) const { return isAttribute(v) && attributeName((list)v) == name; } }; const value attributeValue(const value& name, const value& l) { const list f = filter(filterAttribute(name), list(l)); if (isNil(f)) return value(); return caddr(car(f)); } /** * Returns child elements with the given name. */ struct filterElement { const value name; filterElement(const value& n) : name(n) { } const bool operator()(const value& v) const { return isElement(v) && elementName((list)v) == name; } }; const value elementChildren(const value& name, const value& l) { return filter(filterElement(name), list(l)); } /** * Return the child element with the given name. */ const value elementChild(const value& name, const value& l) { const list f = elementChildren(name, l); if (isNil(f)) return value(); return car(f); } } #endif /* tuscany_element_hpp */