All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.foreach.across.modules.bootstrapui.utils.ControlNamePrefixAdjuster Maven / Gradle / Ivy

/*
 * Copyright 2014 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
 *
 * http://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 com.foreach.across.modules.bootstrapui.utils;

import com.foreach.across.modules.bootstrapui.elements.FormControlElement;
import com.foreach.across.modules.bootstrapui.elements.FormInputElement;
import com.foreach.across.modules.web.ui.ViewElement;
import com.foreach.across.modules.web.ui.ViewElementBuilderContext;
import com.foreach.across.modules.web.ui.ViewElementPostProcessor;
import com.foreach.across.modules.web.ui.elements.ContainerViewElement;
import lombok.NonNull;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.val;
import org.apache.commons.lang3.StringUtils;

import java.util.IdentityHashMap;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * Helper class for updating the control name of an {@link com.foreach.across.modules.bootstrapui.elements.FormInputElement}.
 * Will update the element control name and (depending on the value of {@link #recurse(boolean)}, will also update all
 * child controls if the element is a container.
 * 

* A new instance is pre-configured for bean style element control names: dotted separators will be added and any control * name starting with an underscore is modified *after* the underscore. *

* When processing the container members, this prefixer ensures that controls are only modified a single time, * and ensures correct handling of {@link com.foreach.across.modules.bootstrapui.elements.FormControlElement.Proxy} controls. *

* This is an implementation of both {@link Consumer} and {@link ViewElementPostProcessor} so it can easily * be passed around and used in different contexts. * * @author Arne Vandamme * @since 2.1.0 */ @Accessors(fluent = true, chain = true) public class ControlNamePrefixAdjuster implements Consumer, ViewElementPostProcessor { /** * Prefix value that should be replaced. When specified, only controls matching the prefixToAdd will be modified. * If not specified, all control names will be prefixed. */ @Setter private String prefixToReplace; /** * The new prefixToAdd that should be set on the control name. */ @NonNull @Setter private String prefixToAdd; /** * Set to {@code false} if you want to apply the new prefixToAdd as is. * When {@code true} (default), a dot will be inserted between the new prefixToAdd and * the remaining segment if the remaning segment does not start with a dot or * an indexer related character ({,[ or (). */ @Setter private boolean insertDotSeparator = true; /** * Set to {@code false} if you only want to apply the name modification to the initial element, * and not recurse through the child elements if the element is a container. *

* When false and the initial element is not a {@link FormInputElement}, nothing will happen. */ @Setter private boolean recurse = true; /** * Set to {@code false} if you want to treat any control name starting with an underscore as an * exact control name. If not, a starting _ will be ignored for the control name predicate * and prefixing will be done after the _. A control starting with underscore is usually a special * element for Spring data-binding. */ @Setter private boolean ignoreUnderscore = true; /** * Additional predicate that the candidates should match before they are modified. * Recursing through members of a candidate will happen regardless of the predicate. */ @Setter private Predicate elementPredicate; /** * An additional custom predicate that the (unmodified) control name should match * before it is modified. */ @Setter private Predicate controlNamePredicate; @Override public void postProcess( ViewElementBuilderContext builderContext, ViewElement element ) { accept( element ); } @Override public void accept( ViewElement element ) { if ( prefixToAdd == null || element == null ) { return; } if ( element instanceof FormInputElement ) { replaceControlNamePrefix( (FormInputElement) element ); } if ( recurse && element instanceof ContainerViewElement ) { val processed = new IdentityHashMap(); ( (ContainerViewElement) element ).findAll( FormInputElement.class, i -> !FormControlElement.Proxy.class.isInstance( i ) ) .forEach( control -> { if ( !processed.containsKey( control ) ) { replaceControlNamePrefix( control ); processed.put( control, null ); } } ); } } private void replaceControlNamePrefix( FormInputElement control ) { if ( elementPredicate != null && !elementPredicate.test( control ) ) { return; } String currentControlName = control.getControlName(); if ( currentControlName != null && !currentControlName.isEmpty() ) { if ( controlNamePredicate != null && !controlNamePredicate.test( removeUnderscore( currentControlName ) ) ) { return; } boolean underscored = shouldSkipUnderscore( currentControlName ); if ( underscored ) { currentControlName = currentControlName.substring( 1 ); } String newControlName = null; if ( StringUtils.isEmpty( prefixToReplace ) ) { newControlName = addPrefix( currentControlName ); } else if ( currentControlName.startsWith( prefixToReplace ) ) { newControlName = addPrefix( StringUtils.removeStart( currentControlName, prefixToReplace ) ); } if ( newControlName != null && !newControlName.equals( currentControlName ) ) { if ( underscored ) { control.setControlName( '_' + newControlName ); } else { control.setControlName( newControlName ); } } } } private String removeUnderscore( String controlName ) { return ignoreUnderscore && controlName.charAt( 0 ) == '_' ? controlName.substring( 1 ) : controlName; } private boolean shouldSkipUnderscore( String controlName ) { return ignoreUnderscore && controlName.charAt( 0 ) == '_' && ( StringUtils.isEmpty( prefixToReplace ) || prefixToReplace.charAt( 0 ) != '_' ); } private String addPrefix( String controlName ) { if ( StringUtils.isEmpty( prefixToAdd ) ) { return controlName; } if ( insertDotSeparator ) { if ( prefixToAdd.charAt( prefixToAdd.length() - 1 ) != '.' && controlName.charAt( 0 ) != '[' && controlName.charAt( 0 ) != '(' && controlName.charAt( 0 ) != '{' && controlName.charAt( 0 ) != '.' ) { return prefixToAdd + "." + controlName; } } return prefixToAdd + controlName; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy