2 * Licensed to the University Corporation for Advanced Internet
3 * Development, Inc. (UCAID) under one or more contributor license
4 * agreements. See the NOTICE file distributed with this work for
5 * additional information regarding copyright ownership.
7 * UCAID licenses this file to you under the Apache License,
8 * Version 2.0 (the "License"); you may not use this file except
9 * in compliance with the License. You may obtain a copy of the
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17 * either express or implied. See the License for the specific
18 * language governing permissions and limitations under the License.
22 * shibsp/attribute/ExtensibleAttribute.cpp
24 * An Attribute whose values are arbitrary structures.
29 #include "attribute/ExtensibleAttribute.h"
30 #include "util/SPConstants.h"
32 #include <boost/algorithm/string/trim.hpp>
34 using namespace shibsp;
35 using namespace xmltooling;
39 SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in) {
40 return new ExtensibleAttribute(in);
44 ExtensibleAttribute::ExtensibleAttribute(const vector<string>& ids, const char* formatter) : Attribute(ids)
46 m_obj = Attribute::marshall();
47 m_obj.name("Extensible");
48 m_obj.addmember("_formatter").string(formatter);
51 ExtensibleAttribute::ExtensibleAttribute(DDF& in) : Attribute(in), m_obj(in.copy())
55 ExtensibleAttribute::~ExtensibleAttribute()
60 DDF ExtensibleAttribute::getValues()
65 size_t ExtensibleAttribute::valueCount() const
67 return m_obj.first().integer();
70 void ExtensibleAttribute::clearSerializedValues()
75 const char* ExtensibleAttribute::getString(size_t index) const
77 return m_obj.first()[static_cast<unsigned long>(index)].string();
80 const char* ExtensibleAttribute::getScope(size_t index) const
85 void ExtensibleAttribute::removeValue(size_t index)
87 Attribute::removeValue(index);
88 DDF vals = m_obj.first();
89 if (index < static_cast<size_t>(vals.integer()))
90 vals[static_cast<unsigned long>(index)].remove().destroy();
93 const vector<string>& ExtensibleAttribute::getSerializedValues() const
95 if (m_serialized.empty()) {
96 const char* formatter = m_obj["_formatter"].string();
98 string msg = formatter;
99 DDF val = m_obj.first().first();
100 while (!val.isnull()) {
102 static const char* legal="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_-.[]";
104 m_serialized.push_back(string());
105 string& processed = m_serialized.back();
107 string::size_type i=0,start=0;
108 while (start != string::npos && start < msg.length() && (i = msg.find("$",start)) != string::npos) {
110 processed += msg.substr(start, i-start); // append everything in between
111 start = i+1; // move start to the beginning of the token name
112 i = msg.find_first_not_of(legal, start); // find token delimiter
113 if (i == start) { // append a non legal character
114 processed += msg[start++];
118 string tag = msg.substr(start, (i==string::npos) ? i : i-start);
119 if (tag == "_string" && val.string()) {
120 processed += val.string();
124 DDF child = val.getmember(tag.c_str());
126 processed += child.string();
127 else if (child.isstruct() && child["_string"].string())
128 processed += child["_string"].string();
132 if (start != string::npos && start < msg.length())
133 processed += msg.substr(start,i); // append rest of string
134 boost::trim(processed);
136 val = m_obj.first().next();
140 return Attribute::getSerializedValues();
143 DDF ExtensibleAttribute::marshall() const
145 DDF ddf = Attribute::marshall();
146 ddf.name("Extensible");
147 ddf.addmember("_formatter").string(m_obj["_formatter"].string());
148 DDF val = m_obj.first().first();
149 while (!val.isnull()) {
150 DDF dup = val.copy();
151 ddf.first().add(dup);
152 val = m_obj.first().next();