-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clean CSA constants #1127
base: main
Are you sure you want to change the base?
Clean CSA constants #1127
Changes from all commits
c3cee7f
bf7d37f
ef7689e
906e5cc
3d6367c
2c81ca6
88720d9
6ff6151
db05da9
6a0bce4
c0b5aae
2504254
de0e4f2
a2e9bd2
33f51df
a2fecbf
e0f9f19
eb05d7a
2c6d9a0
17882d6
c429dd7
1c05409
4c36524
a54a2cb
32b056b
7373fbf
4327b93
6bf2981
e4f5fa3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,21 +7,22 @@ | |
|
||
package com.powsybl.openrao.data.cracio.csaprofiles; | ||
|
||
import com.powsybl.openrao.commons.OpenRaoException; | ||
import com.powsybl.openrao.commons.logs.OpenRaoLoggerProvider; | ||
import com.powsybl.openrao.data.cracio.csaprofiles.craccreator.CsaProfileCracUtils; | ||
import com.powsybl.openrao.data.cracio.csaprofiles.craccreator.NcPropertyBagsConverter; | ||
import com.powsybl.openrao.data.cracio.csaprofiles.craccreator.constants.CsaProfileConstants; | ||
import com.powsybl.openrao.data.cracio.csaprofiles.craccreator.constants.CsaProfileKeyword; | ||
import com.powsybl.openrao.data.cracio.csaprofiles.craccreator.constants.HeaderType; | ||
import com.powsybl.openrao.data.cracio.csaprofiles.craccreator.constants.OverridingObjectsFields; | ||
import com.powsybl.openrao.data.cracio.csaprofiles.craccreator.Query; | ||
import com.powsybl.openrao.data.cracio.csaprofiles.nc.*; | ||
import com.powsybl.triplestore.api.PropertyBag; | ||
import com.powsybl.triplestore.api.PropertyBags; | ||
import com.powsybl.triplestore.api.QueryCatalog; | ||
import com.powsybl.triplestore.api.TripleStore; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
import java.time.OffsetDateTime; | ||
import java.util.*; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* @author Jean-Pierre Arnould {@literal <jean-pierre.arnould at rte-france.com>} | ||
|
@@ -34,12 +35,14 @@ public class CsaProfileCrac { | |
|
||
private final Map<String, Set<String>> keywordMap; | ||
private Map<String, String> overridingData; | ||
private Map<Class<? extends NCObject>, Set<? extends NCObject>> queriedNativeObjects; | ||
|
||
public CsaProfileCrac(TripleStore tripleStoreCsaProfileCrac, Map<String, Set<String>> keywordMap) { | ||
this.tripleStoreCsaProfileCrac = tripleStoreCsaProfileCrac; | ||
this.queryCatalogCsaProfileCrac = new QueryCatalog(CsaProfileConstants.SPARQL_FILE_CSA_PROFILE); | ||
this.keywordMap = keywordMap; | ||
this.overridingData = new HashMap<>(); | ||
this.queriedNativeObjects = new HashMap<>(); | ||
} | ||
|
||
public void clearContext(String context) { | ||
|
@@ -64,138 +67,77 @@ private Set<String> getContextNamesToRequest(CsaProfileKeyword keyword) { | |
|
||
public Map<String, PropertyBags> getHeaders() { | ||
Map<String, PropertyBags> returnMap = new HashMap<>(); | ||
tripleStoreCsaProfileCrac.contextNames().forEach(context -> returnMap.put(context, queryTripleStore(CsaProfileConstants.REQUEST_HEADER, Set.of(context)))); | ||
tripleStoreCsaProfileCrac.contextNames().forEach(context -> returnMap.put(context, queryTripleStore("header", Set.of(context)))); | ||
return returnMap; | ||
} | ||
|
||
public PropertyBags getPropertyBags(CsaProfileKeyword keyword, String... queries) { | ||
Set<String> namesToRequest = getContextNamesToRequest(keyword); | ||
public PropertyBags getPropertyBags(Query query) { | ||
Set<String> namesToRequest = getContextNamesToRequest(query.getTargetProfilesKeyword()); | ||
if (namesToRequest.isEmpty()) { | ||
return new PropertyBags(); | ||
} | ||
return this.queryTripleStore(List.of(queries), namesToRequest); | ||
return CsaProfileCracUtils.overrideQuery(this.queryTripleStore(List.of(query.getTitle()), namesToRequest), query, overridingData); | ||
} | ||
|
||
public PropertyBags getPropertyBags(CsaProfileKeyword keyword, OverridingObjectsFields withOverride, String... queries) { | ||
return withOverride == null ? getPropertyBags(keyword, queries) : CsaProfileCracUtils.overrideData(getPropertyBags(keyword, queries), overridingData, withOverride); | ||
} | ||
|
||
public Set<Contingency> getContingencies() { | ||
return new NcPropertyBagsConverter<>(Contingency::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.CONTINGENCY, OverridingObjectsFields.CONTINGENCY, CsaProfileConstants.REQUEST_ORDINARY_CONTINGENCY, CsaProfileConstants.REQUEST_EXCEPTIONAL_CONTINGENCY, CsaProfileConstants.REQUEST_OUT_OF_RANGE_CONTINGENCY)); | ||
} | ||
|
||
public Set<ContingencyEquipment> getContingencyEquipments() { | ||
return new NcPropertyBagsConverter<>(ContingencyEquipment::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.CONTINGENCY, CsaProfileConstants.REQUEST_CONTINGENCY_EQUIPMENT)); | ||
} | ||
|
||
public Set<AssessedElement> getAssessedElements() { | ||
return new NcPropertyBagsConverter<>(AssessedElement::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.ASSESSED_ELEMENT, OverridingObjectsFields.ASSESSED_ELEMENT, CsaProfileConstants.REQUEST_ASSESSED_ELEMENT)); | ||
} | ||
|
||
public Set<AssessedElementWithContingency> getAssessedElementWithContingencies() { | ||
return new NcPropertyBagsConverter<>(AssessedElementWithContingency::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.ASSESSED_ELEMENT, OverridingObjectsFields.ASSESSED_ELEMENT_WITH_CONTINGENCY, CsaProfileConstants.REQUEST_ASSESSED_ELEMENT_WITH_CONTINGENCY)); | ||
} | ||
|
||
public Set<AssessedElementWithRemedialAction> getAssessedElementWithRemedialActions() { | ||
return new NcPropertyBagsConverter<>(AssessedElementWithRemedialAction::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.ASSESSED_ELEMENT, OverridingObjectsFields.ASSESSED_ELEMENT_WITH_REMEDIAL_ACTION, CsaProfileConstants.REQUEST_ASSESSED_ELEMENT_WITH_REMEDIAL_ACTION)); | ||
} | ||
|
||
public Set<CurrentLimit> getCurrentLimits() { | ||
return new NcPropertyBagsConverter<>(CurrentLimit::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.CGMES, OverridingObjectsFields.CURRENT_LIMIT, CsaProfileConstants.REQUEST_CURRENT_LIMIT)); | ||
} | ||
|
||
public Set<VoltageLimit> getVoltageLimits() { | ||
return new NcPropertyBagsConverter<>(VoltageLimit::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.CGMES, OverridingObjectsFields.VOLTAGE_LIMIT, CsaProfileConstants.REQUEST_VOLTAGE_LIMIT)); | ||
} | ||
|
||
public Set<VoltageAngleLimit> getVoltageAngleLimits() { | ||
return new NcPropertyBagsConverter<>(VoltageAngleLimit::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.EQUIPMENT_RELIABILITY, OverridingObjectsFields.VOLTAGE_ANGLE_LIMIT, CsaProfileConstants.REQUEST_VOLTAGE_ANGLE_LIMIT)); | ||
} | ||
|
||
public Set<GridStateAlterationRemedialAction> getGridStateAlterationRemedialActions() { | ||
return new NcPropertyBagsConverter<>(GridStateAlterationRemedialAction::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, OverridingObjectsFields.GRID_STATE_ALTERATION_REMEDIAL_ACTION, CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION)); | ||
} | ||
|
||
public Set<TopologyAction> getTopologyActions() { | ||
return new NcPropertyBagsConverter<>(TopologyAction::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, OverridingObjectsFields.TOPOLOGY_ACTION, CsaProfileConstants.TOPOLOGY_ACTION)); | ||
} | ||
|
||
public Set<RotatingMachineAction> getRotatingMachineActions() { | ||
return new NcPropertyBagsConverter<>(RotatingMachineAction::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, OverridingObjectsFields.ROTATING_MACHINE_ACTION, CsaProfileConstants.ROTATING_MACHINE_ACTION)); | ||
} | ||
|
||
public Set<ShuntCompensatorModification> getShuntCompensatorModifications() { | ||
return new NcPropertyBagsConverter<>(ShuntCompensatorModification::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, OverridingObjectsFields.SHUNT_COMPENSATOR_MODIFICATION, CsaProfileConstants.SHUNT_COMPENSATOR_MODIFICATION)); | ||
} | ||
|
||
public Set<TapPositionAction> getTapPositionActions() { | ||
return new NcPropertyBagsConverter<>(TapPositionAction::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, OverridingObjectsFields.TAP_POSITION_ACTION, CsaProfileConstants.TAP_POSITION_ACTION)); | ||
} | ||
|
||
public Set<StaticPropertyRange> getStaticPropertyRanges() { | ||
return new NcPropertyBagsConverter<>(StaticPropertyRange::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, OverridingObjectsFields.STATIC_PROPERTY_RANGE, CsaProfileConstants.STATIC_PROPERTY_RANGE)); | ||
} | ||
|
||
public Set<ContingencyWithRemedialAction> getContingencyWithRemedialActions() { | ||
return new NcPropertyBagsConverter<>(ContingencyWithRemedialAction::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, OverridingObjectsFields.CONTINGENCY_WITH_REMEDIAL_ACTION, CsaProfileConstants.REQUEST_CONTINGENCY_WITH_REMEDIAL_ACTION)); | ||
} | ||
|
||
public Set<Stage> getStages() { | ||
return new NcPropertyBagsConverter<>(Stage::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, CsaProfileConstants.STAGE)); | ||
} | ||
|
||
public Set<GridStateAlterationCollection> getGridStateAlterationCollections() { | ||
return new NcPropertyBagsConverter<>(GridStateAlterationCollection::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, CsaProfileConstants.GRID_STATE_ALTERATION_COLLECTION)); | ||
} | ||
|
||
public Set<RemedialActionScheme> getRemedialActionSchemes() { | ||
return new NcPropertyBagsConverter<>(RemedialActionScheme::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, OverridingObjectsFields.REMEDIAL_ACTION_SCHEME, CsaProfileConstants.REMEDIAL_ACTION_SCHEME)); | ||
} | ||
|
||
public Set<SchemeRemedialAction> getSchemeRemedialActions() { | ||
return new NcPropertyBagsConverter<>(SchemeRemedialAction::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, OverridingObjectsFields.SCHEME_REMEDIAL_ACTION, CsaProfileConstants.REQUEST_SCHEME_REMEDIAL_ACTION)); | ||
} | ||
|
||
public Set<RemedialActionGroup> getRemedialActionGroups() { | ||
return new NcPropertyBagsConverter<>(RemedialActionGroup::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, CsaProfileConstants.REQUEST_REMEDIAL_ACTION_GROUP)); | ||
|
||
} | ||
|
||
public Set<RemedialActionDependency> getRemedialActionDependencies() { | ||
return new NcPropertyBagsConverter<>(RemedialActionDependency::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.REMEDIAL_ACTION, OverridingObjectsFields.SCHEME_REMEDIAL_ACTION_DEPENDENCY, CsaProfileConstants.REQUEST_REMEDIAL_ACTION_DEPENDENCY)); | ||
} | ||
|
||
public Set<TapChanger> getTapChangers() { | ||
return new NcPropertyBagsConverter<>(TapChanger::fromPropertyBag).convert(getPropertyBags(CsaProfileKeyword.CGMES, CsaProfileConstants.REQUEST_TAP_CHANGER)); | ||
/** | ||
* Returns the set of all the native NC objects of the specified type from the NC profiles | ||
* | ||
* @param nativeType NC type of objects to retrieve | ||
* @param <T> native NC class type | ||
* @return set of native objects | ||
*/ | ||
public <T extends NCObject> Set<T> getNativeObjects(Class<T> nativeType) { | ||
if (queriedNativeObjects.containsKey(nativeType)) { | ||
return (Set<T>) queriedNativeObjects.get(nativeType); | ||
} | ||
Query query = Arrays.stream(Query.values()).filter(q -> nativeType.equals(q.getNativeClass())).findFirst().orElseThrow(); | ||
Set<T> nativeObjects = getPropertyBags(query).stream().map(pb -> { | ||
try { | ||
return NativeParser.fromPropertyBag(pb, nativeType, query.getDefaultValues()); | ||
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | | ||
InvocationTargetException e) { | ||
throw new OpenRaoException(e); | ||
} | ||
}).collect(Collectors.toSet()); | ||
queriedNativeObjects.put(nativeType, nativeObjects); | ||
return nativeObjects; | ||
} | ||
|
||
private void setOverridingData(OffsetDateTime importTimestamp) { | ||
overridingData = new HashMap<>(); | ||
for (OverridingObjectsFields overridingObject : OverridingObjectsFields.values()) { | ||
addDataFromTripleStoreToMap(overridingData, overridingObject.getRequestName(), overridingObject.getObjectName(), overridingObject.getOverridedFieldName(), overridingObject.getHeaderType(), importTimestamp); | ||
} | ||
Arrays.stream(Query.values()).forEach(query -> addDataFromTripleStoreToMap(overridingData, query, importTimestamp)); | ||
} | ||
|
||
private void addDataFromTripleStoreToMap(Map<String, String> dataMap, String queryName, String queryObjectName, String queryFieldName, HeaderType headerType, OffsetDateTime importTimestamp) { | ||
PropertyBags propertyBagsResult = queryTripleStore(queryName, tripleStoreCsaProfileCrac.contextNames()); | ||
private void addDataFromTripleStoreToMap(Map<String, String> dataMap, Query query, OffsetDateTime importTimestamp) { | ||
if (query.getOverridableAttribute() == null) { | ||
return; | ||
} | ||
PropertyBags propertyBagsResult = queryTripleStore(query.getTitle() + "Overriding", tripleStoreCsaProfileCrac.contextNames()); | ||
for (PropertyBag propertyBag : propertyBagsResult) { | ||
if (HeaderType.START_END_DATE.equals(headerType)) { | ||
if (CsaProfileCracUtils.checkProfileKeyword(propertyBag, CsaProfileKeyword.STEADY_STATE_INSTRUCTION) && CsaProfileCracUtils.checkProfileValidityInterval(propertyBag, importTimestamp)) { | ||
String id = propertyBag.getId(queryObjectName); | ||
String overridedValue = propertyBag.get(queryFieldName); | ||
dataMap.put(id, overridedValue); | ||
} | ||
if (!CsaProfileKeyword.CGMES.equals(query.getTargetProfilesKeyword())) { | ||
overrideDataFromSsi(dataMap, query, importTimestamp, propertyBag); | ||
} else { | ||
if (CsaProfileCracUtils.checkProfileKeyword(propertyBag, CsaProfileKeyword.STEADY_STATE_HYPOTHESIS)) { | ||
OffsetDateTime scenarioTime = OffsetDateTime.parse(propertyBag.get(CsaProfileConstants.SCENARIO_TIME)); | ||
if (importTimestamp.isEqual(scenarioTime)) { | ||
String id = propertyBag.getId(queryObjectName); | ||
String overridedValue = propertyBag.get(queryFieldName); | ||
dataMap.put(id, overridedValue); | ||
} | ||
overrideDataFromSsh(dataMap, query, importTimestamp, propertyBag); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private static void overrideDataFromSsi(Map<String, String> dataMap, Query query, OffsetDateTime importTimestamp, PropertyBag propertyBag) { | ||
if (CsaProfileCracUtils.checkProfileKeyword(propertyBag, CsaProfileKeyword.STEADY_STATE_INSTRUCTION) && CsaProfileCracUtils.checkProfileValidityInterval(propertyBag, importTimestamp)) { | ||
String id = propertyBag.getId(query.getTitle()); | ||
String overridingValue = propertyBag.get(query.getOverridableAttribute().getOverridingName()); | ||
dataMap.put(id, overridingValue); | ||
} | ||
} | ||
|
||
private static void overrideDataFromSsh(Map<String, String> dataMap, Query query, OffsetDateTime importTimestamp, PropertyBag propertyBag) { | ||
OffsetDateTime scenarioTime = OffsetDateTime.parse(propertyBag.get("scenarioTime")); | ||
if (importTimestamp.isEqual(scenarioTime)) { | ||
String id = propertyBag.getId(query.getTitle()); | ||
String overridingValue = propertyBag.get(query.getOverridableAttribute().getOverridingName()); | ||
dataMap.put(id, overridingValue); | ||
} | ||
} | ||
|
||
|
@@ -251,8 +193,8 @@ private void clearTimewiseIrrelevantContexts(OffsetDateTime offsetDateTime) { | |
} | ||
|
||
private static boolean checkTimeCoherence(PropertyBag header, OffsetDateTime offsetDateTime) { | ||
String startTime = header.getId(CsaProfileConstants.REQUEST_HEADER_START_DATE); | ||
String endTime = header.getId(CsaProfileConstants.REQUEST_HEADER_END_DATE); | ||
String startTime = header.getId(CsaProfileConstants.START_DATE); | ||
String endTime = header.getId(CsaProfileConstants.END_DATE); | ||
return CsaProfileCracUtils.isValidInterval(offsetDateTime, startTime, endTime); | ||
} | ||
Comment on lines
195
to
199
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you not replace this method with CsaProfileCracUtils.checkProfileValidityInterval directly? |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
* Copyright (c) 2024, RTE (http://www.rte-france.com) | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
package com.powsybl.openrao.data.cracio.csaprofiles; | ||
|
||
import com.powsybl.openrao.commons.OpenRaoException; | ||
import com.powsybl.openrao.data.cracio.csaprofiles.nc.NCObject; | ||
import com.powsybl.triplestore.api.PropertyBag; | ||
|
||
import java.lang.reflect.Constructor; | ||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.RecordComponent; | ||
import java.util.Arrays; | ||
import java.util.Map; | ||
|
||
/** | ||
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>} | ||
* | ||
* Utility class that provides a generic template to query native objects | ||
* in NC profiles and to cast the results to native NC objects. | ||
*/ | ||
public final class NativeParser { | ||
|
||
private NativeParser() { | ||
} | ||
|
||
private static Object parseStringValue(String value, Class<?> targetType) { | ||
if (value == null || String.class.equals(targetType)) { | ||
return value; | ||
} else if (Boolean.class.equals(targetType)) { | ||
if ("true".equalsIgnoreCase(value)) { | ||
return true; | ||
} else if ("false".equalsIgnoreCase(value)) { | ||
return false; | ||
} else { | ||
return null; | ||
} | ||
} else if (Double.class.equals(targetType)) { | ||
return Double.parseDouble(value); | ||
} else if (Integer.class.equals(targetType)) { | ||
return Integer.parseInt(value); | ||
} else { | ||
throw new OpenRaoException("Unsupported type %s".formatted(targetType.getName())); | ||
} | ||
} | ||
|
||
private static String getMrid(PropertyBag propertyBag, Class<?> nativeClass) { | ||
String propertyBagName = Character.toLowerCase(nativeClass.getSimpleName().charAt(0)) + nativeClass.getSimpleName().substring(1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you not simply do getSimpleName().toLowerCase() or do you need any other upper case to stay upper case? |
||
return propertyBag.getId(propertyBagName); | ||
} | ||
|
||
public static <T extends NCObject> T fromPropertyBag(PropertyBag propertyBag, Class<T> nativeClass, Map<String, Object> defaultValues) throws IllegalArgumentException, OpenRaoException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a way to reduce the number of possible thrown exceptions? |
||
// Ensure the class is a record | ||
if (!nativeClass.isRecord()) { | ||
throw new IllegalArgumentException("Provided class is not a record"); | ||
} | ||
|
||
// Get the record's components (fields) | ||
RecordComponent[] components = nativeClass.getRecordComponents(); | ||
|
||
// Prepare an array to hold the values for the record's constructor | ||
Object[] constructorArgs = new Object[components.length]; | ||
|
||
// Loop through the components and extract values from the property bag | ||
for (int i = 0; i < components.length; i++) { | ||
RecordComponent component = components[i]; | ||
if ("mrid".equals(component.getName())) { | ||
constructorArgs[i] = getMrid(propertyBag, nativeClass); | ||
} else { | ||
Object parsedValue = parseStringValue(propertyBag.getId(component.getName()), component.getType()); | ||
if (parsedValue == null) { | ||
parsedValue = defaultValues.get(component.getName()); | ||
} | ||
constructorArgs[i] = parsedValue; | ||
} | ||
} | ||
|
||
// Find the canonical constructor of the record class | ||
Constructor<T> constructor = nativeClass.getDeclaredConstructor( | ||
// Get the types of the components (this matches the constructor signature) | ||
Arrays.stream(components) | ||
.map(RecordComponent::getType) | ||
.toArray(Class<?>[]::new) | ||
); | ||
|
||
// Create and return a new instance of the record | ||
return constructor.newInstance(constructorArgs); | ||
} | ||
Comment on lines
+55
to
+91
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This class is very complex and difficult to maintain. It also requires the name of the fields of the records to match perfectly the ones in the xsd. It also changes all the booleans into Booleans which makes the rest of the code a bit less nice (I guess this can be solved by changing the fields in the records to booleans?). |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you can put this in a static method of query (that would return an optional)