001/* 002 * Copyright 2006-2007 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.batch.sample.domain.trade; 018 019import org.springframework.batch.core.StepExecution; 020import org.springframework.batch.core.listener.StepExecutionListenerSupport; 021import org.springframework.batch.item.file.transform.FieldSet; 022import org.springframework.batch.item.file.transform.LineTokenizer; 023 024/** 025 * Composite {@link LineTokenizer} that delegates the tokenization of a line to one of two potential 026 * tokenizers. The file format in this case uses one character, either F, A, U, or D to indicate 027 * whether or not the line is an a footer record, or a customer add, update, or delete, and 028 * will delegate accordingly. 029 * 030 * @author Lucas Ward 031 * @since 2.0 032 */ 033public class CompositeCustomerUpdateLineTokenizer extends StepExecutionListenerSupport implements LineTokenizer { 034 035 private LineTokenizer customerTokenizer; 036 private LineTokenizer footerTokenizer; 037 private StepExecution stepExecution; 038 039 /* (non-Javadoc) 040 * @see org.springframework.batch.item.file.transform.LineTokenizer#tokenize(java.lang.String) 041 */ 042 @Override 043 public FieldSet tokenize(String line) { 044 045 if(line.charAt(0) == 'F'){ 046 //line starts with F, so the footer tokenizer should tokenize it. 047 FieldSet fs = footerTokenizer.tokenize(line); 048 long customerUpdateTotal = stepExecution.getReadCount(); 049 long fileUpdateTotal = fs.readLong(1); 050 if(customerUpdateTotal != fileUpdateTotal){ 051 throw new IllegalStateException("The total number of customer updates in the file footer does not match the " + 052 "number entered File footer total: [" + fileUpdateTotal + "] Total encountered during processing: [" + 053 customerUpdateTotal + "]"); 054 } 055 else{ 056 //return null, because the footer indicates an end of processing. 057 return null; 058 } 059 } 060 else if(line.charAt(0) == 'A' || line.charAt(0) == 'U' || line.charAt(0) == 'D'){ 061 //line starts with A,U, or D, so it must be a customer operation. 062 return customerTokenizer.tokenize(line); 063 } 064 else{ 065 //If the line doesn't start with any of the characters above, it must obviously be invalid. 066 throw new IllegalArgumentException("Invalid line encountered for tokenizing: " + line); 067 } 068 } 069 070 @Override 071 public void beforeStep(StepExecution stepExecution) { 072 this.stepExecution = stepExecution; 073 } 074 075 /** 076 * Set the {@link LineTokenizer} that will be used to tokenize any lines that begin with 077 * A, U, or D, and are thus a customer operation. 078 * 079 * @param customerTokenizer tokenizer to delegate to for customer operation records 080 */ 081 public void setCustomerTokenizer(LineTokenizer customerTokenizer) { 082 this.customerTokenizer = customerTokenizer; 083 } 084 085 /** 086 * Set the {@link LineTokenizer} that will be used to tokenize any lines that being with 087 * F and is thus a footer record. 088 * 089 * @param footerTokenizer tokenizer to delegate to for footer records 090 */ 091 public void setFooterTokenizer(LineTokenizer footerTokenizer) { 092 this.footerTokenizer = footerTokenizer; 093 } 094}