001/* 002 * jDTAUS Banking RI DTAUS 003 * Copyright (C) 2005 Christian Schulte 004 * <cs@schulte.it> 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2.1 of the License, or any later version. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 019 * 020 */ 021package org.jdtaus.banking.dtaus.ri.zka; 022 023import java.io.IOException; 024import java.util.Arrays; 025import java.util.Currency; 026import java.util.Date; 027import java.util.HashMap; 028import java.util.Iterator; 029import java.util.LinkedList; 030import java.util.List; 031import java.util.Map; 032import org.jdtaus.banking.dtaus.Header; 033import org.jdtaus.banking.dtaus.LogicalFile; 034import org.jdtaus.banking.dtaus.LogicalFileType; 035import org.jdtaus.banking.dtaus.spi.CurrencyCounter; 036import org.jdtaus.banking.dtaus.spi.HeaderValidator; 037import org.jdtaus.banking.dtaus.spi.IllegalHeaderException; 038import org.jdtaus.banking.messages.CurrencyConstraintMessage; 039import org.jdtaus.banking.messages.IllegalCurrencyMessage; 040import org.jdtaus.banking.messages.IllegalDateMessage; 041import org.jdtaus.banking.messages.IllegalScheduleMessage; 042import org.jdtaus.banking.messages.TextschluesselConstraintMessage; 043import org.jdtaus.banking.spi.CurrencyMapper; 044import org.jdtaus.banking.spi.UnsupportedCurrencyException; 045import org.jdtaus.core.container.ContainerFactory; 046import org.jdtaus.core.container.PropertyException; 047import org.jdtaus.core.logging.spi.Logger; 048import org.jdtaus.core.messages.MandatoryPropertyMessage; 049import org.jdtaus.core.text.Message; 050 051/** 052 * jDTAUS Banking SPI {@code HeaderValidator} implementation. 053 * 054 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 055 * @version $JDTAUS: DefaultHeaderValidator.java 8661 2012-09-27 11:29:58Z schulte $ 056 */ 057public final class DefaultHeaderValidator implements HeaderValidator 058{ 059 060 /** Value of property {@code maxScheduleDays} in milliseconds. */ 061 private long maxScheduleDaysMillis = Long.MIN_VALUE; 062 063 public IllegalHeaderException assertValidHeader( final Header header, IllegalHeaderException result ) 064 { 065 if ( header == null ) 066 { 067 throw new NullPointerException( "header" ); 068 } 069 070 this.assertValidProperties(); 071 final List messages = new LinkedList(); 072 final Map properties = new HashMap( 20 ); 073 074 if ( header.getCreateDate() == null ) 075 { 076 properties.put( Header.PROP_CREATEDATE, new MandatoryPropertyMessage() ); 077 } 078 else if ( !this.checkDate( header.getCreateDate() ) ) 079 { 080 properties.put( Header.PROP_CREATEDATE, new IllegalDateMessage( 081 header.getCreateDate(), new Date( this.getMinDateMillis() ), new Date( this.getMaxDateMillis() ) ) ); 082 083 } 084 085 if ( header.getExecutionDate() != null && !this.checkDate( header.getExecutionDate() ) ) 086 { 087 properties.put( Header.PROP_EXECUTIONDATE, new IllegalDateMessage( 088 header.getExecutionDate(), new Date( this.getMinDateMillis() ), new Date( this.getMaxDateMillis() ) ) ); 089 090 } 091 if ( header.getType() == null ) 092 { 093 properties.put( Header.PROP_TYPE, new MandatoryPropertyMessage() ); 094 } 095 else if ( header.getType().isSendByBank() && header.getBankData() == null ) 096 { 097 properties.put( Header.PROP_BANKDATA, new MandatoryPropertyMessage() ); 098 } 099 100 if ( header.getCustomer() == null || header.getCustomer().isEmpty() ) 101 { 102 properties.put( Header.PROP_CUSTOMER, new MandatoryPropertyMessage() ); 103 } 104 if ( header.getBank() == null ) 105 { 106 properties.put( Header.PROP_BANK, new MandatoryPropertyMessage() ); 107 } 108 if ( header.getAccount() == null ) 109 { 110 properties.put( Header.PROP_ACCOUNT, new MandatoryPropertyMessage() ); 111 } 112 if ( header.getCurrency() == null ) 113 { 114 properties.put( Header.PROP_CURRENCY, new MandatoryPropertyMessage() ); 115 } 116 117 if ( header.getCreateDate() != null ) 118 { 119 if ( header.getCurrency() != null ) 120 { 121 try 122 { 123 this.getCurrencyMapper().getDtausCode( header.getCurrency(), header.getCreateDate() ); 124 } 125 catch ( UnsupportedCurrencyException ex ) 126 { 127 if ( this.getLogger().isDebugEnabled() ) 128 { 129 this.getLogger().debug( ex.toString() ); 130 } 131 132 properties.put( Header.PROP_CURRENCY, new IllegalCurrencyMessage( 133 header.getCurrency().getCurrencyCode(), header.getCreateDate() ) ); 134 135 } 136 } 137 138 if ( !this.checkSchedule( header.getCreateDate(), header.getExecutionDate() ) ) 139 { 140 messages.add( new IllegalScheduleMessage( 141 header.getCreateDate(), header.getExecutionDate(), this.getMaxScheduleDays() ) ); 142 143 } 144 } 145 146 if ( properties.size() > 0 || messages.size() > 0 ) 147 { 148 if ( result == null ) 149 { 150 result = new IllegalHeaderException(); 151 } 152 153 for ( Iterator it = properties.entrySet().iterator(); it.hasNext(); ) 154 { 155 final Map.Entry entry = (Map.Entry) it.next(); 156 result.addMessage( (String) entry.getKey(), (Message) entry.getValue() ); 157 } 158 for ( Iterator it = messages.iterator(); it.hasNext(); ) 159 { 160 result.addMessage( (Message) it.next() ); 161 } 162 } 163 164 return result; 165 } 166 167 public IllegalHeaderException assertValidHeader( 168 final LogicalFile lFile, final Header header, final CurrencyCounter counter, IllegalHeaderException result ) 169 throws IOException 170 { 171 if ( lFile == null ) 172 { 173 throw new NullPointerException( "lFile" ); 174 } 175 if ( header == null ) 176 { 177 throw new NullPointerException( "header" ); 178 } 179 if ( counter == null ) 180 { 181 throw new NullPointerException( "counter" ); 182 } 183 184 this.assertValidProperties(); 185 186 IllegalHeaderException e = this.assertValidHeader( header, result ); 187 final LogicalFileType oldLabel = lFile.getHeader().getType(); 188 final LogicalFileType newLabel = header.getType(); 189 190 if ( newLabel != null ) 191 { 192 if ( oldLabel != null && lFile.getChecksum().getTransactionCount() > 0 193 && ( ( oldLabel.isDebitAllowed() && !newLabel.isDebitAllowed() ) 194 || ( oldLabel.isRemittanceAllowed() && !newLabel.isRemittanceAllowed() ) ) ) 195 { 196 if ( e == null ) 197 { 198 e = new IllegalHeaderException(); 199 } 200 201 e.addMessage( Header.PROP_TYPE, new TextschluesselConstraintMessage( 202 newLabel, lFile.getTransaction( 0 ).getType() ) ); 203 204 } 205 } 206 207 if ( header.getCreateDate() != null ) 208 { 209 final Currency[] oldCurrencies = 210 this.getCurrencyMapper().getDtausCurrencies( lFile.getHeader().getCreateDate() ); 211 212 final Currency[] newCurrencies = this.getCurrencyMapper().getDtausCurrencies( header.getCreateDate() ); 213 214 if ( !Arrays.equals( oldCurrencies, newCurrencies ) ) 215 { 216 final Currency[] current = counter.getCurrencies(); 217 for ( int i = current.length - 1; i >= 0; i-- ) 218 { 219 boolean currencyKept = false; 220 221 for ( int j = newCurrencies.length - 1; j >= 0; j-- ) 222 { 223 if ( newCurrencies[j].getCurrencyCode().equals( current[i].getCurrencyCode() ) ) 224 { 225 currencyKept = true; 226 break; 227 } 228 } 229 230 if ( !currencyKept ) 231 { 232 if ( e == null ) 233 { 234 e = new IllegalHeaderException(); 235 } 236 237 e.addMessage( new CurrencyConstraintMessage( 238 current[i].getCurrencyCode(), header.getCreateDate() ) ); 239 240 } 241 } 242 } 243 } 244 245 return e; 246 } 247 248 /** 249 * Gets the value of property {@code maxScheduleDays} in milliseconds. 250 * 251 * @return the value of property {@code maxScheduleDays} in milliseconds. 252 */ 253 private long getMaxScheduleDaysMillis() 254 { 255 if ( this.maxScheduleDaysMillis < 0L ) 256 { 257 this.maxScheduleDaysMillis = this.getMaxScheduleDays() * 86400000L; 258 } 259 260 return this.maxScheduleDaysMillis; 261 } 262 263 /** 264 * Checks configured properties. 265 * 266 * @throws PropertyException for illegal property values. 267 */ 268 private void assertValidProperties() 269 { 270 if ( this.getMinDateMillis() < 0L ) 271 { 272 throw new PropertyException( "minDateMillis", Long.toString( this.getMinDateMillis() ) ); 273 } 274 if ( this.getMaxDateMillis() < 0L || this.getMinDateMillis() > this.getMaxDateMillis() ) 275 { 276 throw new PropertyException( "maxDateMillis", Long.toString( this.getMaxDateMillis() ) ); 277 } 278 if ( this.getMaxScheduleDays() < 0 ) 279 { 280 throw new PropertyException( "maxScheduleDays", Integer.toString( this.getMaxScheduleDays() ) ); 281 } 282 } 283 284 /** 285 * Checks a given date. 286 * 287 * @param date instance to check. 288 * 289 * @return {@code true} if {@code date} is legal; {@code false} if not. 290 */ 291 private boolean checkDate( final Date date ) 292 { 293 boolean valid = false; 294 295 if ( date != null ) 296 { 297 final long millis = date.getTime(); 298 valid = millis >= this.getMinDateMillis() && millis <= this.getMaxDateMillis(); 299 } 300 301 return valid; 302 } 303 304 /** 305 * Checks a given schedule. 306 * 307 * @param createDate file creation date to check. 308 * @param executionDate file execution date to check. 309 * 310 * @return {@code true} if {@code createDate} and {@code executionDate} is a legal combination; {@code false} if 311 * not. 312 */ 313 private boolean checkSchedule( final Date createDate, final Date executionDate ) 314 { 315 boolean valid = createDate != null; 316 317 if ( valid ) 318 { 319 final long createMillis = createDate.getTime(); 320 if ( executionDate != null ) 321 { 322 final long executionMillis = executionDate.getTime(); 323 valid = executionMillis >= createMillis 324 && executionMillis <= createMillis + this.getMaxScheduleDaysMillis(); 325 326 } 327 } 328 329 return valid; 330 } 331 332 //--Constructors------------------------------------------------------------ 333 334// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausConstructors 335 // This section is managed by jdtaus-container-mojo. 336 337 /** Standard implementation constructor <code>org.jdtaus.banking.dtaus.ri.zka.DefaultHeaderValidator</code>. */ 338 public DefaultHeaderValidator() 339 { 340 super(); 341 } 342 343// </editor-fold>//GEN-END:jdtausConstructors 344 345 //------------------------------------------------------------Constructors-- 346 //--Dependencies------------------------------------------------------------ 347 348// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausDependencies 349 // This section is managed by jdtaus-container-mojo. 350 351 /** 352 * Gets the configured <code>CurrencyMapper</code> implementation. 353 * 354 * @return The configured <code>CurrencyMapper</code> implementation. 355 */ 356 private CurrencyMapper getCurrencyMapper() 357 { 358 return (CurrencyMapper) ContainerFactory.getContainer(). 359 getDependency( this, "CurrencyMapper" ); 360 361 } 362 363 /** 364 * Gets the configured <code>Logger</code> implementation. 365 * 366 * @return The configured <code>Logger</code> implementation. 367 */ 368 private Logger getLogger() 369 { 370 return (Logger) ContainerFactory.getContainer(). 371 getDependency( this, "Logger" ); 372 373 } 374 375// </editor-fold>//GEN-END:jdtausDependencies 376 377 //------------------------------------------------------------Dependencies-- 378 //--Properties-------------------------------------------------------------- 379 380// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties 381 // This section is managed by jdtaus-container-mojo. 382 383 /** 384 * Gets the value of property <code>minDateMillis</code>. 385 * 386 * @return Timestamp any date is not allowed to precede. 387 */ 388 private long getMinDateMillis() 389 { 390 return ( (java.lang.Long) ContainerFactory.getContainer(). 391 getProperty( this, "minDateMillis" ) ).longValue(); 392 393 } 394 395 /** 396 * Gets the value of property <code>maxScheduleDays</code>. 397 * 398 * @return Maximum number of days allowed for a schedule. 399 */ 400 private int getMaxScheduleDays() 401 { 402 return ( (java.lang.Integer) ContainerFactory.getContainer(). 403 getProperty( this, "maxScheduleDays" ) ).intValue(); 404 405 } 406 407 /** 408 * Gets the value of property <code>maxDateMillis</code>. 409 * 410 * @return Timestamp any date is not allowed to follow. 411 */ 412 private long getMaxDateMillis() 413 { 414 return ( (java.lang.Long) ContainerFactory.getContainer(). 415 getProperty( this, "maxDateMillis" ) ).longValue(); 416 417 } 418 419// </editor-fold>//GEN-END:jdtausProperties 420 421 //--------------------------------------------------------------Properties-- 422}