summaryrefslogtreecommitdiffstats
path: root/sca-cpp/branches/lightweight-sca/kernel/element.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/branches/lightweight-sca/kernel/element.hpp')
-rw-r--r--sca-cpp/branches/lightweight-sca/kernel/element.hpp304
1 files changed, 304 insertions, 0 deletions
diff --git a/sca-cpp/branches/lightweight-sca/kernel/element.hpp b/sca-cpp/branches/lightweight-sca/kernel/element.hpp
new file mode 100644
index 0000000000..27b5af8691
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/kernel/element.hpp
@@ -0,0 +1,304 @@
+/*
+ * 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>(isList(cadr<value>(v))? (value)cdr<value>(v) : cadr<value>(v), isList(cadr<value>(car(l)))? (value)cdr<value>(car(l)) : cadr<value>(car(l))));
+ return elementToValueGroupValues(g, cdr(l));
+ }
+ const value g = mklist<value>(car<value>(v), cons<value>(isList(cadr<value>(v))? (value)cdr<value>(v) : cadr<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, c_str(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 */