View Javadoc
1   package org.metricshub.wbem.client;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * WBEM Java Client
6    * ჻჻჻჻჻჻
7    * Copyright 2023 - 2025 MetricsHub
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   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
21   */
22  
23  import java.util.Arrays;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.Map;
27  import java.util.function.Function;
28  import java.util.stream.Collectors;
29  import java.util.stream.Stream;
30  import org.metricshub.wbem.javax.cim.CIMDataType;
31  import org.metricshub.wbem.javax.cim.CIMDateTimeAbsolute;
32  import org.metricshub.wbem.javax.cim.CIMDateTimeInterval;
33  import org.metricshub.wbem.javax.cim.CIMInstance;
34  import org.metricshub.wbem.javax.cim.CIMObjectPath;
35  import org.metricshub.wbem.javax.cim.CIMProperty;
36  
37  /**
38   * Handler for CIMProperty conversion to string.
39   *
40   */
41  public class WbemCimDataHandler {
42  
43  	private WbemCimDataHandler() {}
44  
45  	public static final String PATH_PROPERTY = "__Path";
46  
47  	private static final Map<Integer, Function<Object, String>> CONVERT_MAP;
48  
49  	static {
50  		final Map<Integer, Function<Object, String>> map = new HashMap<>();
51  		map.put(CIMDataType.STRING, String::valueOf);
52  		map.put(CIMDataType.BOOLEAN, String::valueOf);
53  		map.put(CIMDataType.SINT8, String::valueOf);
54  		map.put(CIMDataType.SINT16, String::valueOf);
55  		map.put(CIMDataType.SINT32, String::valueOf);
56  		map.put(CIMDataType.SINT64, String::valueOf);
57  		map.put(CIMDataType.CHAR16, String::valueOf);
58  		map.put(CIMDataType.REAL32, String::valueOf);
59  		map.put(CIMDataType.REAL64, String::valueOf);
60  		map.put(CIMDataType.OBJECT, String::valueOf);
61  		map.put(CIMDataType.DATETIME, WbemCimDataHandler::convertDateTime);
62  		map.put(CIMDataType.UINT8, String::valueOf);
63  		map.put(CIMDataType.UINT16, String::valueOf);
64  		map.put(CIMDataType.UINT32, String::valueOf);
65  		map.put(CIMDataType.UINT64, String::valueOf);
66  		map.put(CIMDataType.REFERENCE, WbemCimDataHandler::convertReference);
67  		CONVERT_MAP = Collections.unmodifiableMap(map);
68  	}
69  
70  	/**
71  	 * Get the value of the CIM property.
72  	 *
73  	 * @param property The property name.
74  	 * @param cimInstance The CIM instance.
75  	 * @param arraySeparator The array separator value. default value '|'
76  	 * @return
77  	 */
78  	public static String getCimPropertyAsString(
79  		final String property,
80  		final CIMInstance cimInstance,
81  		final String arraySeparator
82  	) {
83  		Utils.checkNonNull(property, "property");
84  		Utils.checkNonNull(cimInstance, "cimInstance");
85  
86  		if (PATH_PROPERTY.equalsIgnoreCase(property)) {
87  			final CIMObjectPath objectPath = cimInstance.getObjectPath();
88  			Utils.checkNonNull(objectPath, "objectPath");
89  			return convertReference(objectPath);
90  		}
91  
92  		// first check getProperty
93  		CIMProperty<?> cimProperty = cimInstance.getProperty(property);
94  
95  		// then, if null, check getKeys
96  		final String separator = arraySeparator == null ? Utils.DEFAULT_ARRAY_SEPARATOR : arraySeparator;
97  		if (cimProperty == null && cimInstance.getKeys() != null) {
98  			return Stream
99  				.of(cimInstance.getKeys())
100 				.filter(key -> key.getName() != null && key.getName().equalsIgnoreCase(property))
101 				.findFirst()
102 				.map(cp -> convertCimPropertyValue(cp, separator))
103 				.orElse(Utils.EMPTY);
104 		}
105 
106 		return cimProperty == null ? Utils.EMPTY : convertCimPropertyValue(cimProperty, separator);
107 	}
108 
109 	/**
110 	 * Convert the CIM property value into a String.
111 	 *
112 	 * @param cimProperty The CIM property.
113 	 * @param arraySeparator The array separator value.
114 	 * @return
115 	 */
116 	private static String convertCimPropertyValue(final CIMProperty<?> cimProperty, final String arraySeparator) {
117 		final Object cimPropertyValue = cimProperty.getValue();
118 		if (cimPropertyValue == null) {
119 			return Utils.EMPTY;
120 		}
121 
122 		final CIMDataType dataType = cimProperty.getDataType();
123 		if (dataType == null) {
124 			return cimPropertyValue.toString();
125 		}
126 
127 		return dataType.isArray()
128 			? convertArray(cimProperty, arraySeparator)
129 			: CONVERT_MAP.getOrDefault(dataType.getType(), Object::toString).apply(cimPropertyValue);
130 	}
131 
132 	/**
133 	 * Convert a CIM property value array.
134 	 *
135 	 * @param cimProperty The CIM property.
136 	 * @param arraySeparator The array separator value.
137 	 * @return
138 	 */
139 	private static String convertArray(final CIMProperty<?> cimProperty, final String arraySeparator) {
140 		return Arrays
141 			.stream((Object[]) cimProperty.getValue())
142 			.map(
143 				obj ->
144 					(obj == null)
145 						? Utils.EMPTY
146 						: CONVERT_MAP.getOrDefault(cimProperty.getDataType().getType(), Object::toString).apply(obj)
147 			)
148 			.collect(Collectors.joining(arraySeparator, Utils.EMPTY, arraySeparator));
149 	}
150 
151 	/**
152 	 * Convert a CIMObjectPath reference to string:
153 	 * <li>take the part after ':'</li>
154 	 * <li>escape back slash</li>
155 	 * <li>escape double quotes</li>
156 	 *
157 	 * @param cimPropertyValue
158 	 * @return
159 	 */
160 	private static String convertReference(final Object cimPropertyValue) {
161 		final CIMObjectPath objectPath = (CIMObjectPath) cimPropertyValue;
162 		final String str = objectPath.toString();
163 		return str
164 			.substring(str.indexOf(':') + 1) // take the part after : (if exists)
165 			.replace("\\\\", "\\") // Replace \\ by \
166 			.replace("\\\"", "\""); // Replace \" by "
167 	}
168 
169 	/**
170 	 * Convert a CIMDateTime into a string containing to Epoch time milliseconds.
171 	 *
172 	 * @param cimPropertyValue
173 	 * @return
174 	 */
175 	private static String convertDateTime(final Object cimPropertyValue) {
176 		if (cimPropertyValue == null) {
177 			return Utils.EMPTY;
178 		}
179 
180 		if (cimPropertyValue instanceof CIMDateTimeAbsolute) {
181 			final String dateTimeString = ((CIMDateTimeAbsolute) cimPropertyValue).getDateTimeString();
182 			return String.valueOf(Utils.convertCimDateTime(dateTimeString).toInstant().toEpochMilli());
183 		}
184 		return String.valueOf(((CIMDateTimeInterval) cimPropertyValue).getTotalMilliseconds());
185 	}
186 }