10f3e02b743f4187faa655f30c0b9005b95b3c6f
[ccsdk/sli.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights
6  *                                                      reserved.
7  * Modifications Copyright (C) 2019 IBM.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.ccsdk.sli.adaptors.ra;
24
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 import org.onap.ccsdk.sli.adaptors.ra.comp.AllocationData;
33 import org.onap.ccsdk.sli.adaptors.ra.comp.EndPointAllocator;
34 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceData;
35 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceEntity;
36 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceRequest;
37 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceResponse;
38 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceTarget;
39 import org.onap.ccsdk.sli.adaptors.rm.comp.ResourceManager;
40 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationStatus;
41 import org.onap.ccsdk.sli.adaptors.rm.data.ReleaseRequest;
42 import org.onap.ccsdk.sli.adaptors.util.speed.SpeedUtil;
43 import org.onap.ccsdk.sli.adaptors.util.str.StrUtil;
44 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
45 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
46 import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 public class ResourceAllocator implements SvcLogicResource {
51
52     private static final Logger log = LoggerFactory.getLogger(ResourceAllocator.class);
53
54     private static final String[] INPUT_PREFIX = {"ra-input.", "tmp.resource-allocator."};
55
56     private ResourceManager resourceManager;
57     private EndPointAllocator endPointAllocator;
58     private SpeedUtil speedUtil;
59
60     public ResourceAllocator() {
61         log.info("ResourceAllocator created.");
62     }
63
64     @Override
65     public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx)
66             throws SvcLogicException {
67         return QueryStatus.SUCCESS;
68     }
69
70     @Override
71     public QueryStatus update(String resource, String key, Map<String, String> parms, String prefix,
72             SvcLogicContext ctx) throws SvcLogicException {
73
74         return QueryStatus.SUCCESS;
75     }
76
77     @Override
78     public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx)
79             throws SvcLogicException {
80         return QueryStatus.SUCCESS;
81     }
82
83     @Override
84     public QueryStatus delete(String arg0, String arg1, SvcLogicContext arg2) throws SvcLogicException {
85         return QueryStatus.SUCCESS;
86     }
87
88     @Override
89     public QueryStatus save(String arg0, boolean arg1, boolean arg2, String arg3, Map<String, String> arg4, String arg5,
90             SvcLogicContext arg6) throws SvcLogicException {
91         return QueryStatus.SUCCESS;
92     }
93
94     @Override
95     public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx)
96             throws SvcLogicException {
97         return allocateResources(ctx, true, prefix);
98     }
99
100     @Override
101     public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix,
102             String orderBy, SvcLogicContext ctx) throws SvcLogicException {
103
104         String resourceEntityId = getParam(ctx,
105                 new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, false, null);
106         String resourceEntityType =
107                 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, false, null);
108         String resourceEntityVersion =
109                 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, "1");
110
111         String resourceTargetId =
112                 getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, false, null);
113         String resourceTargetType =
114                 getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, false, null);
115         String resourceName = getParam(ctx, "resource-name", false, null);
116         String resourceEntityTypeFilter = getParam(ctx, "resource-entity-type-filter", false, null);
117         String resourceEntityIdFilter = getParam(ctx, "resource-entity-id-filter", false, null);
118         String resourceShareGroupFilter = getParam(ctx, "resource-share-group-filter", false, null);
119         String resourceTargetTypeFilter = getParam(ctx, "resource-target-type-filter", false, null);
120         String resourceTargetIdFilter = getParam(ctx, "resource-target-id-filter", false, null);
121
122         if (resourceEntityId != null && resourceEntityType != null) {
123             List<ResourceData> rdlist = endPointAllocator.getResourcesForEntity(resourceEntityType, resourceEntityId,
124                     resourceEntityVersion);
125             setResourceDataInContext(ctx, prefix, rdlist);
126         } else if (resourceTargetId != null && resourceTargetType != null && resourceName != null) {
127             ResourceData rd = endPointAllocator.getResource(resourceTargetType, resourceTargetId, resourceName,
128                     resourceEntityTypeFilter, resourceEntityIdFilter, resourceShareGroupFilter);
129             if (rd != null) {
130                 setResourceDataInContext(ctx, prefix, Collections.singletonList(rd));
131             }
132         } else if ((resourceTargetTypeFilter != null || resourceTargetIdFilter != null) && resourceName != null) {
133             List<ResourceData> rdlist = endPointAllocator.getResourcesForTarget(resourceTargetTypeFilter,
134                     resourceTargetIdFilter, resourceName);
135             setResourceDataInContext(ctx, prefix, rdlist);
136         }
137
138         return QueryStatus.SUCCESS;
139     }
140
141     public AllocationStatus query(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
142             List<ResourceResponse> rsList) throws Exception {
143
144         if (sd != null && sd.resourceEntityId != null && sd.resourceEntityType != null) {
145             List<ResourceData> rdlist = endPointAllocator.getResourcesForEntity(sd.resourceEntityType,
146                     sd.resourceEntityId, sd.resourceEntityVersion);
147             setResourceDataInResponse(rdlist, rsList);
148         } else if (rt != null && rt.resourceTargetId != null && rt.resourceTargetType != null && rr != null
149                 && rr.resourceName != null) {
150             ResourceData rd = endPointAllocator.getResource(rt.resourceTargetType, rt.resourceTargetId, rr.resourceName,
151                     rr.resourceEntityTypeFilter, rr.resourceEntityIdFilter, rr.resourceShareGroupFilter);
152             setResourceDataInResponse(Collections.singletonList(rd), rsList);
153         } else if (rr != null && (rr.resourceTargetTypeFilter != null || rr.resourceTargetIdFilter != null)
154                 && rr.resourceName != null) {
155             List<ResourceData> rdlist = endPointAllocator.getResourcesForTarget(rr.resourceTargetTypeFilter,
156                     rr.resourceTargetIdFilter, rr.resourceName);
157             setResourceDataInResponse(rdlist, rsList);
158         }
159
160         return AllocationStatus.Success;
161     }
162
163     private void setResourceDataInContext(SvcLogicContext ctx, String prefix, List<ResourceData> rdlist) {
164         if (rdlist == null || rdlist.isEmpty()) {
165             return;
166         }
167
168         prefix = prefix == null ? "" : prefix + '.';
169
170         setAttr(ctx, prefix + "resource-list_length", String.valueOf(rdlist.size()));
171
172         for (int i = 0; i < rdlist.size(); i++) {
173             ResourceData rd = rdlist.get(i);
174
175             String pp = prefix + "resource-list[" + i + "].";
176
177             setAttr(ctx, pp + "resource-name", rd.resourceName);
178             setAttr(ctx, pp + "endpoint-position", rd.endPointPosition);
179             setAttr(ctx, pp + "resource-target-type", rd.resourceTargetType);
180             setAttr(ctx, pp + "resource-target-id", rd.resourceTargetId);
181             setAttr(ctx, pp + "resource-target-value", rd.resourceTargetValue);
182             setAttr(ctx, pp + "status", rd.status);
183
184             Map<String, String> dataProp = dataToProperties(rd.data);
185             for (String kk : dataProp.keySet()) {
186                 String value = String.valueOf(dataProp.get(kk));
187                 setAttr(ctx, pp + kk, value);
188             }
189
190             if (rd.allocationDataList != null && !rd.allocationDataList.isEmpty()) {
191
192                 setAttr(ctx, pp + "allocation-data-list_length", String.valueOf(rd.allocationDataList.size()));
193
194                 for (int j = 0; j < rd.allocationDataList.size(); j++) {
195                     AllocationData ad = rd.allocationDataList.get(j);
196
197                     String ppp = pp + "allocation-data-list[" + j + "].";
198
199                     setAttr(ctx, ppp + "resource-entity-type", ad.resourceEntityType);
200                     setAttr(ctx, ppp + "resource-entity-id", ad.resourceEntityId);
201                     setAttr(ctx, ppp + "resource-entity-version", ad.resourceEntityVersion);
202
203                     if (ad.data != null && !ad.data.isEmpty()) {
204                         for (String kk : ad.data.keySet()) {
205                             String value = String.valueOf(ad.data.get(kk));
206                             setAttr(ctx, ppp + kk, value);
207                         }
208                     }
209                 }
210             }
211         }
212     }
213
214     @Override
215     public QueryStatus reserve(String resource, String select, String key, String prefix, SvcLogicContext ctx)
216             throws SvcLogicException {
217         return allocateResources(ctx, false, prefix);
218     }
219
220     public AllocationStatus reserve(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
221             List<ResourceResponse> rsList) throws Exception {
222         return allocateResources(sd, rt, rr, rsList);
223     }
224
225     @Override
226     public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
227         String resourceEntityId = getParam(ctx,
228                 new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, true, null);
229         String resourceEntityType =
230                 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, true, null);
231         String resourceEntityVersion =
232                 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, null);
233         String resourceTargetId =
234                 getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, false, null);
235         String resourceTargetType =
236                 getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, false, null);
237         String resourceName = getParam(ctx, new String[] {"resource-name"}, false, null);
238         String limitReleaseAmountStr = getParam(ctx, new String[] {"limit-release-amount"}, false, "-1");
239         int limitReleaseAmount = Integer.parseInt(limitReleaseAmountStr);
240         String rangeReleaseNumbers = getParam(ctx, new String[] {"range-release-numbers"}, false, null);
241
242
243         String endPointPosition = getParam(ctx, "endpoint-position", false, null);
244
245         ResourceEntity sd = new ResourceEntity();
246         sd.resourceEntityId = resourceEntityId;
247         sd.resourceEntityType = resourceEntityType;
248         sd.resourceEntityVersion = resourceEntityVersion;
249
250         ResourceRequest rr = new ResourceRequest();
251         rr.endPointPosition = endPointPosition;
252         rr.resourceName = resourceName;
253         rr.rangeReleaseNumbers = rangeReleaseNumbers;
254         rr.limitReleaseAmount = limitReleaseAmount;
255
256         ResourceTarget rt = new ResourceTarget();
257         rt.resourceTargetType = resourceTargetType;
258         rt.resourceTargetId = resourceTargetId;
259
260         try {
261             this.release(sd, rr, rt);
262         } catch (Exception e) {
263             throw new SvcLogicException(e.getMessage());
264         }
265         return QueryStatus.SUCCESS;
266     }
267
268     public AllocationStatus release(ResourceEntity sd) throws Exception {
269         return release(sd, null, null);
270     }
271
272     public AllocationStatus release(ResourceEntity sd, ResourceRequest rr) throws Exception {
273         return release(sd, rr, null);
274     }
275
276     public AllocationStatus release(ResourceEntity sd, ResourceRequest rr, ResourceTarget rt) {
277
278         ReleaseRequest releaseRequest = new ReleaseRequest();
279
280         if (sd != null && sd.resourceEntityVersion != null) {
281             releaseRequest.resourceSetId = null;
282
283             if (rr != null && rr.endPointPosition != null && !rr.endPointPosition.isEmpty()) {
284                 releaseRequest.resourceSetId = sd.resourceEntityType + "::" + sd.resourceEntityId + "::"
285                         + rr.endPointPosition + "::" + sd.resourceEntityVersion;
286             } else {
287                 releaseRequest.resourceSetId =
288                         sd.resourceEntityType + "::" + sd.resourceEntityId + "::" + sd.resourceEntityVersion;
289             }
290
291         } else if (sd != null && (sd.resourceEntityVersion == null || sd.resourceEntityVersion.isEmpty())) {
292             releaseRequest.resourceUnionId = null;
293
294             if (rr != null && rr.endPointPosition != null && !rr.endPointPosition.isEmpty()) {
295                 releaseRequest.resourceUnionId =
296                         sd.resourceEntityType + "::" + sd.resourceEntityId + "::" + rr.endPointPosition;
297             } else {
298                 releaseRequest.resourceUnionId = sd.resourceEntityType + "::" + sd.resourceEntityId;
299             }
300         }
301
302         if (rt != null && rt.resourceTargetId != null && rt.resourceTargetType != null) {
303             releaseRequest.assetId = rt.resourceTargetType + "::" + rt.resourceTargetId;
304         }
305
306         if (rr != null) {
307             releaseRequest.resourceName = rr.resourceName;
308             releaseRequest.releaseNumbers =
309                     StrUtil.listInt(rr.rangeReleaseNumbers, "Invalid value for range-release-numbers");
310             releaseRequest.releaseAmount = rr.limitReleaseAmount;
311         }
312
313         log.info("Releasing resources:");
314         StrUtil.info(log, releaseRequest);
315
316         resourceManager.releaseResources(releaseRequest);
317
318         return AllocationStatus.Success;
319     }
320
321     private QueryStatus allocateResources(SvcLogicContext ctx, boolean checkOnly, String prefix)
322             throws SvcLogicException {
323         String serviceModel = getParam(ctx, "service-model", true, null);
324         String requestType = getParam(ctx, "request-type", false, "New");
325
326         ResourceEntity sd = getResourceEntityData(ctx);
327         ResourceTarget rt = getResourceTargetData(ctx);
328         ResourceRequest rr = getResourceRequest(ctx);
329
330         log.info("Starting reserve: " + requestType + ", service-model: " + serviceModel);
331         StrUtil.info(log, sd);
332         StrUtil.info(log, rt);
333         StrUtil.info(log, rr);
334
335         boolean change = "change".equalsIgnoreCase(requestType);
336
337         List<ResourceData> rlist = endPointAllocator.allocateResources(serviceModel, sd, rt, rr, checkOnly, change);
338
339         if (rlist != null && !rlist.isEmpty()) {
340             setResourceDataInContext(ctx, prefix, rlist);
341
342             for (ResourceData rd : rlist) {
343                 if (!"Success".equals(rd.status)) {
344                     log.info("Capacity not found for: " + sd.resourceEntityType + "::" + sd.resourceEntityId);
345                     return QueryStatus.NOT_FOUND;
346                 }
347             }
348         }
349         return QueryStatus.SUCCESS;
350     }
351
352     private AllocationStatus allocateResources(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
353             List<ResourceResponse> rsList) throws Exception {
354
355         String serviceModel = rr.serviceModel;
356         String requestType = rr.requestType == null ? "New" : rr.requestType;
357
358         log.info("Starting reserve: " + requestType + ", service-model: " + serviceModel);
359         StrUtil.info(log, sd);
360         StrUtil.info(log, rt);
361         StrUtil.info(log, rr);
362
363         boolean change = "change".equalsIgnoreCase(requestType);
364
365         List<ResourceData> rlist = endPointAllocator.allocateResources(serviceModel, sd, rt, rr, rr.checkOnly, change);
366
367         if (rlist != null && !rlist.isEmpty()) {
368             setResourceDataInResponse(rlist, rsList);
369
370             for (ResourceData rd : rlist) {
371                 if (!"Success".equals(rd.status)) {
372                     log.info("Capacity not found for: " + sd.resourceEntityType + "::" + sd.resourceEntityId);
373                     return AllocationStatus.ResourceNotFound;
374                 }
375             }
376         }
377
378         return AllocationStatus.Success;
379     }
380
381     private void setResourceDataInResponse(List<ResourceData> rlist, List<ResourceResponse> rsList) {
382         for (ResourceData rd : emptyIfNull(rlist)) {
383             ResourceResponse res = new ResourceResponse();
384             res.resourceName = rd.resourceName;
385             res.endPointPosition = rd.endPointPosition;
386             res.resourceTargetId = rd.resourceTargetId;
387             res.resourceTargetType = rd.resourceTargetType;
388             res.status = rd.status;
389             if (rd.data != null && !rd.data.isEmpty()) {
390                 for (String kk : rd.data.keySet()) {
391                     if ("allocated".equalsIgnoreCase(kk)) {
392                         res.resourceAllocated = String.valueOf(rd.data.get(kk));
393                     }
394
395                     if ("used".equalsIgnoreCase(kk)) {
396                         res.resourceUsed = String.valueOf(rd.data.get(kk));
397                     }
398
399                     if ("available".equalsIgnoreCase(kk)) {
400                         res.resourceAvailable = String.valueOf(rd.data.get(kk));
401                     }
402
403                     if ("limit".equalsIgnoreCase(kk)) {
404                         res.resourceLimit = String.valueOf(rd.data.get(kk));
405                     }
406
407                 }
408             }
409             rsList.add(res);
410         }
411
412     }
413
414     public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) {
415         return iterable == null ? Collections.<T>emptyList() : iterable;
416     }
417
418     private void setAttr(SvcLogicContext ctx, String name, String value) {
419         ctx.setAttribute(name, value);
420         log.info("Added context attr: " + name + ": " + value);
421     }
422
423     private ResourceEntity getResourceEntityData(SvcLogicContext ctx) throws SvcLogicException {
424         ResourceEntity sd = new ResourceEntity();
425         sd.resourceEntityId = getParam(ctx,
426                 new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, true, null);
427         sd.resourceEntityType =
428                 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, true, null);
429         sd.resourceEntityVersion =
430                 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, "1");
431         sd.data = getDataParam(ctx, "reservation-entity-data", "resource-entity-data", "service-data");
432         return sd;
433     }
434
435     private ResourceTarget getResourceTargetData(SvcLogicContext ctx) throws SvcLogicException {
436         ResourceTarget sd = new ResourceTarget();
437         sd.resourceTargetId = getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, true, null);
438         sd.resourceTargetType =
439                 getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, true, null);
440         sd.data = getDataParam(ctx, "reservation-target-data", "resource-target-data", "equipment-data");
441         return sd;
442     }
443
444     private ResourceRequest getResourceRequest(SvcLogicContext ctx) throws SvcLogicException {
445         ResourceRequest rr = new ResourceRequest();
446         rr.resourceName = getParam(ctx, "resource-name", false, null);
447         rr.resourceShareGroup = getParam(ctx, "resource-share-group", false, null);
448         rr.rangeRequestedNumbers = getParam(ctx, "range-requested-numbers", false, null);
449         rr.rangeExcludeNumbers = getParam(ctx, "range-exclude-numbers", false, null);
450         String rangeReverseOrderStr = getParam(ctx, "range-reverse-order", false, "false");
451         rr.rangeReverseOrder = Boolean.parseBoolean(rangeReverseOrderStr);
452         String rangeMinOverrideStr = getParam(ctx, "range-min-override", false, "-1");
453         rr.rangeMinOverride = Integer.parseInt(rangeMinOverrideStr);
454         String rangeMaxOverrideStr = getParam(ctx, "range-max-override", false, "-1");
455         rr.rangeMaxOverride = Integer.parseInt(rangeMaxOverrideStr);
456         String rangeForceNewNumbersStr = getParam(ctx, "range-force-new-numbers", false, "false");
457         rr.rangeForceNewNumbers = Boolean.parseBoolean(rangeForceNewNumbersStr);
458         String rangeNextInSequenceStr = getParam(ctx, "range-next-in-sequence", false, "false");
459         rr.rangeNextInSequence = Boolean.parseBoolean(rangeNextInSequenceStr);
460         String replaceStr = getParam(ctx, "replace", false, "true");
461         rr.replace = Boolean.parseBoolean(replaceStr);
462         rr.applicationId = getParam(ctx, "application-id", false, "SDNC");
463         rr.endPointPosition = getParam(ctx, "endpoint-position", false, null);
464         return rr;
465     }
466
467     private String getParam(SvcLogicContext ctx, String name, boolean required, String def) throws SvcLogicException {
468         String v = null;
469         for (String p : INPUT_PREFIX) {
470             v = ctx.getAttribute(p + name);
471             if (v != null && v.trim().length() > 0) {
472                 log.info("Param: " + name + ": " + v.trim());
473                 return v.trim();
474             }
475         }
476         if (required) {
477             throw new SvcLogicException("The following variable is required in DG context: " + name);
478         }
479
480         log.info("Param: " + name + " not supplied. Using default: " + def);
481         return def;
482     }
483
484     private String getParam(SvcLogicContext ctx, String[] names, boolean required, String def)
485             throws SvcLogicException {
486         String v = null;
487         for (String name : names) {
488             v = getParam(ctx, name, false, def);
489             if (v != null) {
490                 return v;
491             }
492         }
493         if (required) {
494             throw new SvcLogicException(
495                     "One of the following variable is required in DG context: " + Arrays.deepToString(names));
496         }
497
498         log.info("Param: " + Arrays.deepToString(names) + " not supplied. Using default: " + def);
499         return def;
500     }
501
502     private Map<String, String> getDataParam(SvcLogicContext ctx, String... names) {
503         Map<String, String> data = new HashMap<>();
504         Set<String> ctxNames = ctx.getAttributeKeySet();
505         for (String n : ctxNames) {
506             for (String p : INPUT_PREFIX) {
507                 for (String name : names) {
508                     String pp = p + name + '.';
509                     if (n.startsWith(pp)) {
510                         String nn = n.substring(pp.length());
511                         String vv = ctx.getAttribute(n);
512                         data.put(nn, vv);
513
514                         log.info("Data param: " + nn + ": " + vv);
515
516                         if (ctxNames.contains(n + "-unit")) {
517                             try {
518                                 long v = Long.parseLong(vv);
519                                 String unit = ctx.getAttribute(n + "-unit");
520                                 long kbps = speedUtil.convertToKbps(v, unit);
521                                 long mbps = speedUtil.convertToMbps(v, unit);
522                                 data.put(nn + "-kbps", String.valueOf(kbps));
523                                 data.put(nn + "-mbps", String.valueOf(mbps));
524
525                                 log.info("Data param: " + nn + "-kbps: " + kbps);
526                                 log.info("Data param: " + nn + "-mbps: " + mbps);
527
528                             } catch (Exception e) {
529                                 log.warn("Invalid number for " + n + ": " + vv);
530                             }
531                         }
532                     }
533                 }
534             }
535         }
536         return data;
537     }
538
539     @SuppressWarnings("unchecked")
540     public static Map<String, String> dataToProperties(Map<String, Object> data) {
541         if (data == null || data.isEmpty()) {
542             return Collections.emptyMap();
543         }
544
545         Map<String, String> prop = new HashMap<>();
546         Map<String, Object> data1 = new HashMap<>(data);
547
548         while (!data1.isEmpty()) {
549             for (String key : new ArrayList<>(data1.keySet())) {
550                 Object o = data1.get(key);
551                 data1.remove(key);
552
553                 if (o instanceof Boolean || o instanceof Number || o instanceof String) {
554                     prop.put(key, o.toString());
555                 } else if (o instanceof Map) {
556                     Map<String, Object> mm = (Map<String, Object>) o;
557                     for (String key1 : mm.keySet()) {
558                         data1.put(key + "." + key1, mm.get(key1));
559                     }
560                 } else if (o instanceof List) {
561                     List<Object> ll = (List<Object>) o;
562                     prop.put(key + "_length", String.valueOf(ll.size()));
563                     for (int i = 0; i < ll.size(); i++) {
564                         data1.put(key + '[' + i + ']', ll.get(i));
565                     }
566                 }
567             }
568         }
569         return prop;
570     }
571
572     public void setResourceManager(ResourceManager resourceManager) {
573         this.resourceManager = resourceManager;
574     }
575
576     public void setEndPointAllocator(EndPointAllocator endPointAllocator) {
577         this.endPointAllocator = endPointAllocator;
578     }
579
580     public void setSpeedUtil(SpeedUtil speedUtil) {
581         this.speedUtil = speedUtil;
582     }
583 }