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