mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
CE-882 Initial checkin - Meta-data for making a table shareable
This commit is contained in:
@ -624,6 +624,11 @@ public class QInstanceValidator
|
|||||||
supplementalTableMetaData.validate(qInstance, table, this);
|
supplementalTableMetaData.validate(qInstance, table, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(table.getShareableTableMetaData() != null)
|
||||||
|
{
|
||||||
|
table.getShareableTableMetaData().validate(qInstance, table, this);
|
||||||
|
}
|
||||||
|
|
||||||
runPlugins(QTableMetaData.class, table, qInstance);
|
runPlugins(QTableMetaData.class, table, qInstance);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.sharing;
|
||||||
|
|
||||||
|
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.MetaDataProducerInterface;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
||||||
|
import com.kingsrook.qqq.backend.core.processes.implementations.sharing.ShareScope;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class ShareScopePossibleValueMetaDataProducer implements MetaDataProducerInterface<QPossibleValueSource>
|
||||||
|
{
|
||||||
|
public static final String NAME = "shareScope";
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public QPossibleValueSource produce(QInstance qInstance) throws QException
|
||||||
|
{
|
||||||
|
return QPossibleValueSource.newForEnum(NAME, ShareScope.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.sharing;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** As a component of a ShareableTableMetaData instance, define details about
|
||||||
|
** one particular audience type.
|
||||||
|
**
|
||||||
|
** e.g., if a table can be shared to users and groups, there'd be 2 instances of
|
||||||
|
** this object - one like:
|
||||||
|
** - name: user
|
||||||
|
** - fieldName: userId
|
||||||
|
** - sourceTableName: User.TABLE_NAME
|
||||||
|
** - sourceTableKeyFieldName: email (e.g., can be a UK, not just the PKey)
|
||||||
|
**
|
||||||
|
** and another similar, w/ the group-type details.
|
||||||
|
*******************************************************************************/
|
||||||
|
public class ShareableAudienceType implements Serializable
|
||||||
|
{
|
||||||
|
private String name;
|
||||||
|
private String fieldName;
|
||||||
|
private String sourceTableName;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// maybe normally the primary key in the source table, but could be a unique-key instead sometimes //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
private String sourceTableKeyFieldName;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Constructor
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableAudienceType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for name
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return (this.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for name
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for name
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableAudienceType withName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for fieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getFieldName()
|
||||||
|
{
|
||||||
|
return (this.fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for fieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setFieldName(String fieldName)
|
||||||
|
{
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for fieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableAudienceType withFieldName(String fieldName)
|
||||||
|
{
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for sourceTableName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getSourceTableName()
|
||||||
|
{
|
||||||
|
return (this.sourceTableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for sourceTableName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setSourceTableName(String sourceTableName)
|
||||||
|
{
|
||||||
|
this.sourceTableName = sourceTableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for sourceTableName
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableAudienceType withSourceTableName(String sourceTableName)
|
||||||
|
{
|
||||||
|
this.sourceTableName = sourceTableName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for sourceTableKeyFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getSourceTableKeyFieldName()
|
||||||
|
{
|
||||||
|
return (this.sourceTableKeyFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for sourceTableKeyFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setSourceTableKeyFieldName(String sourceTableKeyFieldName)
|
||||||
|
{
|
||||||
|
this.sourceTableKeyFieldName = sourceTableKeyFieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for sourceTableKeyFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableAudienceType withSourceTableKeyFieldName(String sourceTableKeyFieldName)
|
||||||
|
{
|
||||||
|
this.sourceTableKeyFieldName = sourceTableKeyFieldName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,356 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.sharing;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import com.kingsrook.qqq.backend.core.instances.QInstanceValidator;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** meta data to attach to a table, to describe that its records are shareable.
|
||||||
|
*******************************************************************************/
|
||||||
|
public class ShareableTableMetaData implements Serializable
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// this is the name of the table that is a many-to-one join to the table whose records are being shared. //
|
||||||
|
// not the table whose records are shared (the asset table) //
|
||||||
|
// for example: given that we want to share "savedReports", the value here could be "sharedSavedReports" //
|
||||||
|
// and this object will be attached to the savedReports table. //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
private String sharedRecordTableName;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// name of the field in the sharedRecordTable that has a foreign key pointing at the asset table //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
private String assetIdFieldName;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
// name of the scope field in the sharedRecordTable //
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
private String scopeFieldName;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// map of audienceTypes names to type definition objects //
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
private Map<String, ShareableAudienceType> audienceTypes;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////
|
||||||
|
// PVS that lists the available audience types //
|
||||||
|
/////////////////////////////////////////////////
|
||||||
|
private String audienceTypesPossibleValueSourceName;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
// name of a field in "this" table, that has the owner's id //
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
private String thisTableOwnerIdFieldName;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Constructor
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableTableMetaData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for sharedRecordTableName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getSharedRecordTableName()
|
||||||
|
{
|
||||||
|
return (this.sharedRecordTableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for sharedRecordTableName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setSharedRecordTableName(String sharedRecordTableName)
|
||||||
|
{
|
||||||
|
this.sharedRecordTableName = sharedRecordTableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for sharedRecordTableName
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableTableMetaData withSharedRecordTableName(String sharedRecordTableName)
|
||||||
|
{
|
||||||
|
this.sharedRecordTableName = sharedRecordTableName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for assetIdFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getAssetIdFieldName()
|
||||||
|
{
|
||||||
|
return (this.assetIdFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for assetIdFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setAssetIdFieldName(String assetIdFieldName)
|
||||||
|
{
|
||||||
|
this.assetIdFieldName = assetIdFieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for assetIdFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableTableMetaData withAssetIdFieldName(String assetIdFieldName)
|
||||||
|
{
|
||||||
|
this.assetIdFieldName = assetIdFieldName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for scopeFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getScopeFieldName()
|
||||||
|
{
|
||||||
|
return (this.scopeFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for scopeFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setScopeFieldName(String scopeFieldName)
|
||||||
|
{
|
||||||
|
this.scopeFieldName = scopeFieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for scopeFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableTableMetaData withScopeFieldName(String scopeFieldName)
|
||||||
|
{
|
||||||
|
this.scopeFieldName = scopeFieldName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for audienceTypes
|
||||||
|
*******************************************************************************/
|
||||||
|
public Map<String, ShareableAudienceType> getAudienceTypes()
|
||||||
|
{
|
||||||
|
return (this.audienceTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for audienceTypes
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setAudienceTypes(Map<String, ShareableAudienceType> audienceTypes)
|
||||||
|
{
|
||||||
|
this.audienceTypes = audienceTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for audienceTypes
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableTableMetaData withAudienceTypes(Map<String, ShareableAudienceType> audienceTypes)
|
||||||
|
{
|
||||||
|
this.audienceTypes = audienceTypes;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for audienceTypes
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableTableMetaData withAudienceType(ShareableAudienceType audienceType)
|
||||||
|
{
|
||||||
|
if(this.audienceTypes == null)
|
||||||
|
{
|
||||||
|
this.audienceTypes = new LinkedHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(audienceType.getName() == null)
|
||||||
|
{
|
||||||
|
throw (new IllegalArgumentException("Attempt to add an audience type without a name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.audienceTypes.containsKey(audienceType.getName()))
|
||||||
|
{
|
||||||
|
throw (new IllegalArgumentException("Attempt to add more than 1 audience type with the same name [" + audienceType.getName() + "]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.audienceTypes.put(audienceType.getName(), audienceType);
|
||||||
|
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for audienceTypesPossibleValueSourceName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getAudienceTypesPossibleValueSourceName()
|
||||||
|
{
|
||||||
|
return (this.audienceTypesPossibleValueSourceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for audienceTypesPossibleValueSourceName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setAudienceTypesPossibleValueSourceName(String audienceTypesPossibleValueSourceName)
|
||||||
|
{
|
||||||
|
this.audienceTypesPossibleValueSourceName = audienceTypesPossibleValueSourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for audienceTypesPossibleValueSourceName
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableTableMetaData withAudienceTypesPossibleValueSourceName(String audienceTypesPossibleValueSourceName)
|
||||||
|
{
|
||||||
|
this.audienceTypesPossibleValueSourceName = audienceTypesPossibleValueSourceName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for thisTableOwnerIdFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getThisTableOwnerIdFieldName()
|
||||||
|
{
|
||||||
|
return (this.thisTableOwnerIdFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for thisTableOwnerIdFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setThisTableOwnerIdFieldName(String thisTableOwnerIdFieldName)
|
||||||
|
{
|
||||||
|
this.thisTableOwnerIdFieldName = thisTableOwnerIdFieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for thisTableOwnerIdFieldName
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableTableMetaData withThisTableOwnerIdFieldName(String thisTableOwnerIdFieldName)
|
||||||
|
{
|
||||||
|
this.thisTableOwnerIdFieldName = thisTableOwnerIdFieldName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void validate(QInstance qInstance, QTableMetaData tableMetaData, QInstanceValidator qInstanceValidator)
|
||||||
|
{
|
||||||
|
String prefix = "ShareableTableMetaData for table [" + tableMetaData.getName() + "]: ";
|
||||||
|
if(qInstanceValidator.assertCondition(StringUtils.hasContent(sharedRecordTableName), prefix + "missing sharedRecordTableName."))
|
||||||
|
{
|
||||||
|
boolean hasAssetIdFieldName = qInstanceValidator.assertCondition(StringUtils.hasContent(assetIdFieldName), prefix + "missing assetIdFieldName");
|
||||||
|
boolean hasScopeFieldName = qInstanceValidator.assertCondition(StringUtils.hasContent(scopeFieldName), prefix + "missing scopeFieldName");
|
||||||
|
|
||||||
|
QTableMetaData sharedRecordTable = qInstance.getTable(sharedRecordTableName);
|
||||||
|
boolean hasValidSharedRecordTable = qInstanceValidator.assertCondition(sharedRecordTable != null, prefix + "unrecognized sharedRecordTableName [" + sharedRecordTableName + "]");
|
||||||
|
|
||||||
|
if(hasValidSharedRecordTable && hasAssetIdFieldName)
|
||||||
|
{
|
||||||
|
qInstanceValidator.assertCondition(sharedRecordTable.getFields().containsKey(assetIdFieldName), prefix + "unrecognized assertIdFieldName [" + assetIdFieldName + "] in sharedRecordTable [" + sharedRecordTableName + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hasValidSharedRecordTable && hasScopeFieldName)
|
||||||
|
{
|
||||||
|
qInstanceValidator.assertCondition(sharedRecordTable.getFields().containsKey(scopeFieldName), prefix + "unrecognized scopeFieldName [" + scopeFieldName + "] in sharedRecordTable [" + sharedRecordTableName + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(qInstanceValidator.assertCondition(CollectionUtils.nullSafeHasContents(audienceTypes), prefix + "missing audienceTypes"))
|
||||||
|
{
|
||||||
|
for(Map.Entry<String, ShareableAudienceType> entry : audienceTypes.entrySet())
|
||||||
|
{
|
||||||
|
ShareableAudienceType audienceType = entry.getValue();
|
||||||
|
qInstanceValidator.assertCondition(Objects.equals(entry.getKey(), audienceType.getName()), prefix + "inconsistent naming for shareableAudienceType [" + entry.getKey() + "] != [" + audienceType.getName() + "]");
|
||||||
|
if(qInstanceValidator.assertCondition(StringUtils.hasContent(audienceType.getFieldName()), prefix + "missing fieldName for shareableAudienceType [" + entry.getKey() + "]") && hasValidSharedRecordTable)
|
||||||
|
{
|
||||||
|
qInstanceValidator.assertCondition(sharedRecordTable.getFields().containsKey(audienceType.getFieldName()), prefix + "unrecognized fieldName [" + audienceType.getFieldName() + "] for shareableAudienceType [" + entry.getKey() + "] in sharedRecordTable [" + sharedRecordTableName + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* todo - make these optional i guess, because i didn't put user table in qqq
|
||||||
|
boolean hasSourceTableKeyFieldName = qInstanceValidator.assertCondition(StringUtils.hasContent(audienceType.getSourceTableKeyFieldName()), prefix + "missing sourceTableKeyFieldName for shareableAudienceType [" + entry.getKey() + "]");
|
||||||
|
if(qInstanceValidator.assertCondition(qInstance.getTable(audienceType.getSourceTableName()) != null, prefix + "unrecognized sourceTableName [" + audienceType.getSourceTableName() + "] for shareableAudienceType [" + entry.getKey() + "] in sharedRecordTable [" + sharedRecordTableName + "]") && hasSourceTableKeyFieldName)
|
||||||
|
{
|
||||||
|
qInstanceValidator.assertCondition(qInstance.getTable(audienceType.getSourceTableName()).getFields().containsKey(audienceType.getSourceTableKeyFieldName()), prefix + "unrecognized sourceTableKeyFieldName [" + audienceType.getSourceTableKeyFieldName() + "] for shareableAudienceType [" + entry.getKey() + "] in sharedRecordTable [" + sharedRecordTableName + "]");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(StringUtils.hasContent(thisTableOwnerIdFieldName))
|
||||||
|
{
|
||||||
|
qInstanceValidator.assertCondition(tableMetaData.getFields().containsKey(thisTableOwnerIdFieldName), prefix + "unrecognized thisTableOwnerIdFieldName [" + thisTableOwnerIdFieldName + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(StringUtils.hasContent(audienceTypesPossibleValueSourceName))
|
||||||
|
{
|
||||||
|
qInstanceValidator.assertCondition(qInstance.getPossibleValueSource(audienceTypesPossibleValueSourceName) != null, prefix + "unrecognized audienceTypesPossibleValueSourceName [" + audienceTypesPossibleValueSourceName + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -48,6 +48,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.permissions.MetaDataWithPermissionRules;
|
import com.kingsrook.qqq.backend.core.model.metadata.permissions.MetaDataWithPermissionRules;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.permissions.QPermissionRules;
|
import com.kingsrook.qqq.backend.core.model.metadata.permissions.QPermissionRules;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock;
|
import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.sharing.ShareableTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.QTableAutomationDetails;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.QTableAutomationDetails;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.cache.CacheOf;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.cache.CacheOf;
|
||||||
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||||
@ -107,6 +108,7 @@ public class QTableMetaData implements QAppChildMetaData, Serializable, MetaData
|
|||||||
|
|
||||||
private List<ExposedJoin> exposedJoins;
|
private List<ExposedJoin> exposedJoins;
|
||||||
|
|
||||||
|
private ShareableTableMetaData shareableTableMetaData;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -1385,4 +1387,35 @@ public class QTableMetaData implements QAppChildMetaData, Serializable, MetaData
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for shareableTableMetaData
|
||||||
|
*******************************************************************************/
|
||||||
|
public ShareableTableMetaData getShareableTableMetaData()
|
||||||
|
{
|
||||||
|
return (this.shareableTableMetaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for shareableTableMetaData
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setShareableTableMetaData(ShareableTableMetaData shareableTableMetaData)
|
||||||
|
{
|
||||||
|
this.shareableTableMetaData = shareableTableMetaData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for shareableTableMetaData
|
||||||
|
*******************************************************************************/
|
||||||
|
public QTableMetaData withShareableTableMetaData(ShareableTableMetaData shareableTableMetaData)
|
||||||
|
{
|
||||||
|
this.shareableTableMetaData = shareableTableMetaData;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.scheduleing.QScheduleMetaDa
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.security.FieldSecurityLock;
|
import com.kingsrook.qqq.backend.core.model.metadata.security.FieldSecurityLock;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.security.QSecurityKeyType;
|
import com.kingsrook.qqq.backend.core.model.metadata.security.QSecurityKeyType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock;
|
import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.sharing.ShareableTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.Association;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.Association;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.ExposedJoin;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.ExposedJoin;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection;
|
||||||
@ -2004,7 +2005,21 @@ public class QInstanceValidatorTest extends BaseTest
|
|||||||
qInstance.addTable(newTable("B", "id", "aId"));
|
qInstance.addTable(newTable("B", "id", "aId"));
|
||||||
qInstance.addJoin(new QJoinMetaData().withLeftTable("A").withRightTable("B").withName("AB").withType(JoinType.ONE_TO_ONE).withJoinOn(new JoinOn("id", "aId")));
|
qInstance.addJoin(new QJoinMetaData().withLeftTable("A").withRightTable("B").withName("AB").withType(JoinType.ONE_TO_ONE).withJoinOn(new JoinOn("id", "aId")));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testShareableTableMetaData()
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// just make sure we call this class's validator - the rest of its conditions are covered in its own test //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons(qInstance -> qInstance.addTable(newTable("A", "id").withShareableTableMetaData(new ShareableTableMetaData())),
|
||||||
|
"missing sharedRecordTableName");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2113,7 +2128,7 @@ public class QInstanceValidatorTest extends BaseTest
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private QTableMetaData newTable(String tableName, String... fieldNames)
|
protected QTableMetaData newTable(String tableName, String... fieldNames)
|
||||||
{
|
{
|
||||||
QTableMetaData tableMetaData = new QTableMetaData()
|
QTableMetaData tableMetaData = new QTableMetaData()
|
||||||
.withName(tableName)
|
.withName(tableName)
|
||||||
@ -2207,7 +2222,7 @@ public class QInstanceValidatorTest extends BaseTest
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Assert that an instance is valid!
|
** Assert that an instance is valid!
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private void assertValidationSuccess(Consumer<QInstance> setup)
|
public static void assertValidationSuccess(Consumer<QInstance> setup)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.sharing;
|
||||||
|
|
||||||
|
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static com.kingsrook.qqq.backend.core.instances.QInstanceValidatorTest.assertValidationFailureReasons;
|
||||||
|
import static com.kingsrook.qqq.backend.core.instances.QInstanceValidatorTest.assertValidationFailureReasonsAllowingExtraReasons;
|
||||||
|
import static com.kingsrook.qqq.backend.core.instances.QInstanceValidatorTest.assertValidationSuccess;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Unit test for ShareableTableMetaData
|
||||||
|
*******************************************************************************/
|
||||||
|
class ShareableTableMetaDataTest
|
||||||
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testValidation()
|
||||||
|
{
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons(qInstance -> qInstance.addTable(newTable().withShareableTableMetaData(new ShareableTableMetaData())),
|
||||||
|
"missing sharedRecordTableName");
|
||||||
|
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons(qInstance -> qInstance.addTable(newTable().withShareableTableMetaData(new ShareableTableMetaData()
|
||||||
|
.withSharedRecordTableName("notATable")
|
||||||
|
)), "unrecognized sharedRecordTableName");
|
||||||
|
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons(qInstance -> qInstance.addTable(newTable().withShareableTableMetaData(new ShareableTableMetaData()
|
||||||
|
.withAudienceTypesPossibleValueSourceName("notAPVS")
|
||||||
|
)), "unrecognized audienceTypesPossibleValueSourceName");
|
||||||
|
|
||||||
|
assertValidationFailureReasons(qInstance -> qInstance.addTable(newTable().withShareableTableMetaData(new ShareableTableMetaData()
|
||||||
|
.withSharedRecordTableName(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
)), "missing assetIdFieldName",
|
||||||
|
"missing scopeFieldName",
|
||||||
|
"missing audienceTypes");
|
||||||
|
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons(qInstance -> qInstance.addTable(newTable().withShareableTableMetaData(new ShareableTableMetaData()
|
||||||
|
.withSharedRecordTableName(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withAssetIdFieldName("notAField")
|
||||||
|
)), "unrecognized assertIdFieldName");
|
||||||
|
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons(qInstance -> qInstance.addTable(newTable().withShareableTableMetaData(new ShareableTableMetaData()
|
||||||
|
.withSharedRecordTableName(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withScopeFieldName("notAField")
|
||||||
|
)), "unrecognized scopeFieldName");
|
||||||
|
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons(qInstance -> qInstance.addTable(newTable().withShareableTableMetaData(new ShareableTableMetaData()
|
||||||
|
.withSharedRecordTableName(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withAudienceType(new ShareableAudienceType().withName("myType"))
|
||||||
|
)), "missing fieldName for shareableAudienceType");
|
||||||
|
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons(qInstance -> qInstance.addTable(newTable().withShareableTableMetaData(new ShareableTableMetaData()
|
||||||
|
.withSharedRecordTableName(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withAudienceType(new ShareableAudienceType().withName("myType").withFieldName("notAField"))
|
||||||
|
)), "unrecognized fieldName");
|
||||||
|
|
||||||
|
/* todo - corresponding todo in main class
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons(qInstance -> qInstance.addTable(newTable().withShareableTableMetaData(new ShareableTableMetaData()
|
||||||
|
.withSharedRecordTableName(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withAudienceType(new ShareableAudienceType().withName("myType").withFieldName("firstName").withSourceTableName("notATable"))
|
||||||
|
)), "unrecognized sourceTableName");
|
||||||
|
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons(qInstance -> qInstance.addTable(newTable().withShareableTableMetaData(new ShareableTableMetaData()
|
||||||
|
.withSharedRecordTableName(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withAudienceType(new ShareableAudienceType().withName("myType").withFieldName("firstName").withSourceTableName(TestUtils.TABLE_NAME_SHAPE).withSourceTableKeyFieldName("notAField"))
|
||||||
|
)), "unrecognized sourceTableKeyFieldName");
|
||||||
|
*/
|
||||||
|
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons(qInstance -> qInstance.addTable(newTable().withShareableTableMetaData(new ShareableTableMetaData()
|
||||||
|
.withThisTableOwnerIdFieldName("notAField")
|
||||||
|
)), "unrecognized thisTableOwnerIdFieldName");
|
||||||
|
|
||||||
|
assertValidationSuccess(qInstance -> qInstance.addTable(newTable()
|
||||||
|
.withField(new QFieldMetaData("userId", QFieldType.INTEGER))
|
||||||
|
.withShareableTableMetaData(new ShareableTableMetaData()
|
||||||
|
.withSharedRecordTableName(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withAssetIdFieldName("firstName")
|
||||||
|
.withScopeFieldName("firstName")
|
||||||
|
.withThisTableOwnerIdFieldName("userId")
|
||||||
|
.withAudienceTypesPossibleValueSourceName(TestUtils.POSSIBLE_VALUE_SOURCE_STATE)
|
||||||
|
.withAudienceType(new ShareableAudienceType().withName("myType").withFieldName("lastName").withSourceTableName(TestUtils.TABLE_NAME_SHAPE).withSourceTableKeyFieldName("id"))
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
protected QTableMetaData newTable()
|
||||||
|
{
|
||||||
|
QTableMetaData tableMetaData = new QTableMetaData()
|
||||||
|
.withName("A")
|
||||||
|
.withBackendName(TestUtils.DEFAULT_BACKEND_NAME)
|
||||||
|
.withPrimaryKeyField("id");
|
||||||
|
|
||||||
|
tableMetaData.addField(new QFieldMetaData("id", QFieldType.INTEGER));
|
||||||
|
|
||||||
|
return (tableMetaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user