Commit | Line | Data |
---|---|---|
970ed795 | 1 | /////////////////////////////////////////////////////////////////////////////// |
3abe9331 | 2 | // Copyright (c) 2000-2015 Ericsson Telecom AB |
970ed795 EL |
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 "TableConstraint.hh" | |
9 | #include "../Identifier.hh" | |
10 | #include "Object.hh" | |
11 | #include "Ref.hh" | |
12 | #include "TokenBuf.hh" | |
13 | // FIXME TableConstraint does not use Token or TokenBuf at all. | |
14 | // TokenBuf.hh just happens to drag in everything that TableConstraint needs. | |
15 | ||
16 | #include "../CompField.hh" | |
17 | ||
18 | namespace Asn { | |
19 | ||
20 | // ================================= | |
21 | // ===== AtNotation | |
22 | // ================================= | |
23 | ||
24 | AtNotation::AtNotation(int p_levels, FieldName *p_cids) | |
25 | : Node(), levels(p_levels), cids(p_cids), oc_fieldname(0), | |
26 | firstcomp(0), lastcomp(0) | |
27 | { | |
28 | if(!p_cids) | |
29 | FATAL_ERROR("NULL parameter: Asn::AtNotation::AtNotation()"); | |
30 | } | |
31 | ||
32 | AtNotation::AtNotation(const AtNotation& p) | |
33 | : Node(p), levels(p.levels), oc_fieldname(0), | |
34 | firstcomp(0), lastcomp(0) | |
35 | { | |
36 | cids=p.cids->clone(); | |
37 | } | |
38 | ||
39 | AtNotation::~AtNotation() | |
40 | { | |
41 | delete cids; | |
42 | delete oc_fieldname; | |
43 | } | |
44 | ||
45 | void AtNotation::set_oc_fieldname(const Identifier& p_oc_fieldname) | |
46 | { | |
47 | if(oc_fieldname) | |
48 | FATAL_ERROR("Asn::AtNotation::set_ocfieldname()"); | |
49 | oc_fieldname=p_oc_fieldname.clone(); | |
50 | } | |
51 | ||
52 | string AtNotation::get_dispname() const | |
53 | { | |
54 | string s('@'); | |
55 | for(int i=0; i<levels; i++) s+="."; | |
56 | s+=cids->get_dispname(); | |
57 | return s; | |
58 | } | |
59 | ||
60 | // ================================= | |
61 | // ===== AtNotations | |
62 | // ================================= | |
63 | ||
64 | AtNotations::AtNotations(const AtNotations& p) | |
65 | : Node(p) | |
66 | { | |
67 | for(size_t i=0; i<p.ans.size(); i++) | |
68 | ans.add(p.ans[i]->clone()); | |
69 | } | |
70 | ||
71 | AtNotations::~AtNotations() | |
72 | { | |
73 | for(size_t i=0; i<ans.size(); i++) delete ans[i]; | |
74 | ans.clear(); | |
75 | } | |
76 | ||
77 | void AtNotations::add_an(AtNotation *p_an) | |
78 | { | |
79 | if(!p_an) | |
80 | FATAL_ERROR("NULL parameter: Asn::AtNotations::add_an()"); | |
81 | ans.add(p_an); | |
82 | } | |
83 | ||
84 | // ================================= | |
85 | // ===== TableConstraint | |
86 | // ================================= | |
87 | ||
88 | TableConstraint::TableConstraint(Block *p_block_os, Block *p_block_ans) | |
89 | : Constraint(CT_TABLE), block_os(p_block_os), block_ans(p_block_ans), | |
90 | os(0), ans(0), consdtype(0), oc_fieldname(0) | |
91 | { | |
92 | if(!block_os) | |
93 | FATAL_ERROR("NULL parameter: Asn::TableConstraint::TableConstraint()"); | |
94 | } | |
95 | ||
96 | TableConstraint::TableConstraint(const TableConstraint& p) | |
97 | : Constraint(p), consdtype(0), oc_fieldname(0) | |
98 | { | |
99 | block_os=p.block_os?p.block_os->clone():0; | |
100 | block_ans=p.block_ans?p.block_ans->clone():0; | |
101 | os=p.os?p.os->clone():0; | |
102 | ans=p.ans?p.ans->clone():0; | |
103 | } | |
104 | ||
105 | TableConstraint::~TableConstraint() | |
106 | { | |
107 | delete block_os; | |
108 | delete block_ans; | |
109 | delete os; | |
110 | delete ans; | |
111 | } | |
112 | ||
113 | void TableConstraint::chk() | |
114 | { | |
115 | if(checked) return; | |
116 | checked=true; | |
117 | parse_blocks(); | |
118 | if(!my_type) | |
119 | FATAL_ERROR("Asn::TableConstraint::chk()"); | |
120 | os->set_my_scope(my_type->get_my_scope()); | |
121 | os->set_fullname(my_type->get_fullname()+".<tableconstraint-os>"); | |
122 | os->set_genname(my_type->get_genname_own(), string("os")); | |
123 | // search the constrained type (not the reference to it) | |
124 | consdtype=my_type; | |
125 | bool ok=false; | |
126 | while(true) { | |
127 | Type::typetype_t t=consdtype->get_typetype(); | |
128 | if(t==Type::T_OPENTYPE || t==Type::T_OCFT) { | |
129 | ok=true; | |
130 | break; | |
131 | } | |
132 | else if(t==Type::T_ERROR) { | |
133 | return; | |
134 | } | |
135 | else if(consdtype->is_ref()) | |
136 | consdtype=consdtype->get_type_refd(); | |
137 | else break; | |
138 | } | |
139 | if(!ok) { | |
140 | my_type->error("TableConstraint can only be applied to" | |
141 | " ObjectClassFieldType"); | |
142 | return; | |
143 | } | |
144 | // consdtype is ok | |
145 | if(consdtype->get_typetype()==Type::T_OCFT) { | |
146 | // componentrelationconstraint ignored for this... | |
147 | oc_fieldname=&consdtype->get_oc_fieldname(); | |
148 | os->set_my_governor(consdtype->get_my_oc()); | |
149 | os->chk(); | |
150 | } | |
151 | else if(consdtype->get_typetype()==Type::T_OPENTYPE) { | |
152 | consdtype->set_my_tableconstraint(this); | |
153 | oc_fieldname=&consdtype->get_oc_fieldname(); | |
154 | os->set_my_governor(consdtype->get_my_oc()); | |
155 | os->chk(); | |
156 | if(ans) { | |
157 | // componentrelationconstraint... | |
158 | // search the outermost textually enclosing seq, set or choice | |
159 | Type *outermostparent=0; | |
160 | Type *t_type=my_type; | |
161 | do { | |
162 | if(t_type->is_secho()) | |
163 | outermostparent=t_type; | |
164 | } while((t_type=t_type->get_parent_type())); | |
165 | if(!outermostparent) { | |
166 | my_type->error("Invalid use of ComponentRelationConstraint" | |
167 | " (cannot determine parent type)"); | |
168 | return; | |
169 | } | |
170 | outermostparent->set_opentype_outermost(); | |
171 | // set has_opentypes for enclosing types | |
172 | t_type=my_type; | |
173 | do { | |
174 | t_type=t_type->get_parent_type(); | |
175 | t_type->set_has_opentypes(); | |
176 | } while(t_type!=outermostparent); | |
177 | // checking of atnotations | |
178 | for(size_t i=0; i<ans->get_nof_ans(); i++) { | |
179 | AtNotation *an=ans->get_an_byIndex(i); | |
180 | Type *parent = NULL; | |
181 | if(an->get_levels()==0) parent=outermostparent; | |
182 | else { | |
183 | parent=my_type; | |
184 | for(int level=an->get_levels(); level>0; level--) { | |
185 | parent=parent->get_parent_type(); | |
186 | if(!parent) { | |
187 | my_type->error("Too many dots. This component has only" | |
188 | " %d parents.", an->get_levels()-level); | |
189 | return; | |
190 | } // ! parent | |
191 | } // for level | |
192 | } // not the outermost | |
193 | t_type=parent; | |
194 | an->set_firstcomp(parent); | |
195 | // component identifiers... do they exist? | |
196 | FieldName* cids=an->get_cids(); | |
197 | for(size_t j=0; j<cids->get_nof_fields(); j++) { | |
198 | if(!t_type->is_secho()) { | |
199 | my_type->error("Type `%s' is not a SEQUENCE, SET of CHOICE" | |
200 | " type.", t_type->get_fullname().c_str()); | |
201 | return; | |
202 | } // ! secho | |
203 | const Identifier *id=cids->get_field_byIndex(j); | |
204 | if(!t_type->has_comp_withName(*id)) { | |
205 | my_type->error("Type `%s' has no component with name `%s'.", | |
206 | t_type->get_fullname().c_str(), | |
207 | id->get_dispname().c_str()); | |
208 | return; | |
209 | } // no component with that name | |
210 | t_type=t_type->get_comp_byName(*id)->get_type(); | |
211 | } // for j | |
212 | an->set_lastcomp(t_type); | |
213 | /* check if the referenced component is constrained by the | |
214 | * same objectset... */ | |
215 | ok=false; | |
216 | do { | |
217 | // t_type->chk_constraints(); | |
218 | Constraints *t_cons=t_type->get_constraints(); | |
219 | if(!t_cons) break; | |
220 | t_cons->chk_table(); | |
221 | TableConstraint *t_tc=dynamic_cast<TableConstraint*> | |
222 | (t_cons->get_tableconstraint()); | |
223 | if(!t_tc) break; | |
224 | Type *t_ocft=t_tc->consdtype; | |
225 | if(t_ocft->get_typetype()!=Type::T_OCFT) break; | |
226 | an->set_oc_fieldname(t_ocft->get_oc_fieldname()); | |
227 | // is the same objectset? | |
228 | if(t_tc->os->get_refd_last()!=os->get_refd_last()) break; | |
229 | ok=true; | |
230 | } while(false); | |
231 | if(!ok) { | |
232 | my_type->error | |
233 | ("The referenced components must be value (set) fields" | |
234 | " constrained by the same objectset" | |
235 | " as the referencing component"); | |
236 | return; | |
237 | } | |
238 | } // for i | |
239 | // well, the atnotations seems to be ok, let's produce the | |
240 | // alternatives for the opentype | |
241 | Type *t_ot=consdtype; // opentype | |
242 | DEBUG(1, "Adding alternatives to open type `%s'", | |
243 | t_ot->get_fullname().c_str()); | |
244 | Objects *objs=os->get_refd_last()->get_objs(); | |
245 | for(size_t i=0; i<objs->get_nof_objs(); i++) { | |
246 | Obj_defn *obj=objs->get_obj_byIndex(i); | |
247 | if(!obj->has_fs_withName_dflt(*oc_fieldname)) | |
248 | continue; | |
249 | t_type=dynamic_cast<Type*> | |
250 | (obj->get_setting_byName_dflt(*oc_fieldname)); | |
251 | bool is_strange; | |
252 | const Common::Identifier& altname = t_type->get_otaltname(is_strange); | |
253 | if(!t_ot->has_comp_withName(altname)) { | |
254 | Type * otype = new Type(Type::T_REFDSPEC, t_type); | |
255 | otype->set_genname(t_type->get_genname_own()); | |
256 | t_ot->add_comp(new CompField(altname.clone(), | |
257 | otype)); | |
258 | const char *dispname_str = altname.get_dispname().c_str(); | |
259 | DEBUG(2, "Alternative `%s' added", dispname_str); | |
260 | if (is_strange) | |
261 | t_ot->warning("Strange alternative name (`%s') was added to " | |
262 | "open type `%s'", dispname_str, t_ot->get_fullname().c_str()); | |
263 | } // t_ot ! has the type | |
264 | } // for i (objs) | |
265 | t_ot->set_my_scope(t_ot->get_my_scope()); | |
266 | t_ot->set_fullname(t_ot->get_fullname()); | |
267 | t_ot->chk(); | |
268 | } // if ans | |
269 | } // opentype check | |
270 | ||
271 | // this cannot be inside another constraint | |
272 | if (my_parent) { | |
273 | error("Table constraint cannot be inside a %s", my_parent->get_name()); | |
274 | } | |
275 | ||
276 | } // member function | |
277 | ||
278 | void TableConstraint::parse_blocks() | |
279 | { | |
280 | if(block_os) { | |
281 | if(block_ans) { // ComponentRelationConstraint | |
282 | Node *node=block_os->parse(KW_Block_DefinedObjectSetBlock); | |
283 | os=dynamic_cast<ObjectSet*>(node); | |
284 | delete block_os; block_os=0; | |
285 | node=block_ans->parse(KW_Block_AtNotationList); | |
286 | ans=dynamic_cast<AtNotations*>(node); | |
287 | delete block_ans; block_ans=0; | |
288 | if(!ans) | |
289 | /* syntax error */ | |
290 | ans=new AtNotations(); | |
291 | } | |
292 | else { // SimpleTableConstraint | |
293 | Node *node=block_os->parse(KW_Block_ObjectSetSpec); | |
294 | os=dynamic_cast<ObjectSet*>(node); | |
295 | delete block_os; block_os=0; | |
296 | } | |
297 | if(!os) { | |
298 | /* syntax error */ | |
299 | os=new OS_defn(); | |
300 | } | |
301 | } | |
302 | } | |
303 | ||
304 | } // namespace Asn |