/** * Add given class to dictionary. * * @param cls Entity bean class */ @Override public void bindEntity(Class<?> cls) { String type = WordUtils.uncapitalize(cls.getSimpleName()); Class<?> duplicate = bindJsonApiToEntity.put(type, cls); if (duplicate != null && !duplicate.equals(cls)) { log.error("Duplicate binding {} for {}, {}", type, cls, duplicate); throw new DuplicateMappingException(type + " " + cls.getName() + ":" + duplicate.getName()); } entityBindings.put(cls, new EntityBinding(this, cls, type, type)); } }
/** * Bind an attribute or relationship. * * @param fieldOrMethod Field or method to bind */ private void bindAttrOrRelation(AccessibleObject fieldOrMethod) { boolean isRelation = RELATIONSHIP_TYPES.stream().anyMatch(fieldOrMethod::isAnnotationPresent); String fieldName = getFieldName(fieldOrMethod); Class<?> fieldType = getFieldType(fieldOrMethod); if (fieldName == null || "id".equals(fieldName) || "class".equals(fieldName) || OBJ_METHODS.contains(fieldOrMethod)) { return; // Reserved } if (fieldOrMethod instanceof Method) { Method method = (Method) fieldOrMethod; requestScopeableMethods.put(method, isRequestScopeableMethod(method)); } if (isRelation) { bindRelation(fieldOrMethod, fieldName, fieldType); } else { bindAttr(fieldOrMethod, fieldName, fieldType); } }
bindTriggerIfPresent(OnCreatePreSecurity.class, fieldOrMethod); bindTriggerIfPresent(OnDeletePreSecurity.class, fieldOrMethod); bindTriggerIfPresent(OnUpdatePreSecurity.class, fieldOrMethod); bindTriggerIfPresent(OnReadPreSecurity.class, fieldOrMethod); bindTriggerIfPresent(OnCreatePreCommit.class, fieldOrMethod); bindTriggerIfPresent(OnDeletePreCommit.class, fieldOrMethod); bindTriggerIfPresent(OnUpdatePreCommit.class, fieldOrMethod); bindTriggerIfPresent(OnReadPreCommit.class, fieldOrMethod); bindTriggerIfPresent(OnCreatePostCommit.class, fieldOrMethod); bindTriggerIfPresent(OnDeletePostCommit.class, fieldOrMethod); bindTriggerIfPresent(OnUpdatePostCommit.class, fieldOrMethod); bindTriggerIfPresent(OnReadPostCommit.class, fieldOrMethod); bindEntityId(cls, type, fieldOrMethod); } else if (fieldOrMethod.isAnnotationPresent(Transient.class) && !fieldOrMethod.isAnnotationPresent(ComputedAttribute.class) continue; // Field must have Column annotation? bindAttrOrRelation(fieldOrMethod);
jsonApiType = type; entityName = name; inheritedTypes = getInheritedTypes(cls); List<AccessibleObject> fieldOrMethodList = getAllFields(); getInstanceMembers(cls.getMethods(), (method) -> method.isAnnotationPresent(ComputedAttribute.class) || method.isAnnotationPresent(ComputedRelationship.class) fieldOrMethodList.addAll(getInstanceMembers(cls.getFields())); fieldOrMethodList.addAll(getInstanceMembers(cls.getMethods())); bindEntityFields(cls, type, fieldOrMethodList); attributes = dequeToList(attributesDeque); relationships = dequeToList(relationshipsDeque); entityPermissions = new EntityPermissions(dictionary, cls, fieldOrMethodList);
bindTrigger(annotationClass, callback); } else { bindTrigger(annotationClass, value, callback);
/** * Returns whether the entire entity uses Field or Property level access. * @param entityClass Entity Class * @return The JPA Access Type */ public AccessType getAccessType(Class<?> entityClass) { return getEntityBinding(entityClass).getAccessType(); }
jsonApiType = type; entityName = name; inheritedTypes = getInheritedTypes(cls); List<AccessibleObject> fieldOrMethodList = getAllFields(); getInstanceMembers(cls.getMethods(), (method) -> method.isAnnotationPresent(ComputedAttribute.class) || method.isAnnotationPresent(ComputedRelationship.class) fieldOrMethodList.addAll(getInstanceMembers(cls.getFields())); fieldOrMethodList.addAll(getInstanceMembers(cls.getMethods())); bindEntityFields(cls, type, fieldOrMethodList); attributes = dequeToList(attributesDeque); relationships = dequeToList(relationshipsDeque); entityPermissions = new EntityPermissions(dictionary, cls, fieldOrMethodList);
/** * Binds a lifecycle hook to a particular entity class. The hook will either be called: * - A single time single time per request per class READ, CREATE, UPDATE, or DELETE. * - Multiple times per request per field READ, CREATE, or UPDATE. * * The behavior is determined by the value of the {@code allowMultipleInvocations} flag. * @param entityClass The entity that triggers the lifecycle hook. * @param annotationClass (OnReadPostCommit, OnUpdatePreSecurity, etc) * @param callback The callback function to invoke. * @param allowMultipleInvocations Should the same life cycle hook be invoked multiple times for multiple * CRUD actions on the same model. */ public void bindTrigger(Class<?> entityClass, Class<? extends Annotation> annotationClass, LifeCycleHook callback, boolean allowMultipleInvocations) { bindIfUnbound(entityClass); if (allowMultipleInvocations) { getEntityBinding(entityClass).bindTrigger(annotationClass, callback); } else { getEntityBinding(entityClass).bindTrigger(annotationClass, PersistentResource.CLASS_NO_FIELD, callback); } }
/** * Returns whether the entire entity uses Field or Property level access. * @param entityClass Entity Class * @return The JPA Access Type */ public AccessType getAccessType(Class<?> entityClass) { return getEntityBinding(entityClass).getAccessType(); }
/** * Bind an attribute or relationship. * * @param fieldOrMethod Field or method to bind */ private void bindAttrOrRelation(AccessibleObject fieldOrMethod) { boolean isRelation = RELATIONSHIP_TYPES.stream().anyMatch(fieldOrMethod::isAnnotationPresent); String fieldName = getFieldName(fieldOrMethod); Class<?> fieldType = getFieldType(fieldOrMethod); if (fieldName == null || "id".equals(fieldName) || "class".equals(fieldName) || OBJ_METHODS.contains(fieldOrMethod)) { return; // Reserved } if (fieldOrMethod instanceof Method) { Method method = (Method) fieldOrMethod; requestScopeableMethods.put(method, isRequestScopeableMethod(method)); } if (isRelation) { bindRelation(fieldOrMethod, fieldName, fieldType); } else { bindAttr(fieldOrMethod, fieldName, fieldType); } }
bindTriggerIfPresent(OnCreatePreSecurity.class, fieldOrMethod); bindTriggerIfPresent(OnDeletePreSecurity.class, fieldOrMethod); bindTriggerIfPresent(OnUpdatePreSecurity.class, fieldOrMethod); bindTriggerIfPresent(OnReadPreSecurity.class, fieldOrMethod); bindTriggerIfPresent(OnCreatePreCommit.class, fieldOrMethod); bindTriggerIfPresent(OnDeletePreCommit.class, fieldOrMethod); bindTriggerIfPresent(OnUpdatePreCommit.class, fieldOrMethod); bindTriggerIfPresent(OnReadPreCommit.class, fieldOrMethod); bindTriggerIfPresent(OnCreatePostCommit.class, fieldOrMethod); bindTriggerIfPresent(OnDeletePostCommit.class, fieldOrMethod); bindTriggerIfPresent(OnUpdatePostCommit.class, fieldOrMethod); bindTriggerIfPresent(OnReadPostCommit.class, fieldOrMethod); bindEntityId(cls, type, fieldOrMethod); } else if (fieldOrMethod.isAnnotationPresent(Transient.class) && !fieldOrMethod.isAnnotationPresent(ComputedAttribute.class) continue; // Field must have Column annotation? bindAttrOrRelation(fieldOrMethod);
/** * Add given class to dictionary. * * @param cls Entity bean class */ @Override public void bindEntity(Class<?> cls) { String type = WordUtils.uncapitalize(cls.getSimpleName()); Class<?> duplicate = bindJsonApiToEntity.put(type, cls); if (duplicate != null && !duplicate.equals(cls)) { log.error("Duplicate binding {} for {}, {}", type, cls, duplicate); throw new DuplicateMappingException(type + " " + cls.getName() + ":" + duplicate.getName()); } entityBindings.put(cls, new EntityBinding(this, cls, type, type)); } }
/** * Binds a lifecycle hook to a particular entity class. The hook will either be called: * - A single time single time per request per class READ, CREATE, UPDATE, or DELETE. * - Multiple times per request per field READ, CREATE, or UPDATE. * * The behavior is determined by the value of the {@code allowMultipleInvocations} flag. * @param entityClass The entity that triggers the lifecycle hook. * @param annotationClass (OnReadPostCommit, OnUpdatePreSecurity, etc) * @param callback The callback function to invoke. * @param allowMultipleInvocations Should the same life cycle hook be invoked multiple times for multiple * CRUD actions on the same model. */ public void bindTrigger(Class<?> entityClass, Class<? extends Annotation> annotationClass, LifeCycleHook callback, boolean allowMultipleInvocations) { bindIfUnbound(entityClass); if (allowMultipleInvocations) { getEntityBinding(entityClass).bindTrigger(annotationClass, callback); } else { getEntityBinding(entityClass).bindTrigger(annotationClass, PersistentResource.CLASS_NO_FIELD, callback); } }
entityBindings.putIfAbsent(lookupEntityClass(cls), new EntityBinding(this, cls, type, name)); if (include.rootLevel()) { bindEntityRoots.add(cls);
bindTrigger(annotationClass, callback); } else { bindTrigger(annotationClass, value, callback);
entityBindings.putIfAbsent(lookupEntityClass(cls), new EntityBinding(this, cls, type, name)); if (include.rootLevel()) { bindEntityRoots.add(cls);
/** * Binds a lifecycle hook to a particular field or method in an entity. The hook will be called a * single time per request per field READ, CREATE, or UPDATE. * @param entityClass The entity that triggers the lifecycle hook. * @param annotationClass (OnReadPostCommit, OnUpdatePreSecurity, etc) * @param fieldOrMethodName The name of the field or method * @param callback The callback function to invoke. */ public void bindTrigger(Class<?> entityClass, Class<? extends Annotation> annotationClass, String fieldOrMethodName, LifeCycleHook callback) { bindIfUnbound(entityClass); getEntityBinding(entityClass).bindTrigger(annotationClass, fieldOrMethodName, callback); }
/** * Binds a lifecycle hook to a particular field or method in an entity. The hook will be called a * single time per request per field READ, CREATE, or UPDATE. * @param entityClass The entity that triggers the lifecycle hook. * @param annotationClass (OnReadPostCommit, OnUpdatePreSecurity, etc) * @param fieldOrMethodName The name of the field or method * @param callback The callback function to invoke. */ public void bindTrigger(Class<?> entityClass, Class<? extends Annotation> annotationClass, String fieldOrMethodName, LifeCycleHook callback) { bindIfUnbound(entityClass); getEntityBinding(entityClass).bindTrigger(annotationClass, fieldOrMethodName, callback); }