protected UpdatableRecord<?> persistRecord(final UpdatableRecord<?> record) { if (record.field(ObjectMetaDataManager.DATA_FIELD) != null && record.changed(ObjectMetaDataManager.DATA_FIELD)) { record.attach(getLockingConfiguration()); } else if (record.field(ObjectMetaDataManager.STATE_FIELD) != null && record.changed(ObjectMetaDataManager.STATE_FIELD)) { record.attach(getLockingConfiguration()); } else { record.attach(getConfiguration()); } if (record.changed()) { if (record.update() == 0) { throw new IllegalStateException("Failed to update [" + record + "]"); } } return record; }
@Override public Map<String, Object> convertToPropertiesFor(Object obj, Map<Object, Object> values) { Map<String, Object> result = new LinkedHashMap<>(); Class<?> recordClass; if (obj instanceof Class<?>) { recordClass = JooqUtils.getRecordClass(schemaFactory, (Class<?>) obj); } else { UpdatableRecord<?> record = JooqUtils.getRecordObject(obj); recordClass = JooqUtils.getRecordClass(schemaFactory, record.getClass()); } for (Map.Entry<Object, Object> entry : values.entrySet()) { String name = metaDataManager.convertToPropertyNameString(recordClass, entry.getKey()); if (name != null) { result.put(name, entry.getValue()); } } return result; }
@SuppressWarnings("unchecked") public static <T extends UpdatableRecord<?>> T findById(DSLContext context, Class<T> clz, Object id) { if (id == null) return null; Table<?> table = getTableFromRecordClass(clz); if (table == null) return null; UniqueKey<?> key = table.getPrimaryKey(); if (key == null || key.getFieldsArray().length != 1) return null; TableField<?, Object> keyField = (TableField<?, Object>) key.getFieldsArray()[0]; /* Convert object because we are abusing type safety here */ Object converted = keyField.getDataType().convert(id); return (T) context.selectFrom(table).where(keyField.eq(converted)).fetchOne(); }
@SuppressWarnings("unchecked") public static Class<UpdatableRecord<?>> getRecordClass(SchemaFactory factory, Class<?> clz) { if (UpdatableRecord.class.isAssignableFrom(clz)) { return (Class<UpdatableRecord<?>>) clz; } if (factory != null) { Schema schema = factory.getSchema(clz); Class<?> testClz = factory.getSchemaClass(schema.getId()); if (clz.isAssignableFrom(testClz)) { if (!UpdatableRecord.class.isAssignableFrom(testClz)) { throw new IllegalArgumentException("Class [" + testClz + "] is not an instanceof UpdatableRecord"); } return (Class<UpdatableRecord<?>>) testClz; } } throw new IllegalArgumentException("Failed to find UpdatableRecord class for [" + clz + "]"); }
@SuppressWarnings("unchecked") protected <T> T setFieldsInternal(final Object obj, final Map<String,Object> values) { final List<UpdatableRecord<?>> pending = new ArrayList<UpdatableRecord<?>>(); Map<Object,Object> toWrite = toObjectsToWrite(obj, values); setFields(obj, toWrite, pending); if ( pending.size() == 1 ) { persistRecord(pending.get(0)); } else if ( pending.size() > 1 ){ transactionDelegate.doInTransaction(new Runnable() { @Override public void run() { for ( UpdatableRecord<?> record : pending ) { persistRecord(record); } } }); } return (T)obj; }
@SuppressWarnings("unchecked") @Override protected <T> List<T> getListByRelationshipMap(Object obj, MapRelationship rel) { Class<UpdatableRecord<?>> typeClass = JooqUtils.getRecordClass(schemaFactory, rel.getObjectType()); String mappingType = schemaFactory.getSchemaName(rel.getMappingType()); String fromType = schemaFactory.getSchemaName(rel.getObjectType()); TableField<?, Object> fieldFrom = JooqUtils.getTableField(getMetaDataManager(), fromType, ObjectMetaDataManager.ID_FIELD); TableField<?, Object> mappingTo = JooqUtils.getTableField(getMetaDataManager(), mappingType, rel.getOtherRelationship().getPropertyName()); TableField<?, Object> mappingOther = JooqUtils.getTableField(getMetaDataManager(), mappingType, rel.getPropertyName()); TableField<?, Object> mappingRemoved = JooqUtils.getTableField(getMetaDataManager(), mappingType, ObjectMetaDataManager.REMOVED_FIELD); Table<?> table = JooqUtils.getTable(schemaFactory, typeClass); Table<?> mapTable = JooqUtils.getTable(schemaFactory, rel.getMappingType()); SelectQuery<?> query = create().selectQuery(); query.addFrom(table); query.addSelect(table.fields()); query.addJoin(mapTable, fieldFrom.eq(mappingTo) .and(mappingRemoved == null ? DSL.trueCondition() : mappingRemoved.isNull()) .and(mappingOther.eq(ObjectUtils.getId(obj)))); return (List<T>)query.fetchInto(typeClass); }
@Override public Map<String,Object> convertToPropertiesFor(Object obj, Map<Object,Object> values) { Map<String,Object> result = new LinkedHashMap<String, Object>(); Class<?> recordClass = null; if ( obj instanceof Class<?> ) { recordClass = JooqUtils.getRecordClass(schemaFactory, (Class<?>)obj); } else { UpdatableRecord<?> record = JooqUtils.getRecordObject(obj); recordClass = JooqUtils.getRecordClass(schemaFactory, record.getClass()); } for ( Map.Entry<Object, Object> entry : values.entrySet() ) { String name = metaDataManager.convertToPropertyNameString(recordClass, entry.getKey()); if ( name != null ) { result.put(name, entry.getValue()); } } return result; }
@SuppressWarnings("unchecked") public static <T extends UpdatableRecord<?>> T findById(DSLContext context, Class<T> clz, Object id) { if ( id == null ) return null; Table<?> table = getTableFromRecordClass(clz); if ( table == null ) return null; UniqueKey<?> key = table.getPrimaryKey(); if ( key == null || key.getFieldsArray().length != 1 ) return null; TableField<?, Object> keyField = (TableField<?, Object>)key.getFieldsArray()[0]; /* Convert object because we are abusing type safety here */ Object converted = keyField.getDataType().convert(id); return (T)context.selectFrom(table) .where(keyField.eq(converted)) .fetchOne(); }
@SuppressWarnings("unchecked") public static Class<UpdatableRecord<?>> getRecordClass(SchemaFactory factory, Class<?> clz) { if ( UpdatableRecord.class.isAssignableFrom(clz) ) { return (Class<UpdatableRecord<?>>)clz; } if ( factory != null ) { Schema schema = factory.getSchema(clz); Class<?> testClz = factory.getSchemaClass(schema.getId()); if ( clz.isAssignableFrom(testClz) ) { if ( ! UpdatableRecord.class.isAssignableFrom(testClz) ) { throw new IllegalArgumentException("Class [" + testClz + "] is not an instanceof UpdatableRecord"); } return (Class<UpdatableRecord<?>>) testClz; } } throw new IllegalArgumentException("Failed to find UpdatableRecord class for [" + clz + "]"); }
@Override public boolean checkPermission(List<Agency> roles, UpdatableRecord<?> target, Relationship permission) { if (target == null) { return true; } try { return checkPermission(roles, permission, (UUID) AUTHORITY_HANDLE.get(target.getClass()) .bindTo(target) .invokeExact()); } catch (Throwable e) { throw new IllegalStateException(String.format("Cannot retrieve authority for %s", target.getClass()), e); } }
@SuppressWarnings("unchecked") public static List<UpdatableRecord<? extends UpdatableRecord<? extends UpdatableRecord<?>>>> selectForDelete(DSLContext create, Product definingProduct) { List<UpdatableRecord<? extends UpdatableRecord<? extends UpdatableRecord<?>>>> records = new ArrayList<>(); Ruleform.RULEFORM.getTables() .forEach(t -> { records.addAll(create.selectDistinct(t.fields()) .from(t) .where(((Field<UUID>) t.field("workspace")).equal(definingProduct.getId())) .and(((Field<UUID>) t.field("id")).notEqual(definingProduct.getId())) .fetchInto(t.getRecordType()) .stream() .map(r -> (UpdatableRecord<?>) r) .collect(Collectors.toList())); }); return records; }
@SuppressWarnings("unchecked") public static List<UpdatableRecord<? extends UpdatableRecord<? extends UpdatableRecord<?>>>> selectWorkspaceClosure(DSLContext create, Product definingProduct) { List<UpdatableRecord<? extends UpdatableRecord<? extends UpdatableRecord<?>>>> records = new ArrayList<>(); Ruleform.RULEFORM.getTables() .forEach(t -> { records.addAll(create.selectDistinct(t.fields()) .from(t) .where(((Field<UUID>) t.field("workspace")).equal(definingProduct.getId())) .and(((Field<UUID>) t.field("id")).notEqual(definingProduct.getId())) .fetchInto(t.getRecordType()) .stream() .map(r -> (UpdatableRecord<?>) r) .map(r -> { Field<Integer> version = (Field<Integer>) t.field("version"); r.setValue(version, r.get(version) .intValue() - 1); return r; }) .collect(Collectors.toList())); }); return records; }
/** * Add the list of children to the instance * * @param facet * @param instance * @param auth * @param children */ public ExistentialRuleform addChildren(Aspect facet, ExistentialRuleform instance, NetworkAuthorization auth, List<ExistentialRuleform> children) { if (instance == null) { return null; } if (!model.checkUpdate(facet.getFacet()) || !model.checkUpdate(auth.getAuth())) { return instance; } children.stream() .filter(child -> model.checkRead((UpdatableRecord<?>) child)) .peek(child -> cast(child, auth.getChild())) .forEach(child -> model.getPhantasmModel() .link(instance, auth.getRelationship(), child)); return instance; }
/** * Answer the inferred and immediate network children of the instance * * @param facet * @param instance * @param auth * * @return */ public List<ExistentialRuleform> getChildren(Aspect facet, ExistentialRuleform instance, NetworkAuthorization auth) { if (instance == null) { return Collections.emptyList(); } if (!model.checkRead(facet.getFacet()) || !model.checkRead(auth.getAuth())) { return Collections.emptyList(); } return model.getPhantasmModel() .getConstrainedChildren(instance, auth.getRelationship(), auth.getChild() .getClassifier(), auth.getChild() .getClassification(), auth.getDomain()) .stream() .filter(child -> model.checkRead((UpdatableRecord<?>) child)) .collect(Collectors.toList()); }
/** * Answer the immediate, non inferred children of the instance * * @param facet * @param instance * @param auth * * @return */ public List<ExistentialRuleform> getImmediateChildren(Aspect facet, ExistentialRuleform instance, NetworkAuthorization auth) { if (instance == null) { return Collections.emptyList(); } if (!model.checkRead(facet.getFacet()) || !model.checkRead(auth.getAuth())) { return Collections.emptyList(); } return model.getPhantasmModel() .getImmediateConstrainedChildren(instance, auth.getRelationship(), auth.getChild() .getClassifier(), auth.getChild() .getClassification(), auth.getDomain()) .stream() .map(r -> r) .filter(child -> model.checkRead((UpdatableRecord<?>) child)) .collect(Collectors.toList()); }
/** * Answer the list of instances of this facet. * * @param facet * @return */ public List<ExistentialRuleform> getInstances(Aspect facet) { if (!model.checkRead(facet.getFacet())) { return Collections.emptyList(); } return model.getPhantasmModel() .getChildrenUuid(facet.getClassification() .getId(), facet.getClassifier() .getInverse(), facet.getDomain()) .stream() .map(e -> e) .filter(instance -> model.checkRead((UpdatableRecord<?>) instance)) .collect(Collectors.toList()); }
/** * Answer the singular network child of the instance * * @param facet * @param instance * @param auth * * @return */ public ExistentialRuleform getSingularChild(Aspect facet, ExistentialRuleform instance, NetworkAuthorization auth) { if (instance == null) { return null; } if (!model.checkRead(facet.getFacet()) || !model.checkRead(auth.getAuth())) { return null; } ExistentialRuleform child = model.getPhantasmModel() .getImmediateChild(instance, auth.getRelationship(), auth.getDomain()); return model.checkRead((UpdatableRecord<?>) child) ? child : null; }
/** * Set the immediate children of the instance to be the list of supplied * children. No inferred links will be explicitly added or deleted. * * @param facet * @param instance * @param auth * @param children */ public ExistentialRuleform setChildren(Aspect facet, ExistentialRuleform instance, NetworkAuthorization auth, List<ExistentialRuleform> children) { if (instance == null) { return null; } if (!model.checkUpdate(facet.getFacet()) || !model.checkUpdate(auth.getAuth())) { return instance; } model.getPhantasmModel() .unlinkImmediate(instance, auth.getRelationship()); children.stream() .filter(child -> model.checkRead((UpdatableRecord<?>) child)) .peek(child -> cast(child, auth.getChild())) .forEach(child -> model.getPhantasmModel() .link(instance, auth.getRelationship(), child)); return instance; }
@Override public List<Agency> agencies(@GraphQLName("ids") List<UUID> ids, DataFetchingEnvironment env) { if (ids == null) { return resolved(env, ExistentialDomain.Agency).stream() .map(r -> new Agency(r)) .collect(Collectors.toList()); } Model model = WorkspaceSchema.ctx(env); return ids.stream() .map(s -> s) .map(id -> resolve(env, id)) .filter(r -> model.checkRead((UpdatableRecord<?>) r)) .map(r -> new Agency((ExistentialRecord) r)) .collect(Collectors.toList()); }
@Override public List<Attribute> attributes(@GraphQLName("ids") List<UUID> ids, DataFetchingEnvironment env) { if (ids == null) { return resolved(env, ExistentialDomain.Attribute).stream() .map(r -> new Attribute(r)) .collect(Collectors.toList()); } Model model = ctx(env); return ids.stream() .map(s -> s) .map(id -> resolve(env, id)) .filter(r -> model.checkRead((UpdatableRecord<?>) r)) .map(r -> new Attribute((ExistentialRecord) r)) .collect(Collectors.toList()); }
@Override public List<Interval> intervals(@GraphQLName("ids") List<UUID> ids, DataFetchingEnvironment env) { if (ids == null) { return resolved(env, ExistentialDomain.Interval).stream() .map(r -> new Interval(r)) .collect(Collectors.toList()); } Model model = ctx(env); return ids.stream() .map(s -> s) .map(id -> resolve(env, id)) .filter(r -> model.checkRead((UpdatableRecord<?>) r)) .map(r -> new Interval((ExistentialRecord) r)) .collect(Collectors.toList()); }
@Override public List<Location> locations(@GraphQLName("ids") List<UUID> ids, DataFetchingEnvironment env) { if (ids == null) { return resolved(env, ExistentialDomain.Location).stream() .map(r -> new Location(r)) .collect(Collectors.toList()); } Model model = ctx(env); return ids.stream() .map(s -> s) .map(id -> resolve(env, id)) .filter(r -> model.checkRead((UpdatableRecord<?>) r)) .map(r -> new Location((ExistentialRecord) r)) .collect(Collectors.toList()); }
@Override public List<Product> products(@GraphQLName("ids") List<UUID> ids, DataFetchingEnvironment env) { if (ids == null) { return resolved(env, ExistentialDomain.Product).stream() .map(r -> new Product(r)) .collect(Collectors.toList()); } Model model = ctx(env); return ids.stream() .map(s -> s) .map(id -> resolve(env, id)) .filter(r -> model.checkRead((UpdatableRecord<?>) r)) .map(r -> new Product((ExistentialRecord) r)) .collect(Collectors.toList()); }
@Override public List<Relationship> relationships(@GraphQLName("ids") List<UUID> ids, DataFetchingEnvironment env) { if (ids == null) { return resolved(env, ExistentialDomain.Relationship).stream() .map(r -> new Relationship(r)) .collect(Collectors.toList()); } Model model = ctx(env); return ids.stream() .map(s -> s) .map(id -> resolve(env, id)) .filter(r -> model.checkRead((UpdatableRecord<?>) r)) .map(r -> new Relationship((ExistentialRecord) r)) .collect(Collectors.toList()); }
@Override public List<StatusCode> statusCodes(@GraphQLName("ids") List<UUID> ids, DataFetchingEnvironment env) { if (ids == null) { return resolved(env, ExistentialDomain.StatusCode).stream() .map(r -> new StatusCode(r)) .collect(Collectors.toList()); } Model model = ctx(env); return ids.stream() .map(s -> s) .map(id -> resolve(env, id)) .filter(r -> model.checkRead((UpdatableRecord<?>) r)) .map(r -> new StatusCode((ExistentialRecord) r)) .collect(Collectors.toList()); }
@Override public List<Unit> units(@GraphQLName("ids") List<UUID> ids, DataFetchingEnvironment env) { if (ids == null) { return resolved(env, ExistentialDomain.Unit).stream() .map(r -> new Unit(r)) .collect(Collectors.toList()); } Model model = ctx(env); return ids.stream() .map(s -> s) .map(id -> resolve(env, id)) .filter(r -> model.checkRead((UpdatableRecord<?>) r)) .map(r -> new Unit((ExistentialRecord) r)) .collect(Collectors.toList()); }
private void set(UpdatableRecord<?> instance, Map<String, GraphQLType> types, Map<String, Object> state) { state.entrySet() .stream() .filter(entry -> !entry.getKey() .equals("id")) .forEach(entry -> { try { PropertyUtils.setProperty(instance, entry.getKey(), entry.getValue()); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { throw new IllegalArgumentException(String.format("Illegal property: %s", entry)); } }); }
@SuppressWarnings("unchecked") @Override public <T> T instantiate(Class<T> clz, Map<String, Object> properties) { Class<UpdatableRecord<?>> recordClass = JooqUtils.getRecordClass(schemaFactory, clz); UpdatableRecord<?> record = JooqUtils.getRecord(recordClass); record.attach(getConfiguration()); return (T) record; }
@Override public <T> T insert(T instance, Class<T> clz, Map<String, Object> properties) { final UpdatableRecord<?> record = JooqUtils.getRecordObject(instance); record.attach(configuration); Idempotent.change(record::insert); return instance; }
@Override public <T> T reload(T obj) { if (obj == null) { return null; } UpdatableRecord<?> record = JooqUtils.getRecordObject(obj); record.attach(getConfiguration()); record.refresh(); return obj; }
@Override public <T> T persist(T obj) { final UpdatableRecord<?> record = JooqUtils.getRecordObject(obj); record.attach(getConfiguration()); record.update(); Idempotent.change(() -> persistRecord(record)); return obj; }
protected void persistFields(Schema schema, Object obj, Map<String, Object> values) { if (schema == null) { String type = getPossibleSubType(obj, values); schema = schemaFactory.getSchema(type); } UpdatableRecord<?> record = JooqUtils.getRecordObject(obj); for (Map.Entry<String, Object> entry : values.entrySet()) { setField(schema, record, entry.getKey(), entry.getValue()); } persistRecord(record); }
protected ResultQuery<?> toQuery(Class<?> clz, Map<Object, Object> values) { String type = schemaFactory.getSchemaName(clz); if (type == null) { throw new IllegalArgumentException("Failed to find type of class [" + clz + "]"); } Class<UpdatableRecord<?>> recordClass = JooqUtils.getRecordClass(schemaFactory, clz); Table<?> table = JooqUtils.getTableFromRecordClass(recordClass); return create().selectFrom(table).where(JooqUtils.toConditions(metaDataManager, type, values)); }
@SuppressWarnings("unchecked") protected <T> T loadResource(Class<T> type, Object resourceId) { if (resourceId == null || type == null) { return null; } Class<UpdatableRecord<?>> clz = JooqUtils.getRecordClass(schemaFactory, type); return (T) JooqUtils.findById(DSL.using(getConfiguration()), clz, resourceId); }
@SuppressWarnings("unchecked") public static <T extends UpdatableRecord<?>> T getRecordObject(Object obj) { if (obj == null) return null; if (obj instanceof UpdatableRecord<?>) { return (T) obj; } throw new IllegalArgumentException("Expected instance of [" + UpdatableRecord.class + "] got [" + obj.getClass() + "]"); }