001// Copyright 2006-2013 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5; 016 017import org.apache.tapestry5.ioc.internal.util.CollectionFactory; 018import org.apache.tapestry5.ioc.internal.util.InternalUtils; 019 020import java.io.Serializable; 021import java.util.Collections; 022import java.util.List; 023import java.util.Map; 024 025/** 026 * Standard implementation of {@link ValidationTracker}. Works pretty hard to ensure a minimum 027 * amount of data is stored 028 * in the HttpSession. 029 */ 030public final class ValidationTrackerImpl extends BaseOptimizedSessionPersistedObject implements ValidationTracker, Serializable 031{ 032 private static final long serialVersionUID = -8029192726659275677L; 033 034 private static class FieldTracker implements Serializable 035 { 036 private static final long serialVersionUID = -3653306147088451811L; 037 038 private final String fieldName; 039 040 private String input; 041 042 private String errorMessage; 043 044 FieldTracker(String fieldName) 045 { 046 this.fieldName = fieldName; 047 } 048 } 049 050 private List<String> extraErrors; 051 052 private List<FieldTracker> fieldTrackers; 053 054 // Rebuilt on-demand 055 056 private transient Map<String, FieldTracker> fieldToTracker; 057 058 private void refreshFieldToTracker() 059 { 060 if (fieldToTracker != null) 061 return; 062 063 if (fieldTrackers == null) 064 return; 065 066 fieldToTracker = CollectionFactory.newMap(); 067 068 for (FieldTracker ft : fieldTrackers) 069 fieldToTracker.put(ft.fieldName, ft); 070 } 071 072 private FieldTracker get(Field field) 073 { 074 String key = field.getControlName(); 075 076 refreshFieldToTracker(); 077 078 FieldTracker result = InternalUtils.get(fieldToTracker, key); 079 080 if (result == null) 081 result = new FieldTracker(key); 082 083 return result; 084 } 085 086 private void store(FieldTracker fieldTracker) 087 { 088 if (fieldTrackers == null) 089 fieldTrackers = CollectionFactory.newList(); 090 091 refreshFieldToTracker(); 092 093 String key = fieldTracker.fieldName; 094 095 if (!fieldToTracker.containsKey(key)) 096 { 097 fieldTrackers.add(fieldTracker); 098 fieldToTracker.put(key, fieldTracker); 099 } 100 101 markDirty(); 102 } 103 104 public void clear() 105 { 106 extraErrors = null; 107 fieldTrackers = null; 108 fieldToTracker = null; 109 110 markDirty(); 111 } 112 113 public String getError(Field field) 114 { 115 return get(field).errorMessage; 116 } 117 118 public List<String> getErrors() 119 { 120 List<String> result = CollectionFactory.newList(); 121 122 if (extraErrors != null) 123 result.addAll(extraErrors); 124 125 if (fieldTrackers != null) 126 { 127 for (FieldTracker ft : fieldTrackers) 128 { 129 String errorMessage = ft.errorMessage; 130 131 if (errorMessage != null) 132 result.add(errorMessage); 133 } 134 } 135 136 return result; 137 } 138 139 public List<String> getUnassociatedErrors() 140 { 141 if (extraErrors == null) 142 { 143 return Collections.emptyList(); 144 } 145 146 return Collections.unmodifiableList(extraErrors); 147 } 148 149 public boolean getHasErrors() 150 { 151 return !getErrors().isEmpty(); 152 } 153 154 public String getInput(Field field) 155 { 156 return get(field).input; 157 } 158 159 public boolean inError(Field field) 160 { 161 return InternalUtils.isNonBlank(get(field).errorMessage); 162 } 163 164 public void recordError(Field field, String errorMessage) 165 { 166 FieldTracker ft = get(field); 167 168 ft.errorMessage = errorMessage; 169 170 store(ft); 171 } 172 173 public void recordError(String errorMessage) 174 { 175 if (extraErrors == null) 176 extraErrors = CollectionFactory.newList(); 177 178 extraErrors.add(errorMessage); 179 180 markDirty(); 181 } 182 183 public void recordInput(Field field, String input) 184 { 185 FieldTracker ft = get(field); 186 187 ft.input = input; 188 189 store(ft); 190 } 191}