diff options
Diffstat (limited to 'src/main/java/org/onap/a1pesimulator/util')
7 files changed, 517 insertions, 0 deletions
diff --git a/src/main/java/org/onap/a1pesimulator/util/Constants.java b/src/main/java/org/onap/a1pesimulator/util/Constants.java new file mode 100644 index 0000000..1964efd --- /dev/null +++ b/src/main/java/org/onap/a1pesimulator/util/Constants.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package org.onap.a1pesimulator.util; + +public class Constants { + + private Constants() { + } + + public static final String MEASUREMENT_FIELD_IDENTIFIER = "identifier"; + public static final String MEASUREMENT_FIELD_VALUE = "value"; +} diff --git a/src/main/java/org/onap/a1pesimulator/util/DistanceCalculator.java b/src/main/java/org/onap/a1pesimulator/util/DistanceCalculator.java new file mode 100644 index 0000000..e487ed3 --- /dev/null +++ b/src/main/java/org/onap/a1pesimulator/util/DistanceCalculator.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package org.onap.a1pesimulator.util; + +public class DistanceCalculator { + + private static final int EARTH_RADIUS = 6371; // Earth radius in KM + + private DistanceCalculator() { + } + + /** + * Calculate distance in KM using Haversine formula + */ + public static double calculate(double startLat, double startLong, double endLat, double endLong) { + return haversine(startLat, startLong, endLat, endLong); + } + + public static boolean isInRange(double startLat, double startLong, double endLat, double endLong, double range) { + double distance = calculate(startLat, startLong, endLat, endLong); + return distance < range; + } + + private static double haversine(double startLat, double startLong, double endLat, double endLong) { + double dLat = Math.toRadians(endLat - startLat); + double dLon = Math.toRadians(endLong - startLong); + double startLatInRadians = Math.toRadians(startLat); + double endLatInRadians = Math.toRadians(endLat); + + double a = Math.pow(Math.sin(dLat / 2), 2) + Math.pow(Math.sin(dLon / 2), 2) * Math.cos(startLatInRadians) + * Math.cos(endLatInRadians); + double c = 2 * Math.asin(Math.sqrt(a)); + return EARTH_RADIUS * c; + } +} diff --git a/src/main/java/org/onap/a1pesimulator/util/ItemsRefresher.java b/src/main/java/org/onap/a1pesimulator/util/ItemsRefresher.java new file mode 100644 index 0000000..6991da0 --- /dev/null +++ b/src/main/java/org/onap/a1pesimulator/util/ItemsRefresher.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package org.onap.a1pesimulator.util; + +import org.onap.a1pesimulator.service.cell.RanCellsHolder; +import org.onap.a1pesimulator.service.ue.RanUeHolder; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +@Service +@EnableScheduling +public class ItemsRefresher { + + private final RanCellsHolder cellsHolder; + private final RanUeHolder ueHolder; + + public ItemsRefresher(final RanCellsHolder cellsHolder, final RanUeHolder ueHolder) { + this.cellsHolder = cellsHolder; + this.ueHolder = ueHolder; + } + + @Scheduled(fixedRateString = "${refresher.fixed.rate.ms}") + public void refresh() { + if (cellsHolder.hasChanged()) { + cellsHolder.refresh(); + } + + if (ueHolder.hasChanged()) { + ueHolder.refresh(); + } + } +} diff --git a/src/main/java/org/onap/a1pesimulator/util/JsonUtils.java b/src/main/java/org/onap/a1pesimulator/util/JsonUtils.java new file mode 100644 index 0000000..9263bc1 --- /dev/null +++ b/src/main/java/org/onap/a1pesimulator/util/JsonUtils.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package org.onap.a1pesimulator.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.FileReader; +import java.io.IOException; +import java.net.URL; +import java.text.MessageFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public enum JsonUtils { + + INSTANCE; + + private static final Logger log = LoggerFactory.getLogger(JsonUtils.class); + + private ObjectMapper mapper; + + private JsonUtils() { + this.mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + public String objectToPrettyString(Object object) { + try { + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object); + } catch (JsonProcessingException e) { + throw new JsonUtilsException("Cannot serialize object", e); + } + } + + @SuppressWarnings("unchecked") + public <T> T clone(T object) { + String stringValue; + try { + stringValue = mapper.writeValueAsString(object); + return (T) mapper.readValue(stringValue, object.getClass()); + } catch (JsonProcessingException e) { + throw new JsonUtilsException("Cannot clone object", e); + } + } + + public <T> T deserializeFromFile(String fileName, Class<T> clazz) { + try { + return mapper.readValue(new FileReader(fileName), clazz); + } catch (IOException e) { + String errorMsg = MessageFormat.format("Could not deserialize from file: {0} into {1}", fileName, + clazz.getSimpleName()); + log.error(errorMsg, e); + throw new JsonUtilsException(errorMsg, e); + } + } + + public <T> T deserializeFromFileUrl(URL url, Class<T> clazz) { + try { + return mapper.readValue(url, clazz); + } catch (IOException e) { + String errorMsg = MessageFormat.format("Could not deserialize from file URL: {0} into {1}", url, + clazz.getSimpleName()); + log.error(errorMsg, e); + throw new JsonUtilsException(errorMsg, e); + } + } + + public <T> T deserialize(String string, Class<T> clazz) throws JsonUtilsException { + try { + return mapper.readValue(string, clazz); + } catch (IOException e) { + String errorMsg = MessageFormat + .format("Could not deserialize into {0} from object: {1}", clazz.getSimpleName(), + string); + log.error(errorMsg, e); + throw new JsonUtilsException(errorMsg, e); + } + } + + public static class JsonUtilsException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public JsonUtilsException(String message, Throwable throwable) { + super(message, throwable); + } + } +} diff --git a/src/main/java/org/onap/a1pesimulator/util/RanVesUtils.java b/src/main/java/org/onap/a1pesimulator/util/RanVesUtils.java new file mode 100644 index 0000000..d5f3e67 --- /dev/null +++ b/src/main/java/org/onap/a1pesimulator/util/RanVesUtils.java @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package org.onap.a1pesimulator.util; + +import java.text.MessageFormat; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; +import org.onap.a1pesimulator.data.ue.UserEquipment; +import org.onap.a1pesimulator.data.ves.CommonEventHeader; +import org.onap.a1pesimulator.data.ves.Event; +import org.onap.a1pesimulator.data.ves.MeasurementFields.AdditionalMeasurement; +import org.onap.a1pesimulator.service.ue.RanUeHolder; + +public class RanVesUtils { + + private static final String PATTERN_DIGIT = "\\d+"; + private static final String PATTERN_SPLIT_RANDOM = "-"; + private static final String PATTERN_SPLIT_TRENDING = "->"; + private static final String MARKER_START = "[["; + private static final String MARKER_END = "]]"; + private static final String PATTERN_MARKER_START = "\\[\\["; + private static final String PATTERN_MARKER_END = "\\]\\]"; + + private static final String UE_PARAM_TRAFFIC_MODEL = "trafficModel"; + private static final int TEN_MINUTES_MICROSECONDS = 10 * 60 * 1000_000; + + private static final Random random = new Random(); + + private RanVesUtils() { + } + + public static void updateHeader(Event event) { + CommonEventHeader commonEventHeader = event.getCommonEventHeader(); + commonEventHeader.setLastEpochMicrosec(ChronoUnit.MICROS.between(Instant.EPOCH, Instant.now())); + commonEventHeader.setStartEpochMicrosec(getStartEpochMicroseconds()); + } + + public static AdditionalMeasurement buildTrafficModelMeasurement(AdditionalMeasurement identityMeasurement, + RanUeHolder ranUeHolder, String valuePattern) { + String cellId = identityMeasurement.getHashMap().get(Constants.MEASUREMENT_FIELD_VALUE); + AdditionalMeasurement trafficModel = new AdditionalMeasurement(); + Map<String, String> hashMap = new HashMap<>(); + trafficModel.setName(UE_PARAM_TRAFFIC_MODEL); + trafficModel.setHashMap(hashMap); + Collection<UserEquipment> cellUes = ranUeHolder.getUserEquipmentsConnectedToCell(cellId); + cellUes.stream().map(UserEquipment::getId).forEach(ueId -> hashMap.put(ueId, valuePattern)); + + return trafficModel; + } + + public static List<AdditionalMeasurement> randomizeAdditionalMeasurements( + Collection<AdditionalMeasurement> toRandomize) { + return toRandomize.stream().map(measurement -> transformAdditionalMeasurementValues(measurement, + RanVesUtils::randomizeValue)).collect(Collectors.toList()); + } + + public static List<AdditionalMeasurement> setLowRangeValues(List<AdditionalMeasurement> toUpdateMeasurements) { + return toUpdateMeasurements.stream().map(measurement -> transformAdditionalMeasurementValues(measurement, + RanVesUtils::getLowRangeValue)).collect(Collectors.toList()); + } + + private static AdditionalMeasurement transformAdditionalMeasurementValues(AdditionalMeasurement measurement, + UnaryOperator<String> transformAction) { + AdditionalMeasurement randomizedMeasurement = new AdditionalMeasurement(); + randomizedMeasurement.setName(measurement.getName()); + randomizedMeasurement.setHashMap(transformValues(measurement.getHashMap(), transformAction)); + return randomizedMeasurement; + } + + private static Map<String, String> transformValues(Map<String, String> values, + UnaryOperator<String> transformAction) { + Map<String, String> randomizedMap = new HashMap<>(values.size()); + values.forEach((key, value) -> randomizedMap.put(key, transformAction.apply(value))); + return randomizedMap; + } + + private static String randomizeValue(String value) { + if (!isRange(value)) { + return value; + } + String toRandomize = value.substring(MARKER_START.length(), value.length() - MARKER_END.length()); + String[] ranges = toRandomize.split(PATTERN_SPLIT_RANDOM); + int randomNumber = getRandomNumber(parseInt(ranges[0]), parseInt(ranges[1])); + return String.valueOf(randomNumber); + } + + private static String getLowRangeValue(String value) { + if (!isRange(value)) { + return value; + } + String toRandomize = value.substring(MARKER_START.length(), value.length() - MARKER_END.length()); + String[] ranges = toRandomize.split(PATTERN_SPLIT_RANDOM); + return String.valueOf(ranges[0]); + } + + private static Long getStartEpochMicroseconds() { + long epochMicrosecondsNow = ChronoUnit.MICROS.between(Instant.EPOCH, Instant.now()); + long lowest10minInterval = epochMicrosecondsNow - epochMicrosecondsNow % TEN_MINUTES_MICROSECONDS; + long highest10minInterval = lowest10minInterval + TEN_MINUTES_MICROSECONDS; + + if ((epochMicrosecondsNow - lowest10minInterval) < (highest10minInterval - epochMicrosecondsNow)) { + return lowest10minInterval; + } else { + return highest10minInterval; + } + } + + public static int getRandomNumber(int min, int max) { + return random.nextInt(max - min) + min; + } + + private static int parseInt(String strNum) { + try { + return Integer.parseInt(strNum); + } catch (NumberFormatException nfe) { + throw new IllegalArgumentException(MessageFormat.format("Cannot parse int for value: {0}", strNum), nfe); + } + } + + public static boolean isRange(String value) { + return value.startsWith(MARKER_START) && value.endsWith(MARKER_END); + } + + private static boolean isRange(String value, String splitPattern) { + String pattern = PATTERN_MARKER_START + PATTERN_DIGIT + splitPattern + PATTERN_DIGIT + PATTERN_MARKER_END; + return value.matches(pattern); + } + + public static boolean isRandomRange(String value) { + return isRange(value, PATTERN_SPLIT_RANDOM); + } + + public static boolean isTrandingRange(String value) { + return isRange(value, PATTERN_SPLIT_TRENDING); + } + + public static String[] splitRandomRange(String value) { + return splitRange(value, PATTERN_SPLIT_RANDOM); + } + + public static String[] splitTrendingRange(String value) { + return splitRange(value, PATTERN_SPLIT_TRENDING); + } + + private static String[] splitRange(String value, String splitPattern) { + String truncated = value.substring(MARKER_START.length(), value.length() - MARKER_END.length()); + return truncated.split(splitPattern); + } +} diff --git a/src/main/java/org/onap/a1pesimulator/util/TopologyReader.java b/src/main/java/org/onap/a1pesimulator/util/TopologyReader.java new file mode 100644 index 0000000..55e47cf --- /dev/null +++ b/src/main/java/org/onap/a1pesimulator/util/TopologyReader.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package org.onap.a1pesimulator.util; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import org.onap.a1pesimulator.data.cell.CellList; +import org.onap.a1pesimulator.data.ue.UserEquipment; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class TopologyReader { + + private final String topologyCellConfigFile; + private final String topologyUeConfigFile; + + private long topologyCellLastModified = 0L; + private long topologyUeLastModified = 0L; + + private TopologyReader(@Value("${topology.cell.config.file}") final String topologyCellConfigFile, + @Value("${topology.ue.config.file}") final String topologyUeConfigFile) { + this.topologyCellConfigFile = topologyCellConfigFile; + this.topologyUeConfigFile = topologyUeConfigFile; + } + + public CellList loadCellTopology() { + final File file = new File(topologyCellConfigFile); + topologyCellLastModified = file.lastModified(); + + if (!file.exists()) { + return new CellList(); + } + + return JsonUtils.INSTANCE.deserializeFromFile(topologyCellConfigFile, CellList.class); + } + + public Collection<UserEquipment> loadUeTopology() { + final File file = new File(topologyUeConfigFile); + topologyUeLastModified = file.lastModified(); + + if (!file.exists()) { + return Collections.emptyList(); + } + + final UserEquipment[] userEquipments = + JsonUtils.INSTANCE.deserializeFromFile(topologyUeConfigFile, UserEquipment[].class); + return Arrays.asList(userEquipments); + } + + public boolean topologyCellHasChanged() { + return topologyCellLastModified != new File(topologyCellConfigFile).lastModified(); + } + + public boolean topologyUeHasChanged() { + return topologyUeLastModified != new File(topologyUeConfigFile).lastModified(); + } +} diff --git a/src/main/java/org/onap/a1pesimulator/util/VnfConfigReader.java b/src/main/java/org/onap/a1pesimulator/util/VnfConfigReader.java new file mode 100644 index 0000000..318b3d6 --- /dev/null +++ b/src/main/java/org/onap/a1pesimulator/util/VnfConfigReader.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package org.onap.a1pesimulator.util; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.Properties; +import org.onap.a1pesimulator.data.VnfConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class VnfConfigReader { + + private static final Logger log = LoggerFactory.getLogger(VnfConfigReader.class); + + private String vnfConfigFile; + + private VnfConfigReader(@Value("${vnf.config.file}") String vnfConfigFile) { + this.vnfConfigFile = vnfConfigFile; + } + + public VnfConfig getVnfConfig() { + + Properties props = new Properties(); + VnfConfig vnfConfig; + + try { + props.load(new FileReader(vnfConfigFile)); + ObjectMapper mapper = new ObjectMapper(); + vnfConfig = mapper.convertValue(props, VnfConfig.class); + } catch (FileNotFoundException e) { + String errorMsg = "Could not find vnfConfigFile under: " + vnfConfigFile; + log.error(errorMsg); + throw new VnfConfigReaderException(errorMsg, e); + } catch (Exception e) { + String errorMsg = "Failed to get VnfConfig: " + e.getMessage(); + log.error(errorMsg); + throw new VnfConfigReaderException(errorMsg, e); + } + + return vnfConfig; + } + + private static class VnfConfigReaderException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public VnfConfigReaderException(String message, Throwable t) { + super(message, t); + } + } +} |