-
Notifications
You must be signed in to change notification settings - Fork 397
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- UI: Label correction in SoC widget in history. - Fixed lables shown below. - Energy is represented as Power. - Entladung/Beladung is represented as Charge/Discharge power. replaced with Just Charge/Discharge. - Keba ReadWorker: fix possible Exception - Added Tests to identify when and how the exception can occur. - Tests for the "calculateCycleTime" work for multiple cases without throwing an exception - Tests could still be kept for code coverage - GoodWe: improve serial number filter - Change the serial number filter according to the goowe serial number rule. - Each GoodWe Type is now detected individually by its rated power in combination with its internal model series code. - GoodWeGridMeter: adjust CURRENT sign current if needed - Added Listener to ActivePowerLX Channels - Each Listeners checks if the nextValue for the power channel if the current and power have the same sign - If the sign is different the current channel is set with * -1 - JUnit Test Framework: add possibility to test raw modbus reads - `DummyModbusBridge` can now be used to test raw modbus reads - Apply new test for changes in GoodWe GridMeter and SunSpec - Also: Improve and apply `ReflectionUtils` - Replace exchangerate.host with Eurpean Central Bank API - `_host/OsVersion`: read os version as string - Added OS_VERSION Channel in Host Component - Write e. g. "11 (bullseye)" in channel for linux and for windows "Windows 11" - UI: replace currentUser observable with signal and solve login caching - Start recommended restructuring observables to signals - Fix `UserComponent` caching user information after logout - UI: Smaller Improvements - Auto capitalize ibn-installer key input field to show only upper case letters in mobile view (keyboard) - Fix wrong service number in offline manuals - adjust time of use chart in live with replacing the upper most left yAxis tick with the chart title - UI: remove app center app icon - Improving app center readability of icons - Time-of-use-Tariff Swisspower --------- Co-authored-by: Lukas Rieger <[email protected]> Co-authored-by: Sagar Venu <[email protected]> Co-authored-by: Sebastian Asen <[email protected]> Co-authored-by: Stefan Feilmeier <[email protected]> Co-authored-by: Johann Kaufmann <[email protected]> Co-authored-by: Michael Grill <[email protected]>
- Loading branch information
1 parent
d58852d
commit ae1dbf8
Showing
112 changed files
with
2,517 additions
and
617 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
128 changes: 120 additions & 8 deletions
128
io.openems.common/src/io/openems/common/utils/ReflectionUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,143 @@ | ||
package io.openems.common.utils; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Field; | ||
import java.lang.reflect.Method; | ||
|
||
import io.openems.common.function.ThrowingRunnable; | ||
import io.openems.common.function.ThrowingSupplier; | ||
|
||
public class ReflectionUtils { | ||
|
||
public static class ReflectionException extends RuntimeException { | ||
private static final long serialVersionUID = -8001364348945297741L; | ||
|
||
protected static ReflectionException from(Exception e) { | ||
return new ReflectionException(e.getClass().getSimpleName() + ": " + e.getMessage()); | ||
} | ||
|
||
public ReflectionException(String message) { | ||
super(message); | ||
} | ||
} | ||
|
||
private ReflectionUtils() { | ||
// no instance needed | ||
} | ||
|
||
protected static void callGuarded(ThrowingRunnable<Exception> runnable) throws ReflectionException { | ||
try { | ||
runnable.run(); | ||
} catch (Exception e) { | ||
throw ReflectionException.from(e); | ||
} | ||
} | ||
|
||
protected static <T> T callGuarded(ThrowingSupplier<T, Exception> supplier) throws ReflectionException { | ||
try { | ||
return supplier.get(); | ||
} catch (Exception e) { | ||
throw ReflectionException.from(e); | ||
} | ||
} | ||
|
||
/** | ||
* Sets the value of a Field via Java Reflection. | ||
* | ||
* @param object the target object | ||
* @param memberName the name the declared field | ||
* @param value the value to be set | ||
* @throws Exception on error | ||
*/ | ||
public static void setAttributeViaReflection(Object object, String memberName, Object value) | ||
throws ReflectionException { | ||
var field = getField(object.getClass(), memberName); | ||
callGuarded(() -> field.set(object, value)); | ||
} | ||
|
||
/** | ||
* Sets the value of a static Field via Java Reflection. | ||
* | ||
* @param clazz the {@link Class} | ||
* @param memberName the name the declared field | ||
* @param value the value to be set | ||
* @throws Exception on error | ||
*/ | ||
public static void setStaticAttributeViaReflection(Class<?> clazz, String memberName, Object value) | ||
throws ReflectionException { | ||
var field = getField(clazz, memberName); | ||
callGuarded(() -> field.set(null, value)); | ||
} | ||
|
||
/** | ||
* Gets the value of a Field via Java Reflection. | ||
* | ||
* @param <T> the type of the value | ||
* @param object the target object | ||
* @param memberName the name the declared field | ||
* @return the value | ||
* @throws Exception on error | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
public static <T> boolean setAttribute(Class<? extends T> clazz, T object, String memberName, Object value) | ||
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { | ||
public static <T> T getValueViaReflection(Object object, String memberName) throws ReflectionException { | ||
var field = getField(object.getClass(), memberName); | ||
return (T) callGuarded(() -> field.get(object)); | ||
} | ||
|
||
/** | ||
* Invokes a {@link Method} that takes no arguments via Java Reflection. | ||
* | ||
* @param <T> the type of the result | ||
* @param object the target object | ||
* @param memberName the name of the method | ||
* @return the result of the method | ||
* @throws Exception on error | ||
*/ | ||
public static <T> T invokeMethodWithoutArgumentsViaReflection(Object object, String memberName) | ||
throws ReflectionException { | ||
var method = callGuarded(() -> object.getClass().getDeclaredMethod(memberName)); | ||
return invokeMethodViaReflection(object, method); | ||
} | ||
|
||
/** | ||
* Invokes a {@link Method} via Java Reflection. | ||
* | ||
* @param <T> the type of the result | ||
* @param object the target object | ||
* @param method the {@link Method} | ||
* @param args the arguments to be set | ||
* @return the result of the method | ||
* @throws Exception on error | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
public static <T> T invokeMethodViaReflection(Object object, Method method, Object... args) | ||
throws ReflectionException { | ||
method.setAccessible(true); | ||
return (T) callGuarded(() -> method.invoke(object, args)); | ||
} | ||
|
||
/** | ||
* Gets the {@link Class#getDeclaredField(String)} in the given {@link Class} or | ||
* any of its superclasses. | ||
* | ||
* @param clazz the given {@link Class} | ||
* @param memberName the name of the declared field | ||
* @return a {@link Field} | ||
* @throws ReflectionException if there is no such field | ||
*/ | ||
public static Field getField(Class<?> clazz, String memberName) throws ReflectionException { | ||
try { | ||
var field = clazz.getDeclaredField(memberName); | ||
field.setAccessible(true); | ||
field.set(object, value); | ||
return true; | ||
return field; | ||
} catch (NoSuchFieldException e) { | ||
// Ignore. | ||
} | ||
// If we are here, no matching field or method was found. Search in parent | ||
// classes. | ||
Class<?> parent = clazz.getSuperclass(); | ||
if (parent == null) { | ||
return false; // reached 'java.lang.Object' | ||
throw new ReflectionException("Reached java.lang.Object"); | ||
} | ||
return setAttribute((Class<T>) parent, object, memberName, value); | ||
return getField(parent, memberName); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.