49b878b1b0
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1079292 13f79535-47bb-0310-9956-ffa450edef68
304 lines
7.9 KiB
C++
304 lines
7.9 KiB
C++
/*
|
|
* 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 bool 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 = isNil(cdr<value>(t))? value() : 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 */
|