[SDC-243] jtosca for port mirroring
[sdc/sdc-tosca.git] / src / main / java / org / openecomp / sdc / toscaparser / api / NodeTemplate.java
1 package org.openecomp.sdc.toscaparser.api;
2
3 import java.util.ArrayList;
4 import java.util.LinkedHashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import org.openecomp.sdc.toscaparser.api.elements.*;
9 import org.openecomp.sdc.toscaparser.api.utils.CopyUtils;
10 import org.openecomp.sdc.toscaparser.api.utils.ThreadLocalsHolder;
11
12 public class NodeTemplate extends EntityTemplate {
13         
14         private LinkedHashMap<String,Object> templates;
15         private LinkedHashMap<String,Object> customDef;
16         private ArrayList<RelationshipTemplate> availableRelTpls;
17         private LinkedHashMap<String,Object> availableRelTypes;
18         private LinkedHashMap<NodeTemplate,RelationshipType> related;
19         private ArrayList<RelationshipTemplate> relationshipTpl;
20         private LinkedHashMap<RelationshipType,NodeTemplate> _relationships;
21         private SubstitutionMappings subMappingToscaTemplate;
22         private Metadata metadata;
23
24         private static final String METADATA = "metadata";
25
26         @SuppressWarnings("unchecked")
27         public NodeTemplate(String name,
28                                                 LinkedHashMap<String,Object> ntnodeTemplates,
29                                                 LinkedHashMap<String,Object> ntcustomDef,
30                                                 ArrayList<RelationshipTemplate> ntavailableRelTpls,
31                                                 LinkedHashMap<String,Object> ntavailableRelTypes) {
32                 
33        super(name, (LinkedHashMap<String,Object>)ntnodeTemplates.get(name), "node_type", ntcustomDef);
34
35        templates = ntnodeTemplates;
36        _validateFields((LinkedHashMap<String,Object>)templates.get(name));
37        customDef = ntcustomDef;
38        related = new LinkedHashMap<NodeTemplate,RelationshipType>();
39        relationshipTpl = new ArrayList<RelationshipTemplate>();
40        availableRelTpls = ntavailableRelTpls;
41        availableRelTypes = ntavailableRelTypes;
42        _relationships = new LinkedHashMap<RelationshipType,NodeTemplate>();
43        subMappingToscaTemplate = null;
44        metadata = _metaData();
45         }
46
47         @SuppressWarnings("unchecked")
48         public LinkedHashMap<RelationshipType,NodeTemplate> getRelationships() {
49                 if(_relationships.isEmpty()) {
50                         List<RequirementAssignment> requires = getRequirements().getAll();
51                         if(requires != null && requires instanceof List) {
52                                 for(RequirementAssignment r: requires) {
53                                         LinkedHashMap<RelationshipType,NodeTemplate> explicit = _getExplicitRelationship(r);
54                                         if(explicit != null) {
55                                                 // _relationships.putAll(explicit)...
56                                                 for(Map.Entry<RelationshipType,NodeTemplate> ee: explicit.entrySet()) {
57                                                         _relationships.put(ee.getKey(), ee.getValue());
58                                                 }
59                                         }
60                                 }
61                         }
62                 }
63                 return _relationships;
64         }
65
66         @SuppressWarnings("unchecked")
67         private LinkedHashMap<RelationshipType,NodeTemplate> _getExplicitRelationship(RequirementAssignment req) {
68         // Handle explicit relationship
69
70         // For example,
71         // - req:
72         //     node: DBMS
73         //     relationship: tosca.relationships.HostedOn
74                 
75                 LinkedHashMap<RelationshipType,NodeTemplate> explicitRelation = new LinkedHashMap<RelationshipType,NodeTemplate>();
76                 String node = req.getNodeTemplateName();
77                 
78                 if(node != null && !node.isEmpty()) {
79             //msg = _('Lookup by TOSCA types is not supported. '
80             //        'Requirement for "%s" can not be full-filled.') % self.name
81                         boolean bFound = false;
82                         for(String k: EntityType.TOSCA_DEF.keySet()) {
83                                 if(k.equals(node)) {
84                                         bFound = true;
85                                         break;
86                                 }
87                         }
88                         if(bFound || customDef.get(node) != null) {
89                 ThreadLocalsHolder.getCollector().appendException(String.format(
90                                 "NotImplementedError: Lookup by TOSCA types is not supported. Requirement for \"%s\" can not be full-filled",
91                                 getName()));
92                 return null;
93                         }
94                         if(templates.get(node) == null) {
95                 ThreadLocalsHolder.getCollector().appendException(String.format(
96                         "KeyError: Node template \"%s\" was not found",node));
97                     return null;
98                         }
99                         NodeTemplate relatedTpl = new NodeTemplate(node,templates,customDef,null,null);
100                         Object relationship = req.getRelationship();
101                         String relationshipString = null;
102 //                      // here relationship can be a string or a LHM with 'type':<relationship>
103
104                         // check if its type has relationship defined
105                         if(relationship == null) {
106                                 ArrayList<Object> parentReqs = ((NodeType)typeDefinition).getAllRequirements();
107                                 if(parentReqs == null) {
108                     ThreadLocalsHolder.getCollector().appendException("ValidationError: parent_req is null");
109                                 }
110                                 else {
111 //                                      for(String key: req.keySet()) {
112 //                                              boolean bFoundRel = false;
113                                                 for(Object rdo: parentReqs) {
114                                                         LinkedHashMap<String,Object> reqDict = (LinkedHashMap<String,Object>)rdo;
115                                                         LinkedHashMap<String,Object> relDict = (LinkedHashMap<String,Object>)reqDict.get(req.getName());
116                                                         if(relDict != null) {
117                                                                 relationship = relDict.get("relationship");
118                                                                 //BUG-python??? need to break twice?
119 //                                                              bFoundRel = true;
120                                                                 break;
121                                                         }
122                                                 }
123 //                                              if(bFoundRel) {
124 //                                                      break;
125 //                                              }
126 //                                      }
127                                 }
128                         }
129                         
130                         if(relationship != null) {
131                                 // here relationship can be a string or a LHM with 'type':<relationship>
132                                 if(relationship instanceof String) {
133                                         relationshipString = (String)relationship;
134                                 }
135                                 else if(relationship instanceof LinkedHashMap) {
136                                         relationshipString = (String)((LinkedHashMap<String,Object>)relationship).get("type");
137                                 }
138                                 
139                                 boolean foundRelationshipTpl = false;
140                                 // apply available relationship templates if found
141                                 if(availableRelTpls != null) {
142                                         for(RelationshipTemplate tpl: availableRelTpls) {
143                                                 if(tpl.getName().equals(relationshipString)) {
144                                                         RelationshipType rtype = new RelationshipType(tpl.getType(),null,customDef);
145                                                         explicitRelation.put(rtype, relatedTpl);
146                                                         tpl.setTarget(relatedTpl);
147                                                         tpl.setSource(this);
148                                                         relationshipTpl.add(tpl);
149                                                         foundRelationshipTpl = true;
150                                                 }
151                                         }
152                                 }
153                                 // create relationship template object.
154                                 String relPrfx = EntityType.RELATIONSHIP_PREFIX;
155                                 if(!foundRelationshipTpl) {
156                                         if(relationship instanceof LinkedHashMap) {
157                                 relationshipString = (String)((LinkedHashMap<String,Object>)relationship).get("type");
158                                 if(relationshipString != null) {
159                                         if(availableRelTypes != null && !availableRelTypes.isEmpty() && 
160                                                         availableRelTypes.get(relationshipString) != null) {
161                                                 ;
162                                         }
163                                         else if(!(relationshipString).startsWith(relPrfx)) {
164                                                 relationshipString = relPrfx + relationshipString;
165                                         }
166                                 }
167                                 else {
168                                                 ThreadLocalsHolder.getCollector().appendException(String.format(
169                                                                 "MissingRequiredFieldError: \"relationship\" used in template \"%s\" is missing required field \"type\"",
170                                                                 relatedTpl.getName()));
171                                 }
172                    }
173                    for(RelationshipType rtype: ((NodeType)typeDefinition).getRelationship().keySet()) {
174                            if(rtype.getType().equals(relationshipString)) {
175                                    explicitRelation.put(rtype,relatedTpl);
176                                    relatedTpl._addRelationshipTemplate(req,rtype.getType(),this);
177                            }
178                            else if(availableRelTypes != null && !availableRelTypes.isEmpty()) {
179                                    LinkedHashMap<String,Object> relTypeDef = (LinkedHashMap<String,Object>)availableRelTypes.get(relationshipString);
180                                    if(relTypeDef != null) {
181                                            String superType = (String)relTypeDef.get("derived_from");
182                                            if(superType != null) {
183                                                    if(!superType.startsWith(relPrfx)) {
184                                                            superType = relPrfx + superType;
185                                                    }
186                                                    if(rtype.getType().equals(superType)) {
187                                                    explicitRelation.put(rtype,relatedTpl);
188                                                    relatedTpl._addRelationshipTemplate(req,rtype.getType(),this);
189                                                    }
190                                            }
191                                    }
192                            }
193                    }
194                }
195                         }
196                 }
197                 return explicitRelation;
198         }
199
200         @SuppressWarnings("unchecked")
201         private void _addRelationshipTemplate(RequirementAssignment requirement, String rtype, NodeTemplate source) {
202                 LinkedHashMap<String,Object> req = new LinkedHashMap<>();
203                 req.put("relationship", CopyUtils.copyLhmOrAl(requirement.getRelationship()));
204                 req.put("type",rtype);
205                 RelationshipTemplate tpl = new RelationshipTemplate(req, rtype, customDef, this, source);
206                 relationshipTpl.add(tpl);
207         }
208
209         public ArrayList<RelationshipTemplate> getRelationshipTemplate() {
210                 return relationshipTpl;
211         }
212
213         void _addNext(NodeTemplate nodetpl,RelationshipType relationship) {
214                 related.put(nodetpl,relationship);
215         }
216         
217         public ArrayList<NodeTemplate> getRelatedNodes() {
218                 if(related.isEmpty()) { 
219                         for(Map.Entry<RelationshipType,NodeType> me: ((NodeType)typeDefinition).getRelationship().entrySet()) {
220                                 RelationshipType relation = me.getKey();
221                                 NodeType node = me.getValue();
222                                 for(String tpl: templates.keySet()) {
223                                         if(tpl.equals(node.getType())) {
224                                                 //BUG.. python has
225                                                 //    self.related[NodeTemplate(tpl)] = relation
226                                                 // but NodeTemplate doesn't have a constructor with just name...
227                                                 //????          
228                                                 related.put(new NodeTemplate(tpl,null,null,null,null),relation);
229                                         }
230                                 }
231                         }
232                 }
233                 return new ArrayList<NodeTemplate>(related.keySet());
234         }
235
236         public void validate(/*tosca_tpl=none is not used...*/) {
237         _validateCapabilities();
238         _validateRequirements();
239         _validateProperties(entityTpl,(NodeType)typeDefinition);
240         _validateInterfaces();
241         for(Property prop: getPropertiesObjects()) {
242                 prop.validate();
243         }
244         }
245
246         private Metadata _metaData() {
247                 if(entityTpl.get(METADATA) != null) {
248                         return new Metadata((Map<String,Object>)entityTpl.get(METADATA));
249                 }
250                 else {
251                         return null;
252                 }
253         }
254
255         @SuppressWarnings("unchecked")
256         private void _validateRequirements() {
257                 ArrayList<Object> typeRequires = ((NodeType)typeDefinition).getAllRequirements();
258                 ArrayList<String> allowedReqs = new ArrayList<>();
259                 allowedReqs.add("template");
260                 if(typeRequires != null) {
261                         for(Object to: typeRequires) {
262                                 LinkedHashMap<String,Object> treq = (LinkedHashMap<String,Object>)to;
263                                 for(Map.Entry<String,Object> me: treq.entrySet()) {
264                                         String key = me.getKey();
265                                         Object  value = me.getValue();
266                                         allowedReqs.add(key);
267                                         if(value instanceof LinkedHashMap) {
268                                                 allowedReqs.addAll(((LinkedHashMap<String,Object>)value).keySet());
269                                         }
270                                 }
271                                 
272                         }
273                 }
274                 
275                 ArrayList<Object> requires = (ArrayList<Object>)((NodeType)typeDefinition).getValue(REQUIREMENTS, entityTpl, false);
276                 if(requires != null) {
277                         if(!(requires instanceof ArrayList)) {
278                 ThreadLocalsHolder.getCollector().appendException(String.format(
279                         "TypeMismatchError: \"requirements\" of template \"%s\" are not of type \"list\"",name));
280                         }
281                         else {
282                 for(Object ro: requires) {
283                         LinkedHashMap<String,Object> req = (LinkedHashMap<String,Object>)ro;
284                         for(Map.Entry<String,Object> me: req.entrySet()) {
285                                 String rl = me.getKey();
286                                 Object vo = me.getValue();
287                                 if(vo instanceof LinkedHashMap) {
288                                 LinkedHashMap<String,Object> value = (LinkedHashMap<String,Object>)vo;
289                                         _validateRequirementsKeys(value);
290                                         _validateRequirementsProperties(value);
291                                         allowedReqs.add(rl);
292                                 }
293                         }
294                         _commonValidateField(req,allowedReqs,"requirements");
295                 }
296                         }
297                 }
298         }
299
300         @SuppressWarnings("unchecked")
301         private void _validateRequirementsProperties(LinkedHashMap<String,Object> reqs) {
302         // TO-DO(anyone): Only occurrences property of the requirements is
303         // validated here. Validation of other requirement properties are being
304         // validated in different files. Better to keep all the requirements
305         // properties validation here.
306                 for(Map.Entry<String,Object> me: reqs.entrySet()) {
307                         if(me.getKey().equals("occurrences")) {
308                                 ArrayList<Object> val = (ArrayList<Object>)me.getValue();
309                                 _validateOccurrences(val);
310                         }
311                         
312                 }
313         }
314         
315         private void _validateOccurrences(ArrayList<Object> occurrences) {
316         DataEntity.validateDatatype("list",occurrences,null,null,null);
317         for(Object val: occurrences) {
318             DataEntity.validateDatatype("Integer",val,null,null,null);
319         }
320         if(occurrences.size() != 2 || 
321            !(0 <= (int)occurrences.get(0)  && (int)occurrences.get(0) <= (int)occurrences.get(1)) ||
322            (int)occurrences.get(1) == 0) {
323             ThreadLocalsHolder.getCollector().appendException(String.format(
324                 "InvalidPropertyValueError: property has invalid value %s",occurrences.toString()));
325         }
326         }
327         
328         private void _validateRequirementsKeys(LinkedHashMap<String,Object> reqs) {
329                 for(String key: reqs.keySet()) {
330                         boolean bFound = false;
331                         for(int i=0; i< REQUIREMENTS_SECTION.length; i++) {
332                                 if(key.equals(REQUIREMENTS_SECTION[i])) {
333                                         bFound = true;
334                                         break;
335                                 }
336                         }
337                         if(!bFound) {
338                 ThreadLocalsHolder.getCollector().appendException(String.format(
339                         "UnknownFieldError: \"requirements\" of template \"%s\" contains unknown field \"%s\"",name,key));
340                         }
341                 }
342         }
343         
344         @SuppressWarnings("unchecked")
345         private void _validateInterfaces() {
346                 LinkedHashMap<String,Object> ifaces = (LinkedHashMap<String,Object>)
347                                 ((NodeType)typeDefinition).getValue(INTERFACES, entityTpl, false);
348                 if(ifaces != null) {
349                         for(Map.Entry<String,Object> me: ifaces.entrySet()) {
350                                 String iname = me.getKey();
351                                 LinkedHashMap<String,Object> value = (LinkedHashMap<String,Object>)me.getValue();
352                                 if(iname.equals(InterfacesDef.LIFECYCLE) || iname.equals(InterfacesDef.LIFECYCLE_SHORTNAME)) {
353                                         // maybe we should convert [] to arraylist???
354                                         ArrayList<String> inlo = new ArrayList<>();
355                                         for(int i=0; i<InterfacesDef.interfacesNodeLifecycleOperations.length; i++) {
356                                                 inlo.add(InterfacesDef.interfacesNodeLifecycleOperations[i]);
357                                         }
358                     _commonValidateField(value,inlo,"interfaces");
359                 }
360                                 else if(iname.equals(InterfacesDef.CONFIGURE) || iname.equals(InterfacesDef.CONFIGURE_SHORTNAME)) {
361                                         // maybe we should convert [] to arraylist???
362                                         ArrayList<String> irco = new ArrayList<>();
363                                         for(int i=0; i<InterfacesDef.interfacesRelationshipConfigureOperations.length; i++) {
364                                                 irco.add(InterfacesDef.interfacesRelationshipConfigureOperations[i]);
365                                         }
366                     _commonValidateField(value,irco,"interfaces");
367                 }
368                                 else if(((NodeType)typeDefinition).getInterfaces().keySet().contains(iname)) {
369                                         _commonValidateField(value,_collectCustomIfaceOperations(iname),"interfaces");
370                                 }
371                                 else {
372                     ThreadLocalsHolder.getCollector().appendException(String.format(
373                         "UnknownFieldError: \"interfaces\" of template \"%s\" contains unknown field %s",name,iname));
374                                 }
375                         }
376                 }
377         }
378         
379         @SuppressWarnings("unchecked")
380         private ArrayList<String> _collectCustomIfaceOperations(String iname) {
381                 ArrayList<String> allowedOperations = new ArrayList<>();
382                 LinkedHashMap<String,Object> nodetypeIfaceDef = (LinkedHashMap<String,Object>)((NodeType)
383                                                                                                                         typeDefinition).getInterfaces().get(iname);
384                 allowedOperations.addAll(nodetypeIfaceDef.keySet());
385                 String ifaceType = (String)nodetypeIfaceDef.get("type");
386                 if(ifaceType != null) {
387                         LinkedHashMap<String,Object> ifaceTypeDef = null;
388                         if(((NodeType)typeDefinition).customDef != null) {
389                                 ifaceTypeDef = (LinkedHashMap<String,Object>)((NodeType)typeDefinition).customDef.get(ifaceType);
390                         }
391                         if(ifaceTypeDef == null) {
392                                 ifaceTypeDef = (LinkedHashMap<String,Object>)EntityType.TOSCA_DEF.get(ifaceType);
393                         }
394                         allowedOperations.addAll(ifaceTypeDef.keySet());
395                 }
396                 // maybe we should convert [] to arraylist???
397                 ArrayList<String> idrw = new ArrayList<>();
398                 for(int i=0; i<InterfacesDef.INTERFACE_DEF_RESERVED_WORDS.length; i++) {
399                         idrw.add(InterfacesDef.INTERFACE_DEF_RESERVED_WORDS[i]);
400                 }
401                 allowedOperations.removeAll(idrw);
402                 return allowedOperations;
403         }
404
405         private void _validateFields(LinkedHashMap<String,Object> nodetemplate) {
406                 for(String ntname: nodetemplate.keySet()) {
407                         boolean bFound = false;
408                         for(int i=0; i< SECTIONS.length; i++) {
409                                 if(ntname.equals(SECTIONS[i])) {
410                                         bFound = true;
411                                         break;
412                                 }
413                         }
414                         if(!bFound) {
415                                 for(int i=0; i< SPECIAL_SECTIONS.length; i++) {
416                                         if(ntname.equals(SPECIAL_SECTIONS[i])) {
417                                                 bFound = true;
418                                                 break;
419                                         }
420                                 }
421                                 
422                         }
423                         if(!bFound) {
424                 ThreadLocalsHolder.getCollector().appendException(String.format(
425                             "UnknownFieldError: Node template \"%s\" has unknown field \"%s\"",name,ntname));
426                         }
427                 }
428         }
429         
430         // getter/setter
431
432         // multilevel nesting
433         public SubstitutionMappings getSubMappingToscaTemplate() {
434                 return subMappingToscaTemplate;
435         }
436         
437         public void setSubMappingToscaTemplate(SubstitutionMappings sm) {
438                 subMappingToscaTemplate = sm;
439         }
440         
441         public Metadata getMetaData() {
442                 return metadata;
443         }
444
445         public void setMetaData(Metadata metadata) {
446                 this.metadata = metadata;
447         }
448
449         @Override
450         public String toString() {
451                 return getName();
452         }
453
454 }
455
456 /*python
457
458 from toscaparser.common.exception import ExceptionCollector
459 from toscaparser.common.exception import InvalidPropertyValueError
460 from toscaparser.common.exception import MissingRequiredFieldError
461 from toscaparser.common.exception import TypeMismatchError
462 from toscaparser.common.exception import UnknownFieldError
463 from toscaparser.common.exception import ValidationError
464 from toscaparser.dataentity import DataEntity
465 from toscaparser.elements.interfaces import CONFIGURE
466 from toscaparser.elements.interfaces import CONFIGURE_SHORTNAME
467 from toscaparser.elements.interfaces import INTERFACE_DEF_RESERVED_WORDS
468 from toscaparser.elements.interfaces import InterfacesDef
469 from toscaparser.elements.interfaces import LIFECYCLE
470 from toscaparser.elements.interfaces import LIFECYCLE_SHORTNAME
471 from toscaparser.elements.relationshiptype import RelationshipType
472 from toscaparser.entity_template import EntityTemplate
473 from toscaparser.relationship_template import RelationshipTemplate
474 from toscaparser.utils.gettextutils import _
475
476 log = logging.getLogger('tosca')
477
478
479 class NodeTemplate(EntityTemplate):
480     '''Node template from a Tosca profile.'''
481     def __init__(self, name, node_templates, custom_def=None,
482                  available_rel_tpls=None, available_rel_types=None):
483         super(NodeTemplate, self).__init__(name, node_templates[name],
484                                            'node_type',
485                                            custom_def)
486         self.templates = node_templates
487         self._validate_fields(node_templates[name])
488         self.custom_def = custom_def
489         self.related = {}
490         self.relationship_tpl = []
491         self.available_rel_tpls = available_rel_tpls
492         self.available_rel_types = available_rel_types
493         self._relationships = {}
494         self.sub_mapping_tosca_template = None
495
496     @property
497     def relationships(self):
498         if not self._relationships:
499             requires = self.requirements
500             if requires and isinstance(requires, list):
501                 for r in requires:
502                     for r1, value in r.items():
503                         explicit = self._get_explicit_relationship(r, value)
504                         if explicit:
505                             for key, value in explicit.items():
506                                 self._relationships[key] = value
507         return self._relationships
508
509     def _get_explicit_relationship(self, req, value):
510         """Handle explicit relationship
511
512         For example,
513         - req:
514             node: DBMS
515             relationship: tosca.relationships.HostedOn
516         """
517         explicit_relation = {}
518         node = value.get('node') if isinstance(value, dict) else value
519
520         if node:
521             # TO-DO(spzala) implement look up once Glance meta data is available
522             # to find a matching TOSCA node using the TOSCA types
523             msg = _('Lookup by TOSCA types is not supported. '
524                     'Requirement for "%s" can not be full-filled.') % self.name
525             if (node in list(self.type_definition.TOSCA_DEF.keys())
526                or node in self.custom_def):
527                 ExceptionCollector.appendException(NotImplementedError(msg))
528                 return
529
530             if node not in self.templates:
531                 ExceptionCollector.appendException(
532                     KeyError(_('Node template "%s" was not found.') % node))
533                 return
534
535             related_tpl = NodeTemplate(node, self.templates, self.custom_def)
536             relationship = value.get('relationship') \
537                 if isinstance(value, dict) else None
538             # check if it's type has relationship defined
539             if not relationship:
540                 parent_reqs = self.type_definition.get_all_requirements()
541                 if parent_reqs is None:
542                     ExceptionCollector.appendException(
543                         ValidationError(message='parent_req is ' +
544                                         str(parent_reqs)))
545                 else:
546                     for key in req.keys():
547                         for req_dict in parent_reqs:
548                             if key in req_dict.keys():
549                                 relationship = (req_dict.get(key).
550                                                 get('relationship'))
551                                 break
552             if relationship:
553                 found_relationship_tpl = False
554                 # apply available relationship templates if found
555                 if self.available_rel_tpls:
556                     for tpl in self.available_rel_tpls:
557                         if tpl.name == relationship:
558                             rtype = RelationshipType(tpl.type, None,
559                                                      self.custom_def)
560                             explicit_relation[rtype] = related_tpl
561                             tpl.target = related_tpl
562                             tpl.source = self
563                             self.relationship_tpl.append(tpl)
564                             found_relationship_tpl = True
565                 # create relationship template object.
566                 rel_prfx = self.type_definition.RELATIONSHIP_PREFIX
567                 if not found_relationship_tpl:
568                     if isinstance(relationship, dict):
569                         relationship = relationship.get('type')
570                         if relationship:
571                             if self.available_rel_types and \
572                                relationship in self.available_rel_types.keys():
573                                 pass
574                             elif not relationship.startswith(rel_prfx):
575                                 relationship = rel_prfx + relationship
576                         else:
577                             ExceptionCollector.appendException(
578                                 MissingRequiredFieldError(
579                                     what=_('"relationship" used in template '
580                                            '"%s"') % related_tpl.name,
581                                     required=self.TYPE))
582                     for rtype in self.type_definition.relationship.keys():
583                         if rtype.type == relationship:
584                             explicit_relation[rtype] = related_tpl
585                             related_tpl._add_relationship_template(req,
586                                                                    rtype.type,
587                                                                    self)
588                         elif self.available_rel_types:
589                             if relationship in self.available_rel_types.keys():
590                                 rel_type_def = self.available_rel_types.\
591                                     get(relationship)
592                                 if 'derived_from' in rel_type_def:
593                                     super_type = \
594                                         rel_type_def.get('derived_from')
595                                     if not super_type.startswith(rel_prfx):
596                                         super_type = rel_prfx + super_type
597                                     if rtype.type == super_type:
598                                         explicit_relation[rtype] = related_tpl
599                                         related_tpl.\
600                                             _add_relationship_template(
601                                                 req, rtype.type, self)
602         return explicit_relation
603
604     def _add_relationship_template(self, requirement, rtype, source):
605         req = requirement.copy()
606         req['type'] = rtype
607         tpl = RelationshipTemplate(req, rtype, self.custom_def, self, source)
608         self.relationship_tpl.append(tpl)
609
610     def get_relationship_template(self):
611         return self.relationship_tpl
612
613     def _add_next(self, nodetpl, relationship):
614         self.related[nodetpl] = relationship
615
616     @property
617     def related_nodes(self):
618         if not self.related:
619             for relation, node in self.type_definition.relationship.items():
620                 for tpl in self.templates:
621                     if tpl == node.type:
622                         self.related[NodeTemplate(tpl)] = relation
623         return self.related.keys()
624
625     def validate(self, tosca_tpl=None):
626         self._validate_capabilities()
627         self._validate_requirements()
628         self._validate_properties(self.entity_tpl, self.type_definition)
629         self._validate_interfaces()
630         for prop in self.get_properties_objects():
631             prop.validate()
632
633     def _validate_requirements(self):
634         type_requires = self.type_definition.get_all_requirements()
635         allowed_reqs = ["template"]
636         if type_requires:
637             for treq in type_requires:
638                 for key, value in treq.items():
639                     allowed_reqs.append(key)
640                     if isinstance(value, dict):
641                         for key in value:
642                             allowed_reqs.append(key)
643
644         requires = self.type_definition.get_value(self.REQUIREMENTS,
645                                                   self.entity_tpl)
646         if requires:
647             if not isinstance(requires, list):
648                 ExceptionCollector.appendException(
649                     TypeMismatchError(
650                         what='"requirements" of template "%s"' % self.name,
651                         type='list'))
652             else:
653                 for req in requires:
654                     for r1, value in req.items():
655                         if isinstance(value, dict):
656                             self._validate_requirements_keys(value)
657                             self._validate_requirements_properties(value)
658                             allowed_reqs.append(r1)
659                     self._common_validate_field(req, allowed_reqs,
660                                                 'requirements')
661
662     def _validate_requirements_properties(self, requirements):
663         # TO-DO(anyone): Only occurrences property of the requirements is
664         # validated here. Validation of other requirement properties are being
665         # validated in different files. Better to keep all the requirements
666         # properties validation here.
667         for key, value in requirements.items():
668             if key == 'occurrences':
669                 self._validate_occurrences(value)
670                 break
671
672     def _validate_occurrences(self, occurrences):
673         DataEntity.validate_datatype('list', occurrences)
674         for value in occurrences:
675             DataEntity.validate_datatype('integer', value)
676         if len(occurrences) != 2 or not (0 <= occurrences[0] <= occurrences[1]) \
677                 or occurrences[1] == 0:
678             ExceptionCollector.appendException(
679                 InvalidPropertyValueError(what=(occurrences)))
680
681     def _validate_requirements_keys(self, requirement):
682         for key in requirement.keys():
683             if key not in self.REQUIREMENTS_SECTION:
684                 ExceptionCollector.appendException(
685                     UnknownFieldError(
686                         what='"requirements" of template "%s"' % self.name,
687                         field=key))
688
689     def _validate_interfaces(self):
690         ifaces = self.type_definition.get_value(self.INTERFACES,
691                                                 self.entity_tpl)
692         if ifaces:
693             for name, value in ifaces.items():
694                 if name in (LIFECYCLE, LIFECYCLE_SHORTNAME):
695                     self._common_validate_field(
696                         value, InterfacesDef.
697                         interfaces_node_lifecycle_operations,
698                         'interfaces')
699                 elif name in (CONFIGURE, CONFIGURE_SHORTNAME):
700                     self._common_validate_field(
701                         value, InterfacesDef.
702                         interfaces_relationship_configure_operations,
703                         'interfaces')
704                 elif name in self.type_definition.interfaces.keys():
705                     self._common_validate_field(
706                         value,
707                         self._collect_custom_iface_operations(name),
708                         'interfaces')
709                 else:
710                     ExceptionCollector.appendException(
711                         UnknownFieldError(
712                             what='"interfaces" of template "%s"' %
713                             self.name, field=name))
714
715     def _collect_custom_iface_operations(self, name):
716         allowed_operations = []
717         nodetype_iface_def = self.type_definition.interfaces[name]
718         allowed_operations.extend(nodetype_iface_def.keys())
719         if 'type' in nodetype_iface_def:
720             iface_type = nodetype_iface_def['type']
721             if iface_type in self.type_definition.custom_def:
722                 iface_type_def = self.type_definition.custom_def[iface_type]
723             else:
724                 iface_type_def = self.type_definition.TOSCA_DEF[iface_type]
725             allowed_operations.extend(iface_type_def.keys())
726         allowed_operations = [op for op in allowed_operations if
727                               op not in INTERFACE_DEF_RESERVED_WORDS]
728         return allowed_operations
729
730     def _validate_fields(self, nodetemplate):
731         for name in nodetemplate.keys():
732             if name not in self.SECTIONS and name not in self.SPECIAL_SECTIONS:
733                 ExceptionCollector.appendException(
734                     UnknownFieldError(what='Node template "%s"' % self.name,
735                                       field=name))*/