2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 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.
19 * SPDX-License-Identifier: Apache-2.0
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.pdp.xacml.application.common.std;
25 import com.att.research.xacml.api.Identifier;
26 import com.att.research.xacml.api.Obligation;
27 import com.att.research.xacml.api.Request;
28 import com.att.research.xacml.api.XACML3;
29 import com.att.research.xacml.std.IdentifierImpl;
30 import com.att.research.xacml.util.XACMLPolicyWriter;
31 import java.io.ByteArrayOutputStream;
32 import java.io.IOException;
33 import java.nio.charset.StandardCharsets;
34 import java.nio.file.Files;
35 import java.nio.file.Path;
36 import java.nio.file.Paths;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.Collection;
40 import java.util.Collections;
41 import java.util.HashMap;
42 import java.util.LinkedHashMap;
43 import java.util.LinkedList;
44 import java.util.List;
46 import java.util.Map.Entry;
48 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
49 import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
50 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
51 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
52 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
53 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
54 import org.apache.commons.lang3.tuple.Pair;
55 import org.onap.policy.common.endpoints.parameters.RestServerParameters;
56 import org.onap.policy.common.utils.coder.CoderException;
57 import org.onap.policy.common.utils.coder.StandardCoder;
58 import org.onap.policy.common.utils.coder.StandardYamlCoder;
59 import org.onap.policy.models.decisions.concepts.DecisionRequest;
60 import org.onap.policy.models.decisions.concepts.DecisionResponse;
61 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
62 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
63 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
64 import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
65 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
66 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
67 import org.onap.policy.pdp.xacml.application.common.OnapObligation;
68 import org.onap.policy.pdp.xacml.application.common.PolicyApiCaller;
69 import org.onap.policy.pdp.xacml.application.common.PolicyApiException;
70 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
71 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
72 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
73 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
74 import org.slf4j.Logger;
75 import org.slf4j.LoggerFactory;
78 * This standard matchable translator uses Policy Types that contain "matchable" field in order
79 * to translate policies.
81 * @author pameladragosh
84 public class StdMatchableTranslator extends StdBaseTranslator {
86 private static final Logger LOGGER = LoggerFactory.getLogger(StdMatchableTranslator.class);
87 private static final StandardYamlCoder standardYamlCoder = new StandardYamlCoder();
89 private final Map<ToscaPolicyTypeIdentifier, ToscaPolicyType> matchablePolicyTypes = new HashMap<>();
91 private RestServerParameters apiRestParameters;
93 private Path pathForData;
95 public StdMatchableTranslator() {
100 public Request convertRequest(DecisionRequest request) {
101 LOGGER.info("Converting Request {}", request);
103 return StdMatchablePolicyRequest.createInstance(request);
104 } catch (XacmlApplicationException e) {
105 LOGGER.error("Failed to convert DecisionRequest: {}", e);
108 // TODO throw exception
114 * scanObligations - scans the list of obligations and make appropriate method calls to process
117 * @param obligations Collection of obligation objects
118 * @param decisionResponse DecisionResponse object used to store any results from obligations.
121 protected void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse) {
123 // Implementing a crude "closest match" on the results, which means we will strip out
124 // any policies that has the lower weight than any of the others.
126 // Most likely these are "default" policies with a weight of zero, but not always.
128 // It is possible to have multiple policies with an equal weight, that is desired.
130 // So we need to track each policy type separately and the weights for each policy.
132 // policy-type -> weight -> List({policy-id, policy-content}, {policy-id, policy-content})
134 Map<String, Map<Integer, List<Pair<String, Map<String, Object>>>>> closestMatches = new LinkedHashMap<>();
136 // Now scan the list of obligations
138 for (Obligation obligation : obligations) {
139 Identifier obligationId = obligation.getId();
140 LOGGER.info("Obligation: {}", obligationId);
141 if (ToscaDictionary.ID_OBLIGATION_REST_BODY.equals(obligationId)) {
142 scanClosestMatchObligation(closestMatches, obligation);
144 LOGGER.warn("Unsupported Obligation Id {}", obligation.getId());
148 // Now add all the policies to the DecisionResponse
150 closestMatches.forEach((thePolicyType, weightMap) ->
151 weightMap.forEach((weight, policies) ->
152 policies.forEach(policy -> {
153 LOGGER.info("Policy {}", policy);
154 decisionResponse.getPolicies().put(policy.getLeft(), policy.getRight());
161 * scanClosestMatchObligation - scans for the obligation specifically holding policy
162 * contents and their details.
164 * @param closestMatches Map holding the current set of highest weight policy types
165 * @param Obligation Obligation object
167 protected void scanClosestMatchObligation(
168 Map<String, Map<Integer, List<Pair<String, Map<String, Object>>>>> closestMatches, Obligation obligation) {
170 // Create our OnapObligation object
172 OnapObligation onapObligation = new OnapObligation(obligation);
174 // All 4 *should* be there
176 if (onapObligation.getPolicyId() == null || onapObligation.getPolicyContent() == null
177 || onapObligation.getPolicyType() == null || onapObligation.getWeight() == null) {
178 LOGGER.error("Missing an expected attribute in obligation.");
184 String policyId = onapObligation.getPolicyId();
185 String policyType = onapObligation.getPolicyType();
186 Map<String, Object> policyContent = onapObligation.getPolicyContentAsMap();
187 int policyWeight = onapObligation.getWeight();
189 // If the Policy Type exists, get the weight map.
191 Map<Integer, List<Pair<String, Map<String, Object>>>> weightMap = closestMatches.get(policyType);
192 if (weightMap != null) {
194 // Only need to check first one - as we will ensure there is only one weight
196 Entry<Integer, List<Pair<String, Map<String, Object>>>> firstEntry =
197 weightMap.entrySet().iterator().next();
198 if (policyWeight < firstEntry.getKey()) {
200 // Existing policies have a greater weight, so we will not add it
202 LOGGER.info("{} is lesser weight {} than current policies, will not return it", policyWeight,
203 firstEntry.getKey());
204 } else if (firstEntry.getKey().equals(policyWeight)) {
206 // Same weight - we will add it
208 LOGGER.info("Same weight {}, adding policy", policyWeight);
209 firstEntry.getValue().add(Pair.of(policyId, policyContent));
212 // The weight is greater, so we need to remove the other policies
213 // and point to this one.
215 LOGGER.info("New policy has greater weight {}, replacing {}", policyWeight, firstEntry.getKey());
216 List<Pair<String, Map<String, Object>>> listPolicies = new LinkedList<>();
217 listPolicies.add(Pair.of(policyId, policyContent));
219 weightMap.put(policyWeight, listPolicies);
223 // Create a new entry
225 LOGGER.info("New entry {} weight {}", policyType, policyWeight);
226 List<Pair<String, Map<String, Object>>> listPolicies = new LinkedList<>();
227 listPolicies.add(Pair.of(policyId, policyContent));
228 Map<Integer, List<Pair<String, Map<String, Object>>>> newWeightMap = new LinkedHashMap<>();
229 newWeightMap.put(policyWeight, listPolicies);
230 closestMatches.put(policyType, newWeightMap);
235 public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
237 // Get the TOSCA Policy Type for this policy
239 Collection<ToscaPolicyType> toscaPolicyTypes = this.getPolicyTypes(toscaPolicy.getTypeIdentifier());
241 // If we don't have any TOSCA policy types, then we cannot know
242 // which properties are matchable.
244 if (toscaPolicyTypes.isEmpty()) {
245 throw new ToscaPolicyConversionException(
246 "Cannot retrieve Policy Type definition for policy " + toscaPolicy.getName());
249 // Policy name should be at the root
251 String policyName = toscaPolicy.getMetadata().get(POLICY_ID);
253 // Set it as the policy ID
255 PolicyType newPolicyType = new PolicyType();
256 newPolicyType.setPolicyId(policyName);
258 // Optional description
260 newPolicyType.setDescription(toscaPolicy.getDescription());
262 // There should be a metadata section
264 fillMetadataSection(newPolicyType, toscaPolicy.getMetadata());
266 // Set the combining rule
268 newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_FIRST_APPLICABLE.stringValue());
270 // Generate the TargetType - the policy should not be evaluated
271 // unless all the matchable properties it cares about are matched.
273 Pair<TargetType, Integer> pairGenerated = generateTargetType(toscaPolicy.getProperties(), toscaPolicyTypes);
274 newPolicyType.setTarget(pairGenerated.getLeft());
276 // Now represent the policy as Json
278 StandardCoder coder = new StandardCoder();
281 jsonPolicy = coder.encode(toscaPolicy);
282 } catch (CoderException e) {
283 throw new ToscaPolicyConversionException("Failed to encode policy to json", e);
286 // Add it as an obligation
288 addObligation(newPolicyType, policyName, jsonPolicy, pairGenerated.getRight(), toscaPolicy.getType());
290 // Now create the Permit Rule.
292 RuleType rule = new RuleType();
293 rule.setDescription("Default is to PERMIT if the policy matches.");
294 rule.setRuleId(policyName + ":rule");
295 rule.setEffect(EffectType.PERMIT);
296 rule.setTarget(new TargetType());
298 // The rule contains the Condition which adds logic for
299 // optional policy-type filtering.
301 rule.setCondition(generateConditionForPolicyType(toscaPolicy.getType()));
303 // Add the rule to the policy
305 newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule);
307 // Log output of the policy
309 try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
310 XACMLPolicyWriter.writePolicyFile(os, newPolicyType);
311 LOGGER.info("{}", os);
312 } catch (IOException e) {
313 LOGGER.error("Failed to create byte array stream", e);
318 return newPolicyType;
322 * For generating target type, we scan for matchable properties
323 * and use those to build the policy.
325 * @param properties Properties section of policy
326 * @param policyTypes Collection of policy Type to find matchable metadata
327 * @return {@code Pair<TargetType, Integer>} Returns a TargetType and a Total Weight of matchables.
329 protected Pair<TargetType, Integer> generateTargetType(Map<String, Object> properties,
330 Collection<ToscaPolicyType> policyTypes) {
331 TargetType targetType = new TargetType();
333 // Iterate the properties
335 int totalWeight = findMatchableFromMap(properties, policyTypes, targetType);
336 LOGGER.info("Total weight is {}", totalWeight);
337 return Pair.of(targetType, totalWeight);
340 @SuppressWarnings("unchecked")
341 protected int findMatchableFromList(List<Object> listProperties, Collection<ToscaPolicyType> policyTypes,
342 TargetType targetType) {
343 LOGGER.info("findMatchableFromList {}", listProperties);
345 for (Object property : listProperties) {
346 if (property instanceof List) {
347 totalWeight += findMatchableFromList((List<Object>) property, policyTypes, targetType);
348 } else if (property instanceof Map) {
349 totalWeight += findMatchableFromMap((Map<String, Object>) property, policyTypes, targetType);
355 protected int findMatchableFromMap(Map<String, Object> properties, Collection<ToscaPolicyType> policyTypes,
356 TargetType targetType) {
357 LOGGER.info("findMatchableFromMap {}", properties);
359 for (Entry<String, Object> entrySet : properties.entrySet()) {
361 // Is this a matchable property?
363 if (isMatchable(entrySet.getKey(), policyTypes)) {
364 LOGGER.info("Found matchable property {}", entrySet.getKey());
365 int weight = generateMatchable(targetType, entrySet.getKey(), entrySet.getValue());
366 LOGGER.info("Weight is {}", weight);
367 totalWeight += weight;
370 // Check if we need to search deeper
372 totalWeight += checkDeeperForMatchable(entrySet.getValue(), policyTypes, targetType);
378 @SuppressWarnings("unchecked")
379 protected int checkDeeperForMatchable(Object property, Collection<ToscaPolicyType> policyTypes,
380 TargetType targetType) {
381 if (property instanceof List) {
382 return findMatchableFromList((List<Object>) property, policyTypes, targetType);
383 } else if (property instanceof Map) {
384 return findMatchableFromMap((Map<String, Object>) property, policyTypes,
387 LOGGER.info("checkDeeperForMatchable not necessary for {}", property);
392 * isMatchable - Iterates through available TOSCA Policy Types to determine if a property
393 * should be treated as matchable.
395 * @param propertyName Name of property
396 * @param policyTypes Collection of TOSCA Policy Types to scan
397 * @return true if matchable
399 protected boolean isMatchable(String propertyName, Collection<ToscaPolicyType> policyTypes) {
400 for (ToscaPolicyType policyType : policyTypes) {
401 for (Entry<String, ToscaProperty> propertiesEntry : policyType.getProperties().entrySet()) {
402 if (checkIsMatchableProperty(propertyName, propertiesEntry)) {
406 // Check if its a list or map
408 if (isListOrMap(propertiesEntry.getValue().getType())
409 && ! isYamlType(propertiesEntry.getValue().getEntrySchema().getType())) {
410 LOGGER.info("need to search list or map");
414 LOGGER.info("isMatchable false for {}", propertyName);
418 private boolean isListOrMap(String type) {
419 return "list".equalsIgnoreCase(type) || "map".equalsIgnoreCase(type);
422 private boolean isYamlType(String type) {
423 return "string".equalsIgnoreCase(type) || "integer".equalsIgnoreCase(type) || "float".equalsIgnoreCase(type)
424 || "boolean".equalsIgnoreCase(type) || "timestamp".equalsIgnoreCase(type);
428 * checkIsMatchableProperty - checks the policy contents for matchable field. If the metadata doesn't exist,
429 * then definitely not. If the property doesn't exist, then definitely not. Otherwise need to have a metadata
430 * section with the matchable property set to true.
432 * @param propertyName String value of property
433 * @param propertiesEntry Section of the TOSCA Policy Type where properties and metadata sections are held
434 * @return true if matchable
436 protected boolean checkIsMatchableProperty(String propertyName, Entry<String, ToscaProperty> propertiesEntry) {
437 if (! propertiesEntry.getKey().equals(propertyName)
438 || propertiesEntry.getValue().getMetadata() == null) {
441 for (Entry<String, String> entrySet : propertiesEntry.getValue().getMetadata().entrySet()) {
442 if ("matchable".equals(entrySet.getKey()) && "true".equals(entrySet.getValue())) {
450 * generateMatchable - Given the object, generates list of MatchType objects and add them
451 * to the TargetType object. Returns a weight which is the number of AnyOf's generated. The
452 * weight can be used to further filter the results for "closest match".
454 * @param targetType TargetType object to add matches to
455 * @param key Property key
456 * @param value Object is the value - which can be a Collection or single Object
457 * @return int Weight of the match.
459 @SuppressWarnings("unchecked")
460 protected int generateMatchable(TargetType targetType, String key, Object value) {
462 if (value instanceof Collection) {
463 AnyOfType anyOf = generateMatches((Collection<Object>) value,
464 new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key));
465 if (! anyOf.getAllOf().isEmpty()) {
466 targetType.getAnyOf().add(anyOf);
470 AnyOfType anyOf = generateMatches(Arrays.asList(value),
471 new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key));
472 if (! anyOf.getAllOf().isEmpty()) {
473 targetType.getAnyOf().add(anyOf);
481 * generateMatches - Goes through the collection of objects, creates a MatchType object
482 * for each object and associates it with the given attribute Id. Returns the AnyOfType
483 * object that contains all the generated MatchType objects.
485 * @param matchables Collection of object to generate MatchType from
486 * @param attributeId Given attribute Id for each MatchType
487 * @return AnyOfType object
489 protected AnyOfType generateMatches(Collection<Object> matchables, Identifier attributeId) {
491 // This is our outer AnyOf - which is an OR
493 AnyOfType anyOf = new AnyOfType();
494 for (Object matchable : matchables) {
498 Identifier idFunction = XACML3.ID_FUNCTION_STRING_EQUAL;
499 Identifier idDatatype = XACML3.ID_DATATYPE_STRING;
501 // See if we are another datatype
503 // We should add datetime support. But to do that we need
504 // probably more metadata to describe how that would be translated.
506 if (matchable instanceof Integer) {
507 idFunction = XACML3.ID_FUNCTION_INTEGER_EQUAL;
508 idDatatype = XACML3.ID_DATATYPE_INTEGER;
509 } else if (matchable instanceof Double) {
510 idFunction = XACML3.ID_FUNCTION_DOUBLE_EQUAL;
511 idDatatype = XACML3.ID_DATATYPE_DOUBLE;
512 } else if (matchable instanceof Boolean) {
513 idFunction = XACML3.ID_FUNCTION_BOOLEAN_EQUAL;
514 idDatatype = XACML3.ID_DATATYPE_BOOLEAN;
517 // Create a match for this
519 MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
521 matchable.toString(),
524 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
526 // Now create an anyOf (OR)
528 anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(match));
534 * Get Policy Type definitions. This could be previously loaded, or could be
535 * stored in application path, or may need to be pulled from the API.
538 * @param policyTypeId Policy Type Id
539 * @return A list of PolicyTypes
541 private List<ToscaPolicyType> getPolicyTypes(ToscaPolicyTypeIdentifier policyTypeId) {
543 // Create identifier from the policy
545 ToscaPolicyTypeIdentifier typeId = new ToscaPolicyTypeIdentifier(policyTypeId);
547 // Find the Policy Type
549 ToscaPolicyType policyType = findPolicyType(typeId);
550 if (policyType == null) {
551 return Collections.emptyList();
554 // Create our return object
556 List<ToscaPolicyType> listTypes = new ArrayList<>();
557 listTypes.add(policyType);
559 // Look for parent policy types that could also contain matchable properties
561 ToscaPolicyType childPolicyType = policyType;
562 while (! childPolicyType.getDerivedFrom().startsWith("tosca.policies.Root")) {
564 // Create parent policy type id.
566 // We will have to assume the same version between child and the
567 // parent policy type it derives from.
569 // Or do we assume 1.0.0?
571 ToscaPolicyTypeIdentifier parentId = new ToscaPolicyTypeIdentifier(childPolicyType.getDerivedFrom(),
574 // Find the policy type
576 ToscaPolicyType parentPolicyType = findPolicyType(parentId);
577 if (parentPolicyType == null) {
579 // Probably would be best to throw an exception and
580 // return nothing back.
582 // But instead we will log a warning
584 LOGGER.warn("Missing parent policy type - proceeding anyway {}", parentId);
593 listTypes.add(parentPolicyType);
595 // Move to the next parent
597 childPolicyType = parentPolicyType;
603 * findPolicyType - given the ToscaPolicyTypeIdentifier, finds it in memory, or
604 * then tries to find it either locally on disk or pull it from the Policy
605 * Lifecycle API the given TOSCA Policy Type.
607 * @param policyTypeId ToscaPolicyTypeIdentifier to find
608 * @return ToscaPolicyType object. Can be null if failure.
610 private ToscaPolicyType findPolicyType(ToscaPolicyTypeIdentifier policyTypeId) {
612 // Is it loaded in memory?
614 ToscaPolicyType policyType = this.matchablePolicyTypes.get(policyTypeId);
615 if (policyType == null) {
619 policyType = this.loadPolicyType(policyTypeId);
628 * loadPolicyType - Tries to load the given ToscaPolicyTypeIdentifier from local
629 * storage. If it does not exist, will then attempt to pull from Policy Lifecycle
632 * @param policyTypeId ToscaPolicyTypeIdentifier input
633 * @return ToscaPolicyType object. Null if failure.
635 private ToscaPolicyType loadPolicyType(ToscaPolicyTypeIdentifier policyTypeId) {
637 // Construct what the file name should be
639 Path policyTypePath = this.constructLocalFilePath(policyTypeId);
646 // If it exists locally, read the bytes in
648 bytes = Files.readAllBytes(policyTypePath);
649 } catch (IOException e) {
651 // Does not exist locally, so let's GET it from the policy api
653 LOGGER.error("PolicyType not found in data area yet {}", policyTypePath, e);
655 // So let's pull it from API REST call and save it locally
657 return this.pullPolicyType(policyTypeId, policyTypePath);
660 // Success - we have read locally the policy type. Now bring it into our
663 LOGGER.info("Read in local policy type {}", policyTypePath.toAbsolutePath());
665 ToscaServiceTemplate serviceTemplate = standardYamlCoder.decode(new String(bytes, StandardCharsets.UTF_8),
666 ToscaServiceTemplate.class);
667 JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
668 jtst.fromAuthorative(serviceTemplate);
669 ToscaServiceTemplate completedJtst = jtst.toAuthorative();
671 // Search for our Policy Type, there really only should be one but
672 // this is returned as a map.
674 for ( Entry<String, ToscaPolicyType> entrySet : completedJtst.getPolicyTypes().entrySet()) {
675 ToscaPolicyType entryPolicyType = entrySet.getValue();
676 if (policyTypeId.getName().equals(entryPolicyType.getName())
677 && policyTypeId.getVersion().equals(entryPolicyType.getVersion())) {
678 LOGGER.info("Found existing local policy type {} {}", entryPolicyType.getName(),
679 entryPolicyType.getVersion());
681 // Just simply return the policy type right here
683 return entryPolicyType;
685 LOGGER.warn("local policy type contains different name version {} {}", entryPolicyType.getName(),
686 entryPolicyType.getVersion());
690 // This would be an error, if the file stored does not match what its supposed to be
692 LOGGER.error("Existing policy type file does not contain right name and version");
693 } catch (CoderException e) {
694 LOGGER.error("Failed to decode tosca template for {}", policyTypePath, e);
697 // Hopefully we never get here
699 LOGGER.error("Failed to find/load policy type {}", policyTypeId);
704 * pullPolicyType - pulls the given ToscaPolicyTypeIdentifier from the Policy Lifecycle API.
705 * If successful, will store it locally given the policyTypePath.
707 * @param policyTypeId ToscaPolicyTypeIdentifier
708 * @param policyTypePath Path object to store locally
709 * @return ToscaPolicyType object. Null if failure.
711 private synchronized ToscaPolicyType pullPolicyType(ToscaPolicyTypeIdentifier policyTypeId, Path policyTypePath) {
713 // This is what we return
715 ToscaPolicyType policyType = null;
717 PolicyApiCaller api = new PolicyApiCaller(this.apiRestParameters);
719 policyType = api.getPolicyType(policyTypeId);
720 } catch (PolicyApiException e) {
721 LOGGER.error("Failed to make API call", e);
722 LOGGER.error("parameters: {} ", this.apiRestParameters);
725 LOGGER.info("Successfully pulled {}", policyTypeId);
730 standardYamlCoder.encode(policyTypePath.toFile(), policyType);
731 } catch (CoderException e) {
732 LOGGER.error("Failed to store {} locally to {}", policyTypeId, policyTypePath, e);
735 // Done return the policy type
741 * constructLocalFilePath - common method to ensure the name of the local file for the
742 * policy type is the same.
744 * @param policyTypeId ToscaPolicyTypeIdentifier
745 * @return Path object
747 private Path constructLocalFilePath(ToscaPolicyTypeIdentifier policyTypeId) {
748 return Paths.get(this.pathForData.toAbsolutePath().toString(), policyTypeId.getName() + "-"
749 + policyTypeId.getVersion() + ".yaml");