001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.gwt.client.validation; 029 030import org.opencms.gwt.client.CmsCoreProvider; 031import org.opencms.gwt.client.rpc.CmsRpcAction; 032import org.opencms.gwt.client.ui.input.I_CmsFormField; 033import org.opencms.gwt.shared.CmsValidationQuery; 034import org.opencms.gwt.shared.CmsValidationResult; 035 036import java.util.ArrayList; 037import java.util.Collection; 038import java.util.HashMap; 039import java.util.HashSet; 040import java.util.Map; 041import java.util.Set; 042 043/** 044 * This class is responsible for coordinating the synchronous and asynchronous validation for 045 * a set of form fields.<p> 046 * 047 * @since 8.0.0 048 */ 049public class CmsValidationController implements I_CmsValidationController { 050 051 /** A counter used to give newly created validation controllers unique ids. */ 052 private static int counter; 053 054 /** The list of form fields which should be validated. */ 055 protected Collection<I_CmsFormField> m_fields; 056 057 /** A map containing all validation queries which should be executed asynchronously. */ 058 protected Map<String, CmsValidationQuery> m_validationQueries = new HashMap<String, CmsValidationQuery>(); 059 060 /** The form validator class name. */ 061 private String m_formValidatorClass; 062 063 /** The form validator configuration. */ 064 private String m_formValidatorConfig; 065 066 /** The validation handler which will receive the results of the validation. */ 067 private I_CmsValidationHandler m_handler; 068 069 /** The id of the validation controller. */ 070 private int m_id; 071 072 /** A flag to make sure that the validation controller is not used twice. */ 073 private boolean m_isNew = true; 074 075 /** The set of fields which have been validated. */ 076 private Set<String> m_validatedFields = new HashSet<String>(); 077 078 /** A flag indicating whether the validation has been successful. */ 079 private boolean m_validationOk; 080 081 /** 082 * Creates a new validation controller for a list of form fields.<p> 083 * 084 * @param fields the fields which should be validated 085 * @param handler the validation handler 086 */ 087 public CmsValidationController(Collection<I_CmsFormField> fields, I_CmsValidationHandler handler) { 088 089 m_fields = fields; 090 m_handler = handler; 091 m_id = counter++; 092 } 093 094 /** 095 * Creates a new validation controller for a single form field.<p> 096 * 097 * @param field the form field 098 * @param handler the validation handler 099 */ 100 public CmsValidationController(I_CmsFormField field, I_CmsValidationHandler handler) { 101 102 m_fields = new ArrayList<I_CmsFormField>(); 103 m_fields.add(field); 104 m_handler = handler; 105 m_id = counter++; 106 } 107 108 /** 109 * Returns the id of this validation controller.<p> 110 * 111 * @return an id 112 */ 113 public int getId() { 114 115 return m_id; 116 } 117 118 /** 119 * Returns the set of fields which have been validated. 120 * 121 * @return the set of validated fields 122 */ 123 public Set<String> getValidatedFields() { 124 125 return m_validatedFields; 126 } 127 128 /** 129 * @see org.opencms.gwt.client.validation.I_CmsValidationController#provideValidationResult(java.lang.String, org.opencms.gwt.shared.CmsValidationResult) 130 */ 131 public void provideValidationResult(String field, CmsValidationResult result) { 132 133 if (result.getErrorMessage() != null) { 134 m_validationOk = false; 135 } 136 137 m_handler.onValidationResult(field, result); 138 } 139 140 /** 141 * Sets the form validator class name for this validation controller.<p> 142 * 143 * @param formValidatorClass the class name of the form validator 144 */ 145 public void setFormValidator(String formValidatorClass) { 146 147 m_formValidatorClass = formValidatorClass; 148 } 149 150 /** 151 * Sets the form validator configuration string.<p> 152 * a 153 * @param formValidatorConfig the form validator configuration string 154 */ 155 public void setFormValidatorConfig(String formValidatorConfig) { 156 157 m_formValidatorConfig = formValidatorConfig; 158 159 } 160 161 /** 162 * Starts the validation.<p> 163 * 164 * This uses the {@link CmsValidationScheduler}, so the validation only starts after the currently running or scheduled 165 * validations have finished running.<p> 166 */ 167 public void startValidation() { 168 169 CmsValidationScheduler.get().schedule(this); 170 } 171 172 /** 173 * @see org.opencms.gwt.client.validation.I_CmsValidationController#validateAsync(java.lang.String, java.lang.String, java.lang.String, java.lang.String) 174 */ 175 public void validateAsync(String field, String value, String validator, String config) { 176 177 m_validationQueries.put(field, new CmsValidationQuery(validator, value, config)); 178 } 179 180 /** 181 * Starts the validation.<p> 182 */ 183 protected void internalStartValidation() { 184 185 assert m_isNew : "A validation controller can only be used once!"; 186 m_isNew = false; 187 188 m_validationOk = true; 189 for (I_CmsFormField field : m_fields) { 190 I_CmsFormField.ValidationStatus status = field.getValidationStatus(); 191 if (status == I_CmsFormField.ValidationStatus.unknown) { 192 I_CmsValidator validator = field.getValidator(); 193 validator.validate(field, this); 194 m_validatedFields.add(field.getId()); 195 } else if (status == I_CmsFormField.ValidationStatus.invalid) { 196 m_validationOk = false; 197 } 198 } 199 if (m_validationQueries.isEmpty()) { 200 m_handler.onValidationFinished(m_validationOk); 201 CmsValidationScheduler.get().executeNext(); 202 } else { 203 if (m_formValidatorClass == null) { 204 startAsyncValidation(); 205 } else { 206 startAsyncValidation(m_formValidatorClass, m_formValidatorConfig); 207 } 208 } 209 } 210 211 /** 212 * Internal method which is executed when the results of the asynchronous validation are received from the server.<p> 213 * 214 * @param results the validation results 215 */ 216 protected void onReceiveValidationResults(Map<String, CmsValidationResult> results) { 217 218 try { 219 for (Map.Entry<String, CmsValidationResult> resultEntry : results.entrySet()) { 220 String fieldName = resultEntry.getKey(); 221 CmsValidationResult result = resultEntry.getValue(); 222 provideValidationResult(fieldName, result); 223 } 224 m_handler.onValidationFinished(m_validationOk); 225 } finally { 226 CmsValidationScheduler.get().executeNext(); 227 } 228 } 229 230 /** 231 * Starts the asynchronous validation.<p> 232 */ 233 private void startAsyncValidation() { 234 235 CmsRpcAction<Map<String, CmsValidationResult>> action = new CmsRpcAction<Map<String, CmsValidationResult>>() { 236 237 /** 238 * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute() 239 */ 240 @Override 241 public void execute() { 242 243 start(0, false); 244 CmsCoreProvider.getService().validate(m_validationQueries, this); 245 } 246 247 @Override 248 public void onFailure(Throwable e) { 249 250 super.onFailure(e); 251 CmsValidationScheduler.get().executeNext(); 252 253 } 254 255 /** 256 * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object) 257 */ 258 @Override 259 protected void onResponse(Map<String, CmsValidationResult> result) { 260 261 stop(false); 262 onReceiveValidationResults(result); 263 } 264 265 }; 266 action.execute(); 267 } 268 269 /** 270 * Starts the asynchronous validation.<p> 271 * 272 * @param formValidationHandler the form validator class to use 273 * @param config the form validator configuration string 274 */ 275 private void startAsyncValidation(final String formValidationHandler, final String config) { 276 277 CmsRpcAction<Map<String, CmsValidationResult>> action = new CmsRpcAction<Map<String, CmsValidationResult>>() { 278 279 /** 280 * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute() 281 */ 282 @Override 283 public void execute() { 284 285 final Map<String, String> values = new HashMap<String, String>(); 286 for (I_CmsFormField field : m_fields) { 287 values.put(field.getId(), field.getModelValue()); 288 } 289 start(0, false); 290 CmsCoreProvider.getService().validate(formValidationHandler, m_validationQueries, values, config, this); 291 } 292 293 /** 294 * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object) 295 */ 296 @Override 297 protected void onResponse(Map<String, CmsValidationResult> result) { 298 299 stop(false); 300 onReceiveValidationResults(result); 301 } 302 303 }; 304 action.execute(); 305 } 306}