001/*-
002 * #%L
003 * Smile CDR - CDR
004 * %%
005 * Copyright (C) 2016 - 2026 Smile CDR, Inc.
006 * %%
007 * All rights reserved.
008 * #L%
009 */
010package ca.cdr.test.util;
011
012import jakarta.annotation.Nonnull;
013import jakarta.annotation.Nullable;
014
015import java.io.FileInputStream;
016import java.io.IOException;
017import java.io.InputStream;
018import java.util.HashMap;
019import java.util.Map;
020import java.util.Properties;
021
022/**
023 * Utility class for handling properties file operations in tests.
024 */
025// Created by Claude Sonnet 4
026public class PropertiesTestUtil {
027
028        /**
029         * Loads a properties file and extracts port configurations organized by module type and module ID.
030         * 
031         * @param thePropertiesLocation the path to the properties file. Can be a regular file path or a classpath resource prefixed with "classpath:"
032         * @return a map where the key is module type and the value is a map of module ID to port number
033         * @throws RuntimeException if the properties file cannot be read
034         */
035        public static Map<String, Map<String, Integer>> loadPortsFromPropertiesFile(String thePropertiesLocation) {
036                Map<String, Map<String, Integer>> portsByModuleType = new HashMap<>();
037                
038                try (InputStream inputStream = getInputStream(thePropertiesLocation)) {
039                        Properties properties = new Properties();
040                        properties.load(inputStream);
041
042                        // Extract port values from keys containing ".port"
043                        for (String key : properties.stringPropertyNames()) {
044                                if (key.contains(".port")) {
045                                        String value = properties.getProperty(key);
046                                        try {
047                                                int portValue = Integer.parseInt(value.trim());
048
049                                                // Extract Module ID and Module Type
050                                                if (key.startsWith("module.")) {
051                                                        String[] parts = key.split("\\.");
052                                                        if (parts.length >= 3) {
053                                                                String moduleId = parts[1];
054
055                                                                // Get the module type from the properties
056                                                                String moduleTypeKey = "module." + moduleId + ".type";
057                                                                String moduleType = properties.getProperty(moduleTypeKey);
058
059                                                                if (moduleType != null) {
060                                                                        // Add to the map: moduleType -> (moduleId -> port)
061                                                                        portsByModuleType.computeIfAbsent(moduleType, k -> new HashMap<>())
062                                                                                .put(moduleId, portValue);
063                                                                }
064                                                        }
065                                                }
066                                        } catch (NumberFormatException e) {
067                                                // Skip if the port value is not a valid integer
068                                        }
069                                }
070                        }
071                } catch (IOException e) {
072                        throw new RuntimeException("Failed to read properties file: " + thePropertiesLocation, e);
073                }
074                
075                return portsByModuleType;
076        }
077
078        /**
079         * Reads a module's {@code context_path} from a properties file.
080         *
081         * @param thePropertiesLocation the path to the properties file. Can be a regular file path or a classpath resource prefixed with "classpath:"
082         * @param theModuleId the module whose {@code module.<id>.config.context_path} to read
083         * @return the configured value, or {@literal null} if the module sets none
084         * @throws RuntimeException if the properties file cannot be read
085         */
086        public static @Nullable String loadContextPath(
087                        @Nonnull String thePropertiesLocation, @Nonnull String theModuleId) {
088                try (InputStream inputStream = getInputStream(thePropertiesLocation)) {
089                        Properties properties = new Properties();
090                        properties.load(inputStream);
091                        return properties.getProperty("module." + theModuleId + ".config.context_path");
092                } catch (IOException e) {
093                        throw new RuntimeException("Failed to read properties file: " + thePropertiesLocation, e);
094                }
095        }
096
097        private static InputStream getInputStream(String thePropertiesLocation) throws IOException {
098                if (thePropertiesLocation.startsWith("classpath:")) {
099                        String classpathResource = thePropertiesLocation.substring("classpath:".length());
100                        InputStream resourceStream = PropertiesTestUtil.class.getClassLoader().getResourceAsStream(classpathResource);
101                        if (resourceStream == null) {
102                                throw new IOException("Classpath resource not found: " + classpathResource);
103                        }
104                        return resourceStream;
105                } else {
106                        return new FileInputStream(thePropertiesLocation);
107                }
108        }
109}