2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.validation.impl.util;
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.apache.commons.collections4.MapUtils;
25 import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder;
26 import org.openecomp.core.validation.errors.Messages;
27 import org.openecomp.core.validation.types.GlobalValidationContext;
28 import org.openecomp.sdc.datatypes.error.ErrorLevel;
29 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
30 import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes;
31 import org.openecomp.sdc.heat.datatypes.model.Output;
32 import org.openecomp.sdc.heat.datatypes.model.PolicyTypes;
33 import org.openecomp.sdc.heat.datatypes.model.PropertiesMapKeyTypes;
34 import org.openecomp.sdc.heat.datatypes.model.Resource;
35 import org.openecomp.sdc.heat.datatypes.model.ResourceReferenceFunctions;
36 import org.openecomp.sdc.heat.datatypes.model.ResourceTypeToMessageString;
37 import org.openecomp.sdc.heat.services.HeatStructureUtil;
39 import java.util.ArrayList;
40 import java.util.Collection;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.List;
46 import java.util.Objects;
50 public class ResourceValidationHeatValidator {
53 * Validate resource type.
55 * @param fileName the file name
56 * @param baseFileName the base file name
57 * @param securityGroupsNamesFromBaseFileOutputs the security groups names from base file outputs
58 * @param heatOrchestrationTemplate the heat orchestration template
59 * @param globalContext the global context
61 public static void validateResourceType(String fileName, String baseFileName,
62 Set<String> securityGroupsNamesFromBaseFileOutputs,
63 HeatOrchestrationTemplate heatOrchestrationTemplate,
64 GlobalValidationContext globalContext) {
65 Map<String, Resource> resourceMap =
66 heatOrchestrationTemplate.getResources() == null ? new HashMap<>()
67 : heatOrchestrationTemplate.getResources();
68 Map<String, Integer> numberOfVisitsInPort = new HashMap<>();
69 Set<String> resourcesNames = resourceMap.keySet();
70 Set<String> sharedResourcesFromOutputMap =
71 getSharedResourcesNamesFromOutputs(fileName, heatOrchestrationTemplate.getOutputs(),
73 boolean isBaseFile = baseFileName != null && fileName.equals(baseFileName);
75 Map<HeatResourcesTypes, List<String>> resourceTypeToNamesListMap = HeatResourcesTypes
76 .getListForResourceType(HeatResourcesTypes.NOVA_SERVER_GROUP_RESOURCE_TYPE,
77 HeatResourcesTypes.NEUTRON_SECURITY_GROUP_RESOURCE_TYPE,
78 HeatResourcesTypes.CONTRAIL_NETWORK_RULE_RESOURCE_TYPE);
80 initResourceTypeListWithItsResourcesNames(fileName, resourceTypeToNamesListMap, resourceMap,
81 sharedResourcesFromOutputMap, globalContext);
82 initVisitedPortsMap(fileName, resourceMap, numberOfVisitsInPort, globalContext);
85 for (Map.Entry<String, Resource> resourceEntry : resourceMap.entrySet()) {
86 String resourceType = resourceEntry.getValue().getType();
87 validateSecurityGroupsFromBaseOutput(fileName, resourceEntry, isBaseFile,
88 securityGroupsNamesFromBaseFileOutputs, globalContext);
89 checkResourceDependsOn(fileName, resourceEntry.getValue(), resourcesNames, globalContext);
91 if (Objects.isNull(resourceType)) {
92 globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder
93 .getErrorWithParameters(Messages.INVALID_RESOURCE_TYPE.getErrorMessage(), "null",
94 resourceEntry.getKey()));
96 HeatResourcesTypes heatResourceType = HeatResourcesTypes.findByHeatResource(resourceType);
98 if (heatResourceType != null) {
99 switch (heatResourceType) {
100 case NOVA_SERVER_RESOURCE_TYPE:
101 validateNovaServerResourceType(fileName, resourceEntry, numberOfVisitsInPort,
102 resourceTypeToNamesListMap
103 .get(HeatResourcesTypes.NOVA_SERVER_GROUP_RESOURCE_TYPE),
104 heatOrchestrationTemplate, globalContext);
107 case NOVA_SERVER_GROUP_RESOURCE_TYPE:
108 validateNovaServerGroupPolicy(fileName, resourceEntry, globalContext);
111 case RESOURCE_GROUP_RESOURCE_TYPE:
112 validateResourceGroupType(fileName, resourceEntry, globalContext);
115 case NEUTRON_PORT_RESOURCE_TYPE:
116 validateNeutronPortType(fileName, resourceEntry, resourceTypeToNamesListMap
117 .get(HeatResourcesTypes.NEUTRON_SECURITY_GROUP_RESOURCE_TYPE), globalContext);
120 case CONTRAIL_NETWORK_ATTACH_RULE_RESOURCE_TYPE:
121 validateContrailAttachPolicyType(resourceEntry, resourceTypeToNamesListMap
122 .get(HeatResourcesTypes.CONTRAIL_NETWORK_RULE_RESOURCE_TYPE));
127 if (HeatValidationService.isNestedResource(resourceType)) {
128 handleNestedResourceType(fileName, resourceEntry.getKey(), resourceEntry.getValue(),
135 checkForEmptyResourceNamesInMap(fileName,
136 CollectionUtils.isEmpty(securityGroupsNamesFromBaseFileOutputs), resourceTypeToNamesListMap,
138 handleOrphanPorts(fileName, numberOfVisitsInPort, globalContext);
142 private static void validateNovaServerResourceType(String fileName,
143 Map.Entry<String, Resource> resourceEntry,
144 Map<String, Integer> numberOfVisitsInPort,
145 List<String> serverGroupResourcesNames,
146 HeatOrchestrationTemplate
147 heatOrchestrationTemplate,
148 GlobalValidationContext globalContext) {
149 validateAssignedValueForImageOrFlavorFromNova(fileName, resourceEntry, globalContext);
150 validateNovaServerPortBinding(fileName, resourceEntry.getValue(), numberOfVisitsInPort,
152 validateAllServerGroupsPointedByServerExistAndDefined(fileName, resourceEntry,
153 serverGroupResourcesNames, heatOrchestrationTemplate, globalContext);
158 private static void handleNestedResourceType(String fileName, String resourceName,
160 GlobalValidationContext globalContext) {
161 validateAllPropertiesMatchNestedParameters(fileName, resourceName, resource, globalContext);
162 validateLoopsOfNestingFromFile(fileName, resource.getType(), globalContext);
166 private static void validateResourceGroupType(String fileName,
167 Map.Entry<String, Resource> resourceEntry,
168 GlobalValidationContext globalContext) {
169 Resource resourceDef = HeatStructureUtil
170 .getResourceDef(fileName, resourceEntry.getKey(), resourceEntry.getValue(), globalContext);
171 // validateResourceGroupTypeIsSupported(fileName, resourceEntry.getKey(),resourceDef.getType(),
173 if (resourceDef != null) {
174 if (Objects.nonNull(resourceDef.getType())
175 && HeatValidationService.isNestedResource(resourceDef.getType())) {
176 handleNestedResourceType(fileName, resourceDef.getType(), resourceDef, globalContext);
182 private static void validateAllPropertiesMatchNestedParameters(String fileName,
185 GlobalValidationContext
188 String resourceType = resource.getType();
189 if (globalContext.getFileContextMap().containsKey(resourceType)) {
190 Set<String> propertiesNames =
191 resource.getProperties() == null ? null : resource.getProperties().keySet();
192 if (CollectionUtils.isNotEmpty(propertiesNames)) {
193 HeatValidationService
194 .checkNestedParameters(fileName, resourceType, resourceName, globalContext,
198 globalContext.addMessage(resourceType, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
199 .getErrorWithParameters(Messages.MISSING_NESTED_FILE.getErrorMessage(), resourceType));
204 private static void validateAssignedValueForImageOrFlavorFromNova(String fileName,
205 Map.Entry<String, Resource>
207 GlobalValidationContext
210 Resource resource = resourceEntry.getValue();
211 Map<String, Object> propertiesMap = resource.getProperties();
212 if (propertiesMap.get(PropertiesMapKeyTypes.IMAGE.getKeyMap()) == null
213 && propertiesMap.get(PropertiesMapKeyTypes.FLAVOR.getKeyMap()) == null) {
214 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
215 .getErrorWithParameters(Messages.MISSING_IMAGE_AND_FLAVOR.getErrorMessage(),
216 resourceEntry.getKey()));
221 private static void validateLoopsOfNestingFromFile(String fileName, String resourceType,
222 GlobalValidationContext globalContext) {
223 List<String> filesInLoop = new ArrayList<>(Collections.singletonList(fileName));
224 if (HeatValidationService
225 .isNestedLoopExistInFile(fileName, resourceType, filesInLoop, globalContext)) {
226 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
227 .getErrorWithParameters(Messages.NESTED_LOOP.getErrorMessage(),
228 HeatValidationService.drawFilesLoop(filesInLoop)));
234 @SuppressWarnings("unchecked")
235 private static void validateNovaServerPortBinding(String fileName, Resource resource,
236 Map<String, Integer> numberOfVisitsInPort,
237 GlobalValidationContext globalContext) {
239 Map<String, Object> propertiesMap = resource.getProperties();
240 List<Object> networksList =
241 (List<Object>) propertiesMap.get(PropertiesMapKeyTypes.NETWORKS.getKeyMap());
243 if (CollectionUtils.isNotEmpty(networksList)) {
246 .filter(networkObject -> networkObject instanceof Map)
247 .forEach(networkObject -> {
248 Map<String, Object> portValueMap =
249 (Map<String, Object>) ((Map) networkObject).get("port");
250 if (MapUtils.isNotEmpty(portValueMap)) {
251 checkPortBindingFromMap(fileName, portValueMap, numberOfVisitsInPort, globalContext);
258 @SuppressWarnings("unchecked")
259 private static void validateAllServerGroupsPointedByServerExistAndDefined(String fileName,
260 Map.Entry<String, Resource> resourceEntry,
261 List<String> serverGroupNamesList,
262 HeatOrchestrationTemplate heatOrchestrationTemplate,
263 GlobalValidationContext globalContext) {
264 Map<String, Resource> resourcesMap = heatOrchestrationTemplate.getResources();
266 Map<String, Object> resourceProperties = resourceEntry.getValue().getProperties();
267 Map<String, Object> schedulerHintsMap = resourceProperties == null ? null
268 : (Map<String, Object>) resourceProperties
269 .get(ResourceReferenceFunctions.SCHEDULER_HINTS.getFunction());
271 if (MapUtils.isNotEmpty(schedulerHintsMap)) {
272 for (Object serverGroupMap : schedulerHintsMap.values()) {
273 Map<String, Object> currentServerMap = (Map<String, Object>) serverGroupMap;
274 String serverResourceName = currentServerMap == null ? null
275 : (String) currentServerMap.get(ResourceReferenceFunctions.GET_RESOURCE.getFunction());
276 Resource serverResource = serverResourceName == null || resourcesMap == null ? null
277 : resourcesMap.get(serverResourceName);
278 if (serverResource != null && !serverResource.getType()
279 .equals(HeatResourcesTypes.NOVA_SERVER_GROUP_RESOURCE_TYPE.getHeatResource())) {
280 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
281 .getErrorWithParameters(Messages.SERVER_NOT_DEFINED_FROM_NOVA.getErrorMessage(),
282 serverResourceName, resourceEntry.getKey()));
284 serverGroupNamesList.remove(serverResourceName);
292 @SuppressWarnings("unchecked")
293 private static void validateNovaServerGroupPolicy(String fileName,
294 Map.Entry<String, Resource> resourceEntry,
295 GlobalValidationContext globalContext) {
297 Resource resource = resourceEntry.getValue();
298 List<String> policiesList = resource.getProperties() == null ? null
299 : (List<String>) resource.getProperties().get("policies");
301 if (CollectionUtils.isNotEmpty(policiesList)) {
302 if (policiesList.size() == 1) {
303 String policy = policiesList.get(0);
304 if (!PolicyTypes.isGivenPolicyValid(policy)) {
305 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
306 .getErrorWithParameters(Messages.WRONG_POLICY_IN_SERVER_GROUP.getErrorMessage(),
307 resourceEntry.getKey()));
310 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
311 .getErrorWithParameters(Messages.WRONG_POLICY_IN_SERVER_GROUP.getErrorMessage(),
312 resourceEntry.getKey()));
318 private static void validateNeutronPortType(String filename,
319 Map.Entry<String, Resource> resourceEntry,
320 List<String> securityGroupResourceNameList,
321 GlobalValidationContext globalContext) {
322 validateAllSecurityGroupsAreUsed(filename, resourceEntry, securityGroupResourceNameList,
328 @SuppressWarnings("unchecked")
329 private static void validateAllSecurityGroupsAreUsed(String filename,
330 Map.Entry<String, Resource> resourceEntry,
331 List<String> securityGroupResourceNameList,
332 GlobalValidationContext globalContext) {
333 Map<String, Object> propertiesMap = resourceEntry.getValue().getProperties();
335 if (MapUtils.isEmpty(propertiesMap)) {
339 Object securityGroupsValue = propertiesMap.get("security_groups");
341 if (Objects.isNull(securityGroupsValue)) {
345 if (securityGroupsValue instanceof List) {
346 List<Object> securityGroupsListFromCurrResource =
347 (List<Object>) propertiesMap.get("security_groups");
348 for (Object securityGroup : securityGroupsListFromCurrResource) {
349 removeSecurityGroupNamesFromListByGivenFunction(filename,
350 ResourceReferenceFunctions.GET_RESOURCE.getFunction(), securityGroup,
351 securityGroupResourceNameList, globalContext);
357 private static void validateSecurityGroupsFromBaseOutput(String filename,
358 Map.Entry<String, Resource> resourceEntry,
360 Set<String> securityGroupNamesFromBaseOutput,
361 GlobalValidationContext globalContext) {
362 if (!isBaseFile && CollectionUtils.isNotEmpty(securityGroupNamesFromBaseOutput)) {
363 Map<String, Object> propertiesMap = resourceEntry.getValue().getProperties();
365 if (MapUtils.isEmpty(propertiesMap)) {
369 for (Map.Entry<String, Object> propertyEntry : propertiesMap.entrySet()) {
370 removeSecurityGroupNamesFromListByGivenFunction(filename,
371 ResourceReferenceFunctions.GET_PARAM.getFunction(), propertyEntry.getValue(),
372 securityGroupNamesFromBaseOutput, globalContext);
378 private static void removeSecurityGroupNamesFromListByGivenFunction(String filename,
380 Object securityGroup,
381 Collection<String> securityGroupResourceNameList,
382 GlobalValidationContext globalContext) {
383 Set<String> securityGroupsNamesFromFunction = HeatStructureUtil
384 .getReferencedValuesByFunctionName(filename, functionName, securityGroup, globalContext);
385 securityGroupsNamesFromFunction.forEach(securityGroupResourceNameList::remove);
389 @SuppressWarnings("unchecked")
390 private static void validateContrailAttachPolicyType(Map.Entry<String, Resource> resourceEntry,
391 List<String> networkPolicyResourceNames) {
392 Map<String, Object> propertiesMap = resourceEntry.getValue().getProperties();
394 if (MapUtils.isNotEmpty(propertiesMap)) {
395 Map<String, Object> policyMap = (Map<String, Object>) propertiesMap.get("policy");
396 if (MapUtils.isNotEmpty(policyMap)) {
397 List<Object> securityGroupList =
398 (List<Object>) policyMap.get(ResourceReferenceFunctions.GET_ATTR.getFunction());
399 //noinspection SuspiciousMethodCalls
400 if (CollectionUtils.isNotEmpty(securityGroupList)) {
401 //noinspection SuspiciousMethodCalls
402 networkPolicyResourceNames.remove(securityGroupList.get(0));
409 private static void getResourceNamesListFromSpecificResource(String filename,
410 List<String> resourcesNames,
411 HeatResourcesTypes heatResourcesType,
412 Map<String, Resource> resourcesMap,
413 Set<String> sharedResourcesFromOutputMap,
414 GlobalValidationContext globalContext) {
416 for (Map.Entry<String, Resource> resourceEntry : resourcesMap.entrySet()) {
417 String resourceType = resourceEntry.getValue().getType();
418 if (Objects.isNull(resourceType)) {
419 globalContext.addMessage(filename, ErrorLevel.WARNING, ErrorMessagesFormatBuilder
420 .getErrorWithParameters(Messages.INVALID_RESOURCE_TYPE.getErrorMessage(), null,
421 resourceEntry.getKey()));
423 if (resourceType.equals(heatResourcesType.getHeatResource())
424 && !isSharedResource(resourceEntry.getKey(), sharedResourcesFromOutputMap)) {
425 resourcesNames.add(resourceEntry.getKey());
432 private static boolean isSharedResource(String resourceName,
433 Set<String> sharedResourcesFromOutputMap) {
434 return !CollectionUtils.isEmpty(sharedResourcesFromOutputMap)
435 && sharedResourcesFromOutputMap.contains(resourceName);
439 * Handle not empty resource names list.
441 * @param fileName the file name
442 * @param resourcesNameList the resources name list
443 * @param securityOrServerGroup the security or server group
444 * @param globalContext the global context
446 public static void handleNotEmptyResourceNamesList(String fileName,
447 Collection<String> resourcesNameList,
448 String securityOrServerGroup,
449 GlobalValidationContext globalContext) {
450 if (CollectionUtils.isNotEmpty(resourcesNameList)) {
451 resourcesNameList.forEach(name ->
456 ErrorMessagesFormatBuilder
457 .getErrorWithParameters(
458 Messages.SERVER_OR_SECURITY_GROUP_NOT_IN_USE.getErrorMessage(),
459 securityOrServerGroup, name)));
464 private static void initVisitedPortsMap(String filename, Map<String, Resource> resourceMap,
465 Map<String, Integer> numberOfVisitsInPort,
466 GlobalValidationContext globalContext) {
467 for (Map.Entry<String, Resource> resourceEntry : resourceMap.entrySet()) {
468 String resourceType = resourceEntry.getValue().getType();
470 if (Objects.isNull(resourceType)) {
471 globalContext.addMessage(filename, ErrorLevel.WARNING, ErrorMessagesFormatBuilder
472 .getErrorWithParameters(Messages.INVALID_RESOURCE_TYPE.getErrorMessage(), "null",
473 resourceEntry.getKey()));
475 if (resourceType.equals(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource())) {
476 numberOfVisitsInPort.put(resourceEntry.getKey(), 0);
482 private static boolean checkIfPortWasVisited(String resourcePortName,
483 Map<String, Integer> numberOfVisitsInPort) {
484 return numberOfVisitsInPort.containsKey(resourcePortName)
485 && numberOfVisitsInPort.get(resourcePortName) == 1;
489 private static void incrementNumberOfVisitsInPort(String resourcePortName,
490 Map<String, Integer> numberOfVisitsInPort) {
491 if (numberOfVisitsInPort.containsKey(resourcePortName)) {
492 numberOfVisitsInPort.put(resourcePortName, numberOfVisitsInPort.get(resourcePortName) + 1);
497 private static void handleOrphanPorts(String fileName, Map<String, Integer> numberOfVisitsInPort,
498 GlobalValidationContext globalContext) {
502 .filter(entry -> entry.getValue() == 0)
508 ErrorMessagesFormatBuilder
509 .getErrorWithParameters(
510 Messages.PORT_NO_BIND_TO_ANY_NOVA_SERVER.getErrorMessage(),
514 @SuppressWarnings("unchecked")
515 private static void checkResourceDependsOn(String fileName, Resource resource,
516 Set<String> resourcesNames,
517 GlobalValidationContext globalContext) {
518 Object dependencies = resource.getDepends_on();
519 if (dependencies instanceof Collection) {
520 ((Collection<String>) dependencies)
522 .filter(resource_id -> !resourcesNames.contains(resource_id))
523 .forEach(resource_id -> globalContext.addMessage(fileName, ErrorLevel.ERROR,
524 ErrorMessagesFormatBuilder
525 .getErrorWithParameters(Messages.MISSING_RESOURCE_IN_DEPENDS_ON.getErrorMessage(),
526 (String) resource_id)));
527 } else if (dependencies instanceof String) {
528 if (!resourcesNames.contains(dependencies)) {
529 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
530 .getErrorWithParameters(Messages.MISSING_RESOURCE_IN_DEPENDS_ON.getErrorMessage(),
531 (String) dependencies));
537 private static void checkPortBindingFromMap(String fileName, Map<String, Object> portValueMap,
538 Map<String, Integer> numberOfVisitsInPort,
539 GlobalValidationContext globalContext) {
540 String resourcePortName =
541 (String) portValueMap.get(ResourceReferenceFunctions.GET_RESOURCE.getFunction());
542 if (checkIfPortWasVisited(resourcePortName, numberOfVisitsInPort)) {
543 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
544 .getErrorWithParameters(Messages.MORE_THAN_ONE_BIND_FROM_NOVA_TO_PORT.getErrorMessage(),
545 (String) portValueMap.get(ResourceReferenceFunctions.GET_RESOURCE.getFunction())));
547 incrementNumberOfVisitsInPort(resourcePortName, numberOfVisitsInPort);
552 private static void initResourceTypeListWithItsResourcesNames(String filename,
553 Map<HeatResourcesTypes, List<String>> resourcesTypesListMap,
554 Map<String, Resource> resourcesMap,
555 Set<String> sharedResourcesFromOutputsMap,
556 GlobalValidationContext globalContext) {
557 for (Map.Entry<HeatResourcesTypes, List<String>> resourcesTypesToListEntry
558 : resourcesTypesListMap.entrySet()) {
559 HeatResourcesTypes currentType = resourcesTypesToListEntry.getKey();
560 List<String> currNamesList = new ArrayList<>();
561 getResourceNamesListFromSpecificResource(filename, currNamesList, currentType, resourcesMap,
562 sharedResourcesFromOutputsMap, globalContext);
563 resourcesTypesListMap.put(currentType, currNamesList);
568 private static void checkForEmptyResourceNamesInMap(String fileName,
569 boolean isBaseFileContainPorts,
570 Map<HeatResourcesTypes, List<String>> resourcesTypesListMap,
571 GlobalValidationContext globalContext) {
572 if (isBaseFileContainPorts) {
573 for (Map.Entry<HeatResourcesTypes, List<String>> resourcesTypesListEntry
574 : resourcesTypesListMap.entrySet()) {
575 handleNotEmptyResourceNamesList(fileName, resourcesTypesListEntry.getValue(),
576 ResourceTypeToMessageString
577 .getTypeForMessageFromResourceType(resourcesTypesListEntry.getKey()),
584 private static Set<String> getSharedResourcesNamesFromOutputs(String filename,
585 Map<String, Output> outputsMap,
586 GlobalValidationContext globalContext) {
587 Set<String> sharedResources = new HashSet<>();
589 if (MapUtils.isEmpty(outputsMap)) {
593 for (Map.Entry<String, Output> outputEntry : outputsMap.entrySet()) {
594 Output output = outputEntry.getValue();
595 Object valueObject = output.getValue();
596 if (valueObject instanceof Map) {
597 Map<String, Object> outputValueMap = (Map<String, Object>) valueObject;
598 Object getResourceValue =
599 outputValueMap.get(ResourceReferenceFunctions.GET_RESOURCE.getFunction());
600 if (Objects.nonNull(getResourceValue)) {
601 if (getResourceValue instanceof String) {
602 String resourceName =
603 (String) outputValueMap.get(ResourceReferenceFunctions.GET_RESOURCE.getFunction());
604 sharedResources.add(resourceName);
606 globalContext.addMessage(filename, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
607 .getErrorWithParameters(Messages.INVALID_GET_RESOURCE_SYNTAX.getErrorMessage(),
608 getResourceValue.toString()));
615 return sharedResources;