package io.cattle.platform.core.dao.impl; import io.cattle.platform.core.constants.CommonStatesConstants; import io.cattle.platform.core.dao.GenericMapDao; import io.cattle.platform.object.jooq.utils.JooqUtils; import io.cattle.platform.object.meta.ObjectMetaDataManager; import io.cattle.platform.object.meta.Relationship; import io.github.ibuildthecloud.gdapi.factory.SchemaFactory; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.inject.Named; import org.jooq.Table; import org.jooq.TableField; import org.jooq.UpdatableRecord; @Named public class GenericMapDaoImpl extends AbstractCoreDao implements GenericMapDao { SchemaFactory schemaFactory; ObjectMetaDataManager metaDataManager; @SuppressWarnings("unchecked") @Override public <T> List<? extends T> findNonRemoved(Class<T> mapType, Class<?> resourceType, long resourceId) { String type = schemaFactory.getSchemaName(mapType); Table<?> table = getTable(mapType); Relationship reference = getRelationship(mapType, resourceType); TableField<?, Object> removed = JooqUtils.getTableField(metaDataManager, type, ObjectMetaDataManager.REMOVED_FIELD); TableField<?, Object> referenceField = JooqUtils.getTableField(metaDataManager, type, reference.getPropertyName()); if ( removed == null || referenceField == null ) { throw new IllegalArgumentException("Type [" + mapType + "] is missing required removed or reference column"); } return (List<? extends T>)create() .selectFrom(table) .where( removed.isNull() .and(referenceField.eq(resourceId))) .fetch(); } @SuppressWarnings("unchecked") @Override public <T> T findNonRemoved(Class<T> mapType, Class<?> leftResourceType, long leftResourceId, Class<?> rightResourceType, long rightResourceId) { String type = schemaFactory.getSchemaName(mapType); Table<?> table = getTable(mapType); Relationship leftReference = getRelationship(mapType, leftResourceType); Relationship rightReference = getRelationship(mapType, rightResourceType); TableField<?, Object> removed = JooqUtils.getTableField(metaDataManager, type, ObjectMetaDataManager.REMOVED_FIELD); TableField<?, Object> leftReferenceField = JooqUtils.getTableField(metaDataManager, type, leftReference.getPropertyName()); TableField<?, Object> rightReferenceField = JooqUtils.getTableField(metaDataManager, type, rightReference.getPropertyName()); if ( removed == null || leftReferenceField == null || rightReferenceField == null ) { throw new IllegalArgumentException("Type [" + mapType + "] is missing required removed or references column"); } return (T)create() .selectFrom(table) .where( removed.isNull() .and(leftReferenceField.eq(leftResourceId)) .and(rightReferenceField.eq(rightResourceId))) .fetchOne(); } @SuppressWarnings("unchecked") @Override public <T> List<? extends T> findToRemove(Class<T> mapType, Class<?> resourceType, long resourceId) { String type = schemaFactory.getSchemaName(mapType); Table<?> table = getTable(mapType); Relationship reference = getRelationship(mapType, resourceType); TableField<?, Object> removed = JooqUtils.getTableField(metaDataManager, type, ObjectMetaDataManager.REMOVED_FIELD); TableField<?, Object> referenceField = JooqUtils.getTableField(metaDataManager, type, reference.getPropertyName()); TableField<?, Object> state = JooqUtils.getTableField(metaDataManager, type, ObjectMetaDataManager.STATE_FIELD); if ( removed == null || referenceField == null || state == null ) { throw new IllegalArgumentException("Type [" + mapType + "] is missing required removed, reference, or state column"); } return (List<? extends T>)create() .selectFrom(table) .where( referenceField.eq(resourceId) .and( removed.isNull() .or(state.eq(CommonStatesConstants.REMOVING)))) .fetch(); } @SuppressWarnings("unchecked") @Override public <T> List<? extends T> findNonPurged(Class<T> mapType, Class<?> resourceType, long resourceId) { String type = schemaFactory.getSchemaName(mapType); Table<?> table = getTable(mapType); Relationship reference = getRelationship(mapType, resourceType); TableField<?, Object> referenceField = JooqUtils.getTableField(metaDataManager, type, reference.getPropertyName()); TableField<?, Object> state = JooqUtils.getTableField(metaDataManager, type, ObjectMetaDataManager.STATE_FIELD); if ( referenceField == null || state == null ) { throw new IllegalArgumentException("Type [" + mapType + "] is missing required reference or state column"); } return (List<? extends T>)create() .selectFrom(table) .where( referenceField.eq(resourceId) .and(state.ne(CommonStatesConstants.PURGED))) .fetch(); } protected <T> Table<?> getTable(Class<?> mapType) { Class<UpdatableRecord<?>> record = JooqUtils.getRecordClass(schemaFactory, mapType); return JooqUtils.getTableFromRecordClass(record); } protected Relationship getRelationship(Class<?> mapType, Class<?> resourceType) { Map<String,Relationship> rels = metaDataManager.getLinkRelationships(schemaFactory, schemaFactory.getSchemaName(mapType)); Relationship reference = null; for ( Map.Entry<String,Relationship> entry : rels.entrySet() ) { Relationship rel = entry.getValue(); if ( rel.getRelationshipType() == Relationship.RelationshipType.REFERENCE && resourceType.isAssignableFrom(rel.getObjectType())) { reference = rel; break; } } if ( reference == null ) { throw new IllegalArgumentException("Failed to find reference relationship from [" + mapType + "] to [" + resourceType + "]"); } return reference; } public SchemaFactory getSchemaFactory() { return schemaFactory; } @Inject @Named("CoreSchemaFactory") public void setSchemaFactory(SchemaFactory schemaFactory) { this.schemaFactory = schemaFactory; } public ObjectMetaDataManager getMetaDataManager() { return metaDataManager; } @Inject public void setMetaDataManager(ObjectMetaDataManager metaDataManager) { this.metaDataManager = metaDataManager; } @SuppressWarnings("unchecked") @Override public <T> T findToRemove(Class<T> mapType, Class<?> leftResourceType, long leftResourceId, Class<?> rightResourceType, long rightResourceId) { String type = schemaFactory.getSchemaName(mapType); Table<?> table = getTable(mapType); Relationship leftReference = getRelationship(mapType, leftResourceType); Relationship rightReference = getRelationship(mapType, rightResourceType); TableField<?, Object> removed = JooqUtils.getTableField(metaDataManager, type, ObjectMetaDataManager.REMOVED_FIELD); TableField<?, Object> state = JooqUtils.getTableField(metaDataManager, type, ObjectMetaDataManager.STATE_FIELD); TableField<?, Object> leftReferenceField = JooqUtils.getTableField(metaDataManager, type, leftReference.getPropertyName()); TableField<?, Object> rightReferenceField = JooqUtils.getTableField(metaDataManager, type, rightReference.getPropertyName()); if (removed == null || leftReferenceField == null || rightReferenceField == null) { throw new IllegalArgumentException("Type [" + mapType + "] is missing required removed or references column"); } return (T) create() .selectFrom(table) .where( (removed.isNull().or(state.eq(CommonStatesConstants.REMOVING))) .and(leftReferenceField.eq(leftResourceId)) .and(rightReferenceField.eq(rightResourceId))) .fetchOne(); } }