001package org.gwtbootstrap3.client.ui.form.validator; 002 003/* 004 * #%L 005 * GwtBootstrap3 006 * %% 007 * Copyright (C) 2015 GwtBootstrap3 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import java.util.LinkedHashMap; 024import java.util.Map; 025 026import org.gwtbootstrap3.client.ui.form.validator.ValidationChangedEvent.ValidationChangedHandler; 027 028import com.google.gwt.editor.client.Editor; 029import com.google.gwt.event.shared.GwtEvent; 030import com.google.gwt.user.client.ui.Widget; 031import com.google.web.bindery.event.shared.EventBus; 032import com.google.web.bindery.event.shared.HandlerRegistration; 033import com.google.web.bindery.event.shared.SimpleEventBus; 034 035/** 036 * Useful for validating a group of fields that implement the {@link HasValidators} interface. 037 * 038 * @author Steven Jardine 039 */ 040public class GroupValidator implements ValidationChangedEvent.HasValidationChangedHandlers { 041 042 private final SimpleEventBus eventBus; 043 044 private boolean fireEvents = false; 045 046 private final Map<HasValidators<?>, Boolean> fields; 047 048 private final Map<HasValidators<?>, HandlerRegistration> registrations; 049 050 private Boolean groupValid = null; 051 052 /** 053 * Constructor. 054 */ 055 public GroupValidator() { 056 fields = new LinkedHashMap<HasValidators<?>, Boolean>(); 057 registrations = new LinkedHashMap<HasValidators<?>, HandlerRegistration>(); 058 eventBus = new SimpleEventBus(); 059 } 060 061 /** 062 * Adds a field to the group. 063 * 064 * @param <T> the generic type 065 * @param field the field 066 */ 067 public <T extends Widget & HasValidators<?>> void add(final T field) { 068 fields.put(field, field.validate(false)); 069 if (field.isAttached()) { 070 updateStateAndNotify(); 071 } 072 registrations.put(field, field.addValidationChangedHandler(new ValidationChangedHandler() { 073 @Override 074 public void onValidationChanged(ValidationChangedEvent event) { 075 fields.put(field, event.isValid()); 076 if (fireEvents) { 077 updateStateAndNotify(); 078 } 079 } 080 })); 081 } 082 083 /** {@inheritDoc} */ 084 @Override 085 public HandlerRegistration addValidationChangedHandler(ValidationChangedHandler handler) { 086 return eventBus.addHandler(ValidationChangedEvent.getType(), handler); 087 } 088 089 /** {@inheritDoc} */ 090 @Override 091 public void fireEvent(GwtEvent<?> event) { 092 eventBus.fireEvent(event); 093 } 094 095 /** 096 * Removes a field from the validation group. 097 * 098 * @param <T> the generic type 099 * @param field the field 100 * @return true, if successful 101 */ 102 public <T extends Widget & HasValidators<?>> boolean remove(final T field) { 103 fields.remove(field); 104 HandlerRegistration reg = registrations.remove(field); 105 if (reg != null) { 106 reg.removeHandler(); 107 return true; 108 } 109 return false; 110 } 111 112 /** 113 * Update the state of the validator and notify via {@link EventBus} any changed handlers. 114 */ 115 private void updateStateAndNotify() { 116 Boolean oldGroupValid = groupValid; 117 groupValid = true; 118 for (Boolean valid : fields.values()) { 119 groupValid &= valid; 120 } 121 if (groupValid != oldGroupValid) { 122 eventBus.fireEvent(new ValidationChangedEvent(groupValid)); 123 } 124 } 125 126 /** 127 * Validate the group. This calls {@link Validator #validate(Editor, Object)} on each field in the group. 128 * 129 * @return true, if successful 130 */ 131 public boolean validate() { 132 return validate(true); 133 } 134 135 /** 136 * Validate the group. This calls {@link Validator #validate(Editor, Object)} on each field in the group. 137 * 138 * @param show do we want to show the user the result of the validate via ui marks? 139 * @return true, if successful 140 */ 141 public boolean validate(boolean show) { 142 fireEvents = false; 143 for (HasValidators<?> field : fields.keySet()) { 144 field.validate(show); 145 } 146 fireEvents = true; 147 updateStateAndNotify(); 148 return groupValid; 149 } 150 151}