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