3abe9331 |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Copyright (c) 2000-2015 Ericsson Telecom AB |
3 | // All rights reserved. This program and the accompanying materials |
4 | // are made available under the terms of the Eclipse Public License v1.0 |
5 | // which accompanies this distribution, and is available at |
6 | // http://www.eclipse.org/legal/epl-v10.html |
7 | /////////////////////////////////////////////////////////////////////////////// |
8 | #include "AttributeType.hh" |
9 | |
10 | AttributeType::AttributeType(ComplexType * a_complexType) |
11 | : SimpleType(a_complexType->getParser(), a_complexType->getModule(), c_unknown) |
12 | , isAnyAttr(false) |
13 | , useVal(optional) |
14 | , nameSpace(empty_string) |
15 | , used(false) |
16 | , origModule(a_complexType->getModule()) { |
17 | parent = a_complexType; |
18 | } |
19 | |
20 | AttributeType::AttributeType(const AttributeType & other) |
21 | : SimpleType(other) |
22 | , isAnyAttr(other.isAnyAttr) |
23 | , useVal(other.useVal) |
24 | , nameSpace(other.nameSpace) |
25 | , used(other.used) |
26 | , origModule(other.getModule()) { |
27 | } |
28 | |
29 | AttributeType::~AttributeType() { |
30 | |
31 | } |
32 | |
33 | void AttributeType::modifyValues() { |
34 | if (parser->getActualTagName() == n_attribute || parser->getActualTagName() == n_anyAttribute) { |
35 | ((ComplexType*) parent)->modifyAttributeParent(); |
36 | } |
37 | } |
38 | |
39 | void AttributeType::setTypeOfField(const Mstring& in) { |
40 | type.upload(in); |
41 | } |
42 | |
43 | void AttributeType::setNameOfField(const Mstring& in) { |
44 | name.upload(in); |
45 | } |
46 | |
47 | void AttributeType::setToAnyAttribute() { |
48 | isAnyAttr = true; |
49 | } |
50 | |
51 | void AttributeType::setFieldPath(const Mstring path) { |
52 | if (path.empty()) { |
53 | actualPath = getName().convertedValue; |
54 | } else { |
55 | if ((parent->getMinOccurs() != 1 || parent->getMaxOccurs() != 1) && parent->getName().list_extension) { |
56 | actualPath = path + Mstring("[-].") + getName().convertedValue; |
57 | } else { |
58 | actualPath = path + Mstring(".") + getName().convertedValue; |
59 | } |
60 | } |
61 | } |
62 | |
63 | void AttributeType::collectVariants(List<Mstring>& container) { |
64 | |
65 | if (variant.empty() && hidden_variant.empty()) { |
66 | return; |
67 | } |
68 | |
69 | if (!isVisible()) { |
70 | return; |
71 | } |
3f84031e |
72 | |
73 | enumeration.insertVariants(); |
3abe9331 |
74 | |
75 | for (List<Mstring>::iterator var2 = variant.end(); var2; var2 = var2->Prev) { |
76 | container.push_back(Mstring("variant (") + actualPath + Mstring(") ") + Mstring(var2->Data.c_str()) + Mstring(";\n")); |
77 | } |
78 | for (List<Mstring>::iterator hidden_var = hidden_variant.end(); hidden_var; hidden_var = hidden_var->Prev) { |
79 | container.push_back(Mstring("//variant (") + actualPath + Mstring(") ") + Mstring(hidden_var->Data.c_str()) + Mstring(";\n")); |
80 | } |
81 | } |
82 | |
83 | void AttributeType::nameConversion_names(QualifiedNames& used_ns) { |
84 | //Do not convert invisible field names |
85 | if (!visible || useVal == prohibited) { |
86 | return; |
87 | } |
88 | Mstring res, var(module->getTargetNamespace()); |
89 | QualifiedNames used_names = TTCN3ModuleInventory::getInstance().getTypenames(); |
90 | for (QualifiedNames::iterator n = used_ns.begin(); n; n = n->Next) { |
91 | used_names.push_back(n->Data); |
92 | } |
93 | QualifiedName q; |
94 | if(!used_names.empty()){ |
95 | q = used_names.back(); |
96 | }else { |
97 | q = QualifiedName(empty_string, empty_string); |
98 | } |
99 | XSDName2TTCN3Name(name.convertedValue, used_names, field_name, res, var); |
100 | name.convertedValue = res; |
101 | addVariant(V_onlyValue, var); |
102 | if (q.name != used_names.back().name) { |
103 | //If the name is converted then push to the used names list |
104 | used_ns.push_back(used_names.back()); |
105 | } |
106 | |
107 | for (List<SimpleType*>::iterator st = nameDepList.begin(); st; st = st->Next) { |
108 | st->Data->setTypeValue(res); |
109 | } |
110 | } |
111 | |
112 | void AttributeType::applyUseAttribute() { |
113 | if (isAnyAttr) { |
114 | return; |
115 | } |
116 | switch (useVal) { |
117 | case optional: |
118 | minOccurs = 0; |
119 | maxOccurs = 1; |
120 | break; |
121 | case required: |
122 | minOccurs = 1; |
123 | maxOccurs = 1; |
124 | break; |
125 | case prohibited: |
126 | minOccurs = 0; |
127 | maxOccurs = 0; |
128 | setInvisible(); |
129 | break; |
130 | } |
131 | isOptional = isOptional || (minOccurs == 0 && maxOccurs == 1); |
132 | } |
133 | |
134 | void AttributeType::applyNamespaceAttribute(VariantMode varLabel) { |
135 | List<Mstring> namespaces; |
136 | if (!nameSpace.empty()) { |
137 | expstring_t valueToSplitIntoTokens = mcopystr(nameSpace.c_str()); |
138 | char * token; |
139 | token = strtok(valueToSplitIntoTokens, " "); |
140 | while (token != NULL) { |
141 | namespaces.push_back(Mstring(token)); |
142 | token = strtok(NULL, " "); |
143 | } |
144 | Free(valueToSplitIntoTokens); |
145 | } |
146 | |
147 | Mstring any_ns; |
148 | bool first = true; |
149 | // Note: libxml2 will verify the namespace list according to the schema |
150 | // of XML Schema. It is either ##any, ##other, ##local, ##targetNamespace, |
151 | // or a list of (namespace reference | ##local | ##targetNamespace). |
152 | for (List<Mstring>::iterator ns = namespaces.begin(); ns; ns = ns->Next) { |
153 | static const Mstring xxany("##any"), xxother("##other"), xxlocal("##local"), |
154 | xxtargetNamespace("##targetNamespace"); |
155 | if (!first) any_ns += ", "; |
156 | |
157 | if (ns->Data == xxany) { |
158 | }// this must be the only element, nothing to add |
159 | else if (ns->Data == xxother) { // this must be the only element |
160 | if(first){ any_ns += " except "; } |
161 | any_ns += "unqualified"; |
162 | if (module->getTargetNamespace() != "NoTargetNamespace") { |
163 | any_ns += ", \'"; |
164 | any_ns += parent->getModule()->getTargetNamespace(); |
165 | any_ns += '\''; |
166 | } |
167 | }// The three cases below can happen multiple times |
168 | else { |
169 | if (first) any_ns += " from "; |
170 | // else a comma was already added |
171 | if (ns->Data == xxtargetNamespace) { |
172 | any_ns += '\''; |
173 | any_ns += parent->getModule()->getTargetNamespace(); |
174 | any_ns += '\''; |
175 | } else if (ns->Data == xxlocal) { |
176 | any_ns += "unqualified"; |
177 | } else { |
178 | any_ns += '\''; |
179 | any_ns += ns->Data; |
180 | any_ns += '\''; |
181 | } |
182 | } |
183 | if(!first || ns->Data != xxany){ |
184 | first = false; |
185 | } |
186 | } |
187 | |
188 | addVariant(varLabel, any_ns, true); |
189 | } |
190 | |
191 | void AttributeType::applyMinMaxOccursAttribute(unsigned long long min, unsigned long long max) { |
192 | minOccurs = min; |
193 | maxOccurs = max; |
194 | } |
195 | |
196 | void AttributeType::dump(unsigned int depth) const { |
197 | fprintf(stderr, "%*s %sField '%s' -> '%s' at %p\n", depth * 2, "", isVisible() ? "" : "(hidden)", |
198 | name.originalValueWoPrefix.c_str(), name.convertedValue.c_str(), (const void*) this); |
199 | fprintf(stderr, "%*s %s Type: \n", depth * 2, "", type.convertedValue.c_str()); |
200 | fprintf(stderr, "%*s type %s \n", (depth + 1) * 2, "", type.convertedValue.c_str()); |
201 | fprintf(stderr, "%*s (%llu .. %llu)\n", (depth + 1) * 2, "", minOccurs, maxOccurs); |
202 | fprintf(stderr, "%*s %d variants: ", (depth + 1) * 2, "", (int) variant.size()); |
203 | for (List<Mstring>::iterator var = variant.begin(); var; var = var->Next) { |
204 | fprintf(stderr, "%s, ", var->Data.c_str()); |
205 | } |
206 | fprintf(stderr, "\n%*s path =/%s/", (depth + 1) * 2, "", actualPath.c_str()); |
207 | } |
208 | |
209 | void AttributeType::printToFile(FILE* file, unsigned level) { |
210 | if (!isVisible()) { |
211 | return; |
212 | } |
213 | printComment(file, level); |
214 | indent(file, level); |
215 | if(enumeration.modified && hasVariant(Mstring("\"list\""))){ |
216 | printMinOccursMaxOccurs(file, false); |
217 | fprintf(file, "enumerated {\n"); |
218 | enumeration.sortFacets(); |
219 | enumeration.printToFile(file); |
220 | indent(file, level); |
221 | fprintf(file, "\n} %s", name.convertedValue.c_str()); |
222 | } else if (enumeration.modified) { |
223 | if (isFloatType(builtInBase)) { |
224 | fprintf(file, "%s %s (", type.convertedValue.c_str(), name.convertedValue.c_str()); |
225 | enumeration.sortFacets(); |
226 | enumeration.printToFile(file); |
227 | fputc(')', file); |
228 | } else { |
229 | fprintf(file, "enumerated {\n"); |
230 | enumeration.sortFacets(); |
231 | enumeration.printToFile(file); |
232 | fprintf(file, "\n"); |
233 | indent(file, level); |
234 | fprintf(file, "} %s", name.convertedValue.c_str()); |
235 | } |
236 | }else { |
237 | printMinOccursMaxOccurs(file, false); |
238 | int multiplicity = multi(module, getReference(), this); |
239 | if ((multiplicity > 1) && getReference().get_ref()) { |
240 | fprintf(file, "%s.", getReference().get_ref()->getModule()->getModulename().c_str()); |
241 | } |
242 | fprintf(file, "%s %s", type.convertedValue.c_str(), name.convertedValue.c_str()); |
243 | getPattern().printToFile(file); |
244 | getValue().printToFile(file); |
245 | getLength().printToFile(file); |
246 | } |
247 | if (isOptional || isAnyAttr) { |
248 | fprintf(file, " optional"); |
249 | } |
250 | } |