mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Removing TableCustomizer (mostly redundant with TableCustomizers and confusing for no real gain). Initial pass at update, delete customizers
This commit is contained in:
@ -26,27 +26,30 @@ package com.kingsrook.qqq.backend.core.actions.customizers;
|
|||||||
** Enum definition of possible table customizers - "roles" for custom code that
|
** Enum definition of possible table customizers - "roles" for custom code that
|
||||||
** can be applied to tables.
|
** can be applied to tables.
|
||||||
**
|
**
|
||||||
** Works with TableCustomizer (singular version of this name) objects, during
|
|
||||||
** instance validation, to provide validation of the referenced code (and to
|
|
||||||
** make such validation from sub-backend-modules possible in the future).
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public enum TableCustomizers
|
public enum TableCustomizers
|
||||||
{
|
{
|
||||||
PRE_INSERT_RECORD(new TableCustomizer("preInsertRecord", AbstractPreInsertCustomizer.class)),
|
POST_QUERY_RECORD("postQueryRecord", AbstractPostQueryCustomizer.class),
|
||||||
POST_QUERY_RECORD(new TableCustomizer("postQueryRecord", AbstractPostQueryCustomizer.class)),
|
PRE_INSERT_RECORD("preInsertRecord", AbstractPreInsertCustomizer.class),
|
||||||
POST_INSERT_RECORD(new TableCustomizer("postInsertRecord", AbstractPostInsertCustomizer.class));
|
POST_INSERT_RECORD("postInsertRecord", AbstractPostInsertCustomizer.class),
|
||||||
|
PRE_UPDATE_RECORD("preUpdateRecord", AbstractPreUpdateCustomizer.class),
|
||||||
|
POST_UPDATE_RECORD("postUpdateRecord", AbstractPostUpdateCustomizer.class),
|
||||||
|
PRE_DELETE_RECORD("preDeleteRecord", AbstractPreDeleteCustomizer.class),
|
||||||
|
POST_DELETE_RECORD("postDeleteRecord", AbstractPostDeleteCustomizer.class);
|
||||||
|
|
||||||
|
|
||||||
private final TableCustomizer tableCustomizer;
|
private final String role;
|
||||||
|
private final Class<?> expectedType;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
TableCustomizers(TableCustomizer tableCustomizer)
|
TableCustomizers(String role, Class<?> expectedType)
|
||||||
{
|
{
|
||||||
this.tableCustomizer = tableCustomizer;
|
this.role = role;
|
||||||
|
this.expectedType = expectedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -59,7 +62,7 @@ public enum TableCustomizers
|
|||||||
{
|
{
|
||||||
for(TableCustomizers value : values())
|
for(TableCustomizers value : values())
|
||||||
{
|
{
|
||||||
if(value.tableCustomizer.getRole().equals(name))
|
if(value.role.equals(name))
|
||||||
{
|
{
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
@ -70,24 +73,23 @@ public enum TableCustomizers
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Getter for tableCustomizer
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public TableCustomizer getTableCustomizer()
|
|
||||||
{
|
|
||||||
return tableCustomizer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** get the role from the tableCustomizer
|
** get the role from the tableCustomizer
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public String getRole()
|
public String getRole()
|
||||||
{
|
{
|
||||||
return (tableCustomizer.getRole());
|
return (role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for expectedType
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Class<?> getExpectedType()
|
||||||
|
{
|
||||||
|
return expectedType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,13 @@ import java.util.HashMap;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||||
import com.kingsrook.qqq.backend.core.actions.audits.DMLAuditAction;
|
import com.kingsrook.qqq.backend.core.actions.audits.DMLAuditAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPreDeleteCustomizer;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
|
||||||
import com.kingsrook.qqq.backend.core.actions.interfaces.DeleteInterface;
|
import com.kingsrook.qqq.backend.core.actions.interfaces.DeleteInterface;
|
||||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
@ -74,6 +78,8 @@ public class DeleteAction
|
|||||||
{
|
{
|
||||||
ActionHelper.validateSession(deleteInput);
|
ActionHelper.validateSession(deleteInput);
|
||||||
|
|
||||||
|
QTableMetaData table = deleteInput.getTable();
|
||||||
|
|
||||||
QBackendModuleDispatcher qBackendModuleDispatcher = new QBackendModuleDispatcher();
|
QBackendModuleDispatcher qBackendModuleDispatcher = new QBackendModuleDispatcher();
|
||||||
QBackendModuleInterface qModule = qBackendModuleDispatcher.getQBackendModule(deleteInput.getBackend());
|
QBackendModuleInterface qModule = qBackendModuleDispatcher.getQBackendModule(deleteInput.getBackend());
|
||||||
DeleteInterface deleteInterface = qModule.getDeleteInterface();
|
DeleteInterface deleteInterface = qModule.getDeleteInterface();
|
||||||
@ -102,6 +108,13 @@ public class DeleteAction
|
|||||||
List<QRecord> recordListForAudit = deleteInterface.supportsPreFetchQuery() ? getRecordListForAuditIfNeeded(deleteInput) : new ArrayList<>();
|
List<QRecord> recordListForAudit = deleteInterface.supportsPreFetchQuery() ? getRecordListForAuditIfNeeded(deleteInput) : new ArrayList<>();
|
||||||
List<QRecord> recordsWithValidationErrors = deleteInterface.supportsPreFetchQuery() ? validateRecordsExistAndCanBeAccessed(deleteInput, recordListForAudit) : new ArrayList<>();
|
List<QRecord> recordsWithValidationErrors = deleteInterface.supportsPreFetchQuery() ? validateRecordsExistAndCanBeAccessed(deleteInput, recordListForAudit) : new ArrayList<>();
|
||||||
|
|
||||||
|
Optional<AbstractPreDeleteCustomizer> preDeleteCustomizer = QCodeLoader.getTableCustomizer(AbstractPreDeleteCustomizer.class, table, TableCustomizers.PRE_DELETE_RECORD.getRole());
|
||||||
|
if(preDeleteCustomizer.isPresent())
|
||||||
|
{
|
||||||
|
preDeleteCustomizer.get().setDeleteInput(deleteInput);
|
||||||
|
preDeleteCustomizer.get().apply(null); // todo monday
|
||||||
|
}
|
||||||
|
|
||||||
DeleteOutput deleteOutput = deleteInterface.execute(deleteInput);
|
DeleteOutput deleteOutput = deleteInterface.execute(deleteInput);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -87,18 +87,16 @@ public class InsertAction extends AbstractQActionFunction<InsertInput, InsertOut
|
|||||||
throw (new QException("Error: Undefined table: " + insertInput.getTableName()));
|
throw (new QException("Error: Undefined table: " + insertInput.getTableName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<AbstractPreInsertCustomizer> preInsertCustomizer = QCodeLoader.getTableCustomizer(AbstractPreInsertCustomizer.class, table, TableCustomizers.PRE_INSERT_RECORD.getRole());
|
|
||||||
Optional<AbstractPostInsertCustomizer> postInsertCustomizer = QCodeLoader.getTableCustomizer(AbstractPostInsertCustomizer.class, table, TableCustomizers.POST_INSERT_RECORD.getRole());
|
|
||||||
setAutomationStatusField(insertInput);
|
setAutomationStatusField(insertInput);
|
||||||
|
|
||||||
QBackendModuleInterface qModule = getBackendModuleInterface(insertInput);
|
QBackendModuleInterface qModule = getBackendModuleInterface(insertInput);
|
||||||
// todo pre-customization - just get to modify the request?
|
|
||||||
|
|
||||||
ValueBehaviorApplier.applyFieldBehaviors(insertInput.getInstance(), table, insertInput.getRecords());
|
ValueBehaviorApplier.applyFieldBehaviors(insertInput.getInstance(), table, insertInput.getRecords());
|
||||||
setErrorsIfUniqueKeyErrors(insertInput, table);
|
setErrorsIfUniqueKeyErrors(insertInput, table);
|
||||||
validateRequiredFields(insertInput);
|
validateRequiredFields(insertInput);
|
||||||
ValidateRecordSecurityLockHelper.validateSecurityFields(insertInput.getTable(), insertInput.getRecords(), ValidateRecordSecurityLockHelper.Action.INSERT);
|
ValidateRecordSecurityLockHelper.validateSecurityFields(insertInput.getTable(), insertInput.getRecords(), ValidateRecordSecurityLockHelper.Action.INSERT);
|
||||||
|
|
||||||
|
Optional<AbstractPreInsertCustomizer> preInsertCustomizer = QCodeLoader.getTableCustomizer(AbstractPreInsertCustomizer.class, table, TableCustomizers.PRE_INSERT_RECORD.getRole());
|
||||||
if(preInsertCustomizer.isPresent())
|
if(preInsertCustomizer.isPresent())
|
||||||
{
|
{
|
||||||
preInsertCustomizer.get().setInsertInput(insertInput);
|
preInsertCustomizer.get().setInsertInput(insertInput);
|
||||||
@ -114,8 +112,6 @@ public class InsertAction extends AbstractQActionFunction<InsertInput, InsertOut
|
|||||||
|
|
||||||
manageAssociations(table, insertOutput.getRecords(), insertInput.getTransaction());
|
manageAssociations(table, insertOutput.getRecords(), insertInput.getTransaction());
|
||||||
|
|
||||||
// todo post-customization - can do whatever w/ the result if you want
|
|
||||||
|
|
||||||
if(insertInput.getOmitDmlAudit())
|
if(insertInput.getOmitDmlAudit())
|
||||||
{
|
{
|
||||||
LOG.debug("Requested to omit DML audit");
|
LOG.debug("Requested to omit DML audit");
|
||||||
@ -125,6 +121,7 @@ public class InsertAction extends AbstractQActionFunction<InsertInput, InsertOut
|
|||||||
new DMLAuditAction().execute(new DMLAuditInput().withTableActionInput(insertInput).withRecordList(insertOutput.getRecords()));
|
new DMLAuditAction().execute(new DMLAuditInput().withTableActionInput(insertInput).withRecordList(insertOutput.getRecords()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<AbstractPostInsertCustomizer> postInsertCustomizer = QCodeLoader.getTableCustomizer(AbstractPostInsertCustomizer.class, table, TableCustomizers.POST_INSERT_RECORD.getRole());
|
||||||
if(postInsertCustomizer.isPresent())
|
if(postInsertCustomizer.isPresent())
|
||||||
{
|
{
|
||||||
postInsertCustomizer.get().setInsertInput(insertInput);
|
postInsertCustomizer.get().setInsertInput(insertInput);
|
||||||
|
@ -27,12 +27,17 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||||
import com.kingsrook.qqq.backend.core.actions.audits.DMLAuditAction;
|
import com.kingsrook.qqq.backend.core.actions.audits.DMLAuditAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.automation.AutomationStatus;
|
import com.kingsrook.qqq.backend.core.actions.automation.AutomationStatus;
|
||||||
import com.kingsrook.qqq.backend.core.actions.automation.RecordAutomationStatusUpdater;
|
import com.kingsrook.qqq.backend.core.actions.automation.RecordAutomationStatusUpdater;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPostUpdateCustomizer;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPreUpdateCustomizer;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
|
||||||
import com.kingsrook.qqq.backend.core.actions.interfaces.UpdateInterface;
|
import com.kingsrook.qqq.backend.core.actions.interfaces.UpdateInterface;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.helpers.ValidateRecordSecurityLockHelper;
|
import com.kingsrook.qqq.backend.core.actions.tables.helpers.ValidateRecordSecurityLockHelper;
|
||||||
import com.kingsrook.qqq.backend.core.actions.values.ValueBehaviorApplier;
|
import com.kingsrook.qqq.backend.core.actions.values.ValueBehaviorApplier;
|
||||||
@ -85,8 +90,9 @@ public class UpdateAction
|
|||||||
ActionHelper.validateSession(updateInput);
|
ActionHelper.validateSession(updateInput);
|
||||||
setAutomationStatusField(updateInput);
|
setAutomationStatusField(updateInput);
|
||||||
|
|
||||||
ValueBehaviorApplier.applyFieldBehaviors(updateInput.getInstance(), updateInput.getTable(), updateInput.getRecords());
|
QTableMetaData table = updateInput.getTable();
|
||||||
// todo - need to handle records with errors coming out of here...
|
|
||||||
|
ValueBehaviorApplier.applyFieldBehaviors(updateInput.getInstance(), table, updateInput.getRecords());
|
||||||
|
|
||||||
QBackendModuleDispatcher qBackendModuleDispatcher = new QBackendModuleDispatcher();
|
QBackendModuleDispatcher qBackendModuleDispatcher = new QBackendModuleDispatcher();
|
||||||
QBackendModuleInterface qModule = qBackendModuleDispatcher.getQBackendModule(updateInput.getBackend());
|
QBackendModuleInterface qModule = qBackendModuleDispatcher.getQBackendModule(updateInput.getBackend());
|
||||||
@ -102,11 +108,17 @@ public class UpdateAction
|
|||||||
}
|
}
|
||||||
|
|
||||||
validateRequiredFields(updateInput);
|
validateRequiredFields(updateInput);
|
||||||
ValidateRecordSecurityLockHelper.validateSecurityFields(updateInput.getTable(), updateInput.getRecords(), ValidateRecordSecurityLockHelper.Action.UPDATE);
|
ValidateRecordSecurityLockHelper.validateSecurityFields(table, updateInput.getRecords(), ValidateRecordSecurityLockHelper.Action.UPDATE);
|
||||||
|
|
||||||
|
Optional<AbstractPreUpdateCustomizer> preUpdateCustomizer = QCodeLoader.getTableCustomizer(AbstractPreUpdateCustomizer.class, table, TableCustomizers.PRE_UPDATE_RECORD.getRole());
|
||||||
|
if(preUpdateCustomizer.isPresent())
|
||||||
|
{
|
||||||
|
preUpdateCustomizer.get().setUpdateInput(updateInput);
|
||||||
|
preUpdateCustomizer.get().setOldRecordList(oldRecordList);
|
||||||
|
updateInput.setRecords(preUpdateCustomizer.get().apply(updateInput.getRecords()));
|
||||||
|
}
|
||||||
|
|
||||||
// todo pre-customization - just get to modify the request?
|
|
||||||
UpdateOutput updateOutput = updateInterface.execute(updateInput);
|
UpdateOutput updateOutput = updateInterface.execute(updateInput);
|
||||||
// todo post-customization - can do whatever w/ the result if you want
|
|
||||||
|
|
||||||
List<String> errors = updateOutput.getRecords().stream().flatMap(r -> r.getErrors().stream()).toList();
|
List<String> errors = updateOutput.getRecords().stream().flatMap(r -> r.getErrors().stream()).toList();
|
||||||
if(CollectionUtils.nullSafeHasContents(errors))
|
if(CollectionUtils.nullSafeHasContents(errors))
|
||||||
@ -125,6 +137,14 @@ public class UpdateAction
|
|||||||
new DMLAuditAction().execute(new DMLAuditInput().withTableActionInput(updateInput).withRecordList(updateOutput.getRecords()).withOldRecordList(oldRecordList));
|
new DMLAuditAction().execute(new DMLAuditInput().withTableActionInput(updateInput).withRecordList(updateOutput.getRecords()).withOldRecordList(oldRecordList));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<AbstractPostUpdateCustomizer> postUpdateCustomizer = QCodeLoader.getTableCustomizer(AbstractPostUpdateCustomizer.class, table, TableCustomizers.POST_UPDATE_RECORD.getRole());
|
||||||
|
if(postUpdateCustomizer.isPresent())
|
||||||
|
{
|
||||||
|
postUpdateCustomizer.get().setUpdateInput(updateInput);
|
||||||
|
postUpdateCustomizer.get().setOldRecordList(oldRecordList);
|
||||||
|
updateOutput.setRecords(postUpdateCustomizer.get().apply(updateOutput.getRecords()));
|
||||||
|
}
|
||||||
|
|
||||||
return updateOutput;
|
return updateOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizer;
|
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecordEntityField;
|
import com.kingsrook.qqq.backend.core.model.data.QRecordEntityField;
|
||||||
@ -525,16 +524,6 @@ public class QTableMetaData implements QAppChildMetaData, Serializable, MetaData
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public QTableMetaData withCustomizer(TableCustomizer tableCustomizer, QCodeReference customizer)
|
|
||||||
{
|
|
||||||
return (withCustomizer(tableCustomizer.getRole(), customizer));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -22,31 +22,25 @@
|
|||||||
package com.kingsrook.qqq.backend.module.filesystem.base.actions;
|
package com.kingsrook.qqq.backend.module.filesystem.base.actions;
|
||||||
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizer;
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public enum FilesystemTableCustomizers
|
public enum FilesystemTableCustomizers
|
||||||
{
|
{
|
||||||
POST_READ_FILE(new TableCustomizer("postReadFile", Function.class, ((Object x) ->
|
POST_READ_FILE("postReadFile", AbstractPostReadFileCustomizer.class);
|
||||||
{
|
|
||||||
Function<String, String> function = (Function<String, String>) x;
|
|
||||||
String output = function.apply(new String());
|
|
||||||
})));
|
|
||||||
|
|
||||||
private final TableCustomizer tableCustomizer;
|
private final String role;
|
||||||
|
private final Class<?> expectedType;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
FilesystemTableCustomizers(TableCustomizer tableCustomizer)
|
FilesystemTableCustomizers(String role, Class<?> expectedType)
|
||||||
{
|
{
|
||||||
this.tableCustomizer = tableCustomizer;
|
this.role = role;
|
||||||
|
this.expectedType = expectedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -59,7 +53,7 @@ public enum FilesystemTableCustomizers
|
|||||||
{
|
{
|
||||||
for(FilesystemTableCustomizers value : values())
|
for(FilesystemTableCustomizers value : values())
|
||||||
{
|
{
|
||||||
if(value.tableCustomizer.getRole().equals(name))
|
if(value.role.equals(name))
|
||||||
{
|
{
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
@ -71,23 +65,22 @@ public enum FilesystemTableCustomizers
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for tableCustomizer
|
** Getter for role
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public TableCustomizer getTableCustomizer()
|
public String getRole()
|
||||||
{
|
{
|
||||||
return tableCustomizer;
|
return role;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** get the role from the tableCustomizer
|
** Getter for expectedType
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public String getRole()
|
public Class<?> getExpectedType()
|
||||||
{
|
{
|
||||||
return (tableCustomizer.getRole());
|
return expectedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user