Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2006-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package grails.web.databinding;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import jakarta.servlet.ServletRequest;
import groovy.lang.GroovySystem;
import groovy.lang.MetaClass;
import org.springframework.context.ApplicationContext;
import org.springframework.util.ReflectionUtils;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import grails.core.GrailsApplication;
import grails.databinding.CollectionDataBindingSource;
import grails.databinding.DataBinder;
import grails.databinding.DataBindingSource;
import grails.util.Environment;
import grails.util.Holders;
import grails.validation.ValidationErrors;
import grails.web.mime.MimeType;
import grails.web.mime.MimeTypeResolver;
import grails.web.mime.MimeTypeUtils;
import org.grails.core.exceptions.GrailsConfigurationException;
import org.grails.datastore.mapping.model.PersistentEntity;
import org.grails.datastore.mapping.model.PersistentProperty;
import org.grails.datastore.mapping.model.types.OneToOne;
import org.grails.web.databinding.DefaultASTDatabindingHelper;
import org.grails.web.databinding.bindingsource.DataBindingSourceRegistry;
import org.grails.web.databinding.bindingsource.DefaultDataBindingSourceRegistry;
import org.grails.web.databinding.bindingsource.InvalidRequestBodyException;
/**
* Utility methods to perform data binding from Grails objects.
*
* @author Graeme Rocher
* @since 1.0
*/
@SuppressWarnings("rawtypes")
public final class DataBindingUtils {
public static final String DATA_BINDER_BEAN_NAME = "grailsWebDataBinder";
private static final String BLANK = "";
private static final Map CLASS_TO_BINDING_INCLUDE_LIST = new ConcurrentHashMap<>();
private DataBindingUtils() {
}
/**
* Associations both sides of any bidirectional relationships found in the object and source map to bind
*
* @param object The object
* @param source The source map
* @param persistentEntity The PersistentEntity for the object
*/
public static void assignBidirectionalAssociations(Object object, Map source, PersistentEntity persistentEntity) {
if (source == null) {
return;
}
for (Object key : source.keySet()) {
String propertyName = key.toString();
if (propertyName.contains(".")) {
propertyName = propertyName.substring(0, propertyName.indexOf('.'));
}
PersistentProperty prop = persistentEntity.getPropertyByName(propertyName);
if (prop != null && prop instanceof OneToOne && ((OneToOne) prop).isBidirectional()) {
Object val = source.get(key);
PersistentProperty otherSide = ((OneToOne) prop).getInverseSide();
if (val != null && otherSide != null) {
MetaClass mc = GroovySystem.getMetaClassRegistry().getMetaClass(val.getClass());
try {
mc.setProperty(val, otherSide.getName(), object);
}
catch (Exception ignored) {
// ignore
}
}
}
}
}
/**
* Binds the given source object to the given target object performing type conversion if necessary
*
* @param object The object to bind to
* @param source The source object
* @return A BindingResult if there were errors or null if it was successful
*/
public static BindingResult bindObjectToInstance(Object object, Object source) {
return bindObjectToInstance(object, source, getBindingIncludeList(object), Collections.emptyList(), null);
}
protected static List getBindingIncludeList(final Object object) {
List includeList = Collections.emptyList();
try {
Class> objectClass = object.getClass();
if (CLASS_TO_BINDING_INCLUDE_LIST.containsKey(objectClass)) {
includeList = CLASS_TO_BINDING_INCLUDE_LIST.get(objectClass);
}
else {
Field whiteListField = objectClass.getDeclaredField(DefaultASTDatabindingHelper.DEFAULT_DATABINDING_WHITELIST);
if (whiteListField != null) {
if ((whiteListField.getModifiers() & Modifier.STATIC) != 0) {
Object whiteListValue = whiteListField.get(objectClass);
if (whiteListValue instanceof List) {
includeList = (List) whiteListValue;
}
}
}
if (!Environment.getCurrent().isReloadEnabled()) {
CLASS_TO_BINDING_INCLUDE_LIST.put(objectClass, includeList);
}
}
}
catch (Exception ignored) {
}
return includeList;
}
/**
* Binds the given source object to the given target object performing type conversion if necessary
*
* @param entity The PersistentEntity instance
* @param object The object to bind to
* @param source The source object
*
* @see org.grails.datastore.mapping.model.PersistentEntity
*
* @return A BindingResult if there were errors or null if it was successful
*/
public static BindingResult bindObjectToDomainInstance(PersistentEntity entity, Object object, Object source) {
return bindObjectToDomainInstance(entity, object, source, getBindingIncludeList(object), Collections.emptyList(), null);
}
/**
* For each DataBindingSource provided by collectionBindingSource a new instance of targetType is created,
* data binding is imposed on that instance with the DataBindingSource and the instance is added to the end of
* collectionToPopulate
*
* @param targetType The type of objects to create, must be a concrete class
* @param collectionToPopulate A collection to populate with new instances of targetType
* @param collectionBindingSource A CollectionDataBindingSource
* @since 2.3
*/
public static void bindToCollection(Class targetType, Collection collectionToPopulate,
CollectionDataBindingSource collectionBindingSource)
throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
GrailsApplication application = Holders.findApplication();
PersistentEntity entity = null;
if (application != null) {
try {
entity = application.getMappingContext().getPersistentEntity(targetType.getName());
}
catch (GrailsConfigurationException ignored) {
//no-op
}
}
List dataBindingSources = collectionBindingSource.getDataBindingSources();
for (DataBindingSource dataBindingSource : dataBindingSources) {
T newObject = ReflectionUtils.accessibleConstructor(targetType).newInstance();
bindObjectToDomainInstance(entity, newObject, dataBindingSource, getBindingIncludeList(newObject), Collections.emptyList(), null);
collectionToPopulate.add(newObject);
}
}
public static void bindToCollection(Class targetType,
Collection collectionToPopulate, ServletRequest request)
throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
GrailsApplication grailsApplication = Holders.findApplication();
CollectionDataBindingSource collectionDataBindingSource = createCollectionDataBindingSource(grailsApplication, targetType, request);
bindToCollection(targetType, collectionToPopulate, collectionDataBindingSource);
}
/**
* Binds the given source object to the given target object performing type conversion if necessary
*
* @param object The object to bind to
* @param source The source object
* @param include The list of properties to include
* @param exclude The list of properties to exclude
* @param filter The prefix to filter by
*
* @return A BindingResult if there were errors or null if it was successful
*/
public static BindingResult bindObjectToInstance(Object object, Object source, List include, List exclude, String filter) {
if (include == null && exclude == null) {
include = getBindingIncludeList(object);
}
GrailsApplication application = Holders.findApplication();
PersistentEntity entity = null;
if (application != null) {
try {
entity = application.getMappingContext().getPersistentEntity(object.getClass().getName());
}
catch (GrailsConfigurationException ignored) {
//no-op
}
}
return bindObjectToDomainInstance(entity, object, source, include, exclude, filter);
}
/**
* Binds the given source object to the given target object performing type conversion if necessary
*
* @param entity The PersistentEntity instance
* @param object The object to bind to
* @param source The source object
* @param include The list of properties to include
* @param exclude The list of properties to exclude
* @param filter The prefix to filter by
*
* @see org.grails.datastore.mapping.model.PersistentEntity
*
* @return A BindingResult if there were errors or null if it was successful
*/
@SuppressWarnings("unchecked")
public static BindingResult bindObjectToDomainInstance(PersistentEntity entity, Object object,
Object source, List include, List exclude, String filter) {
BindingResult bindingResult = null;
GrailsApplication grailsApplication = Holders.findApplication();
try {
DataBindingSource bindingSource = createDataBindingSource(grailsApplication, object.getClass(), source);
DataBinder grailsWebDataBinder = getGrailsWebDataBinder(grailsApplication);
grailsWebDataBinder.bind(object, bindingSource, filter, include, exclude);
}
catch (InvalidRequestBodyException e) {
String messageCode = "invalidRequestBody";
Class objectType = object.getClass();
String defaultMessage = "An error occurred parsing the body of the request";
String[] codes = getMessageCodes(messageCode, objectType);
bindingResult = new BeanPropertyBindingResult(object, objectType.getName());
bindingResult.addError(new ObjectError(bindingResult.getObjectName(), codes, null, defaultMessage));
}
catch (Exception e) {
bindingResult = new BeanPropertyBindingResult(object, object.getClass().getName());
bindingResult.addError(new ObjectError(bindingResult.getObjectName(), e.getMessage()));
}
if (entity != null && bindingResult != null) {
BindingResult newResult = new ValidationErrors(object);
for (Object error : bindingResult.getAllErrors()) {
if (error instanceof FieldError) {
FieldError fieldError = (FieldError) error;
boolean isBlank = BLANK.equals(fieldError.getRejectedValue());
if (!isBlank) {
newResult.addError(fieldError);
}
else {
PersistentProperty property = entity.getPropertyByName(fieldError.getField());
if (property != null) {
boolean isOptional = property.isNullable();
if (!isOptional) {
newResult.addError(fieldError);
}
}
else {
newResult.addError(fieldError);
}
}
}
else {
newResult.addError((ObjectError) error);
}
}
bindingResult = newResult;
}
MetaClass mc = GroovySystem.getMetaClassRegistry().getMetaClass(object.getClass());
if (mc.hasProperty(object, "errors") != null && bindingResult != null) {
ValidationErrors errors = new ValidationErrors(object);
errors.addAllErrors(bindingResult);
mc.setProperty(object, "errors", errors);
}
return bindingResult;
}
protected static String[] getMessageCodes(String messageCode, Class objectType) {
String[] codes = { objectType.getName() + "." + messageCode, messageCode };
return codes;
}
public static DataBindingSourceRegistry getDataBindingSourceRegistry(GrailsApplication grailsApplication) {
DataBindingSourceRegistry registry = null;
if (grailsApplication != null) {
ApplicationContext context = grailsApplication.getMainContext();
if (context != null) {
if (context.containsBean(DataBindingSourceRegistry.BEAN_NAME)) {
registry = context.getBean(DataBindingSourceRegistry.BEAN_NAME, DataBindingSourceRegistry.class);
}
}
}
if (registry == null) {
registry = new DefaultDataBindingSourceRegistry();
}
return registry;
}
public static DataBindingSource createDataBindingSource(GrailsApplication grailsApplication, Class bindingTargetType, Object bindingSource) {
DataBindingSourceRegistry registry = getDataBindingSourceRegistry(grailsApplication);
MimeType mimeType = getMimeType(grailsApplication, bindingSource);
return registry.createDataBindingSource(mimeType, bindingTargetType, bindingSource);
}
public static CollectionDataBindingSource createCollectionDataBindingSource(GrailsApplication grailsApplication,
Class bindingTargetType, Object bindingSource) {
DataBindingSourceRegistry registry = getDataBindingSourceRegistry(grailsApplication);
MimeType mimeType = getMimeType(grailsApplication, bindingSource);
return registry.createCollectionDataBindingSource(mimeType, bindingTargetType, bindingSource);
}
public static MimeType getMimeType(GrailsApplication grailsApplication, Object bindingSource) {
MimeTypeResolver mimeTypeResolver = getMimeTypeResolver(grailsApplication);
return resolveMimeType(bindingSource, mimeTypeResolver);
}
public static MimeTypeResolver getMimeTypeResolver(GrailsApplication grailsApplication) {
MimeTypeResolver mimeTypeResolver = null;
if (grailsApplication != null) {
ApplicationContext context = grailsApplication.getMainContext();
if (context != null) {
if (context.containsBean(MimeTypeResolver.BEAN_NAME)) {
mimeTypeResolver = context.getBean(MimeTypeResolver.BEAN_NAME, MimeTypeResolver.class);
}
}
}
return mimeTypeResolver;
}
public static MimeType resolveMimeType(Object bindingSource, MimeTypeResolver mimeTypeResolver) {
return MimeTypeUtils.resolveMimeType(bindingSource, mimeTypeResolver);
}
private static DataBinder getGrailsWebDataBinder(GrailsApplication grailsApplication) {
DataBinder dataBinder = null;
if (grailsApplication != null) {
ApplicationContext mainContext = grailsApplication.getMainContext();
if (mainContext != null && mainContext.containsBean(DATA_BINDER_BEAN_NAME)) {
dataBinder = mainContext.getBean(DATA_BINDER_BEAN_NAME, DataBinder.class);
}
}
if (dataBinder == null) {
// this should really never happen in the running app as the binder
// should always be found in the context
dataBinder = new GrailsWebDataBinder(grailsApplication);
}
return dataBinder;
}
@SuppressWarnings("unchecked")
public static Map convertPotentialGStrings(Map