EMMA Coverage Report (generated Thu May 22 12:08:10 CDT 2014)
[all classes][org.springframework.batch.item.file.transform]

COVERAGE SUMMARY FOR SOURCE FILE [RangeArrayPropertyEditor.java]

nameclass, %method, %block, %line, %
RangeArrayPropertyEditor.java100% (2/2)100% (8/8)93%  (282/302)98%  (40/41)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RangeArrayPropertyEditor100% (1/1)100% (6/6)93%  (259/279)98%  (39/40)
setAsText (String): void 100% (1/1)81%  (87/107)94%  (15/16)
RangeArrayPropertyEditor (): void 100% (1/1)100% (6/6)100% (2/2)
getAsText (): String 100% (1/1)100% (32/32)100% (7/7)
setForceDisjointRanges (boolean): void 100% (1/1)100% (4/4)100% (2/2)
setMaxValues (Range []): void 100% (1/1)100% (76/76)100% (10/10)
verifyRanges (Range []): void 100% (1/1)100% (54/54)100% (3/3)
     
class RangeArrayPropertyEditor$1100% (1/1)100% (2/2)100% (23/23)100% (2/2)
RangeArrayPropertyEditor$1 (RangeArrayPropertyEditor, Range []): void 100% (1/1)100% (9/9)100% (1/1)
compare (Integer, Integer): int 100% (1/1)100% (14/14)100% (1/1)

1/*
2 * Copyright 2006-2007 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17package org.springframework.batch.item.file.transform;
18 
19import java.beans.PropertyEditorSupport;
20import java.util.Arrays;
21import java.util.Comparator;
22 
23import org.springframework.util.Assert;
24import org.springframework.util.StringUtils;
25 
26/**
27 * Property editor implementation which parses string and creates array of
28 * ranges. Ranges can be provided in any order. </br> Input string should be
29 * provided in following format: 'range1, range2, range3,...' where range is
30 * specified as:
31 * <ul>
32 * <li>'X-Y', where X is minimum value and Y is maximum value (condition X<=Y
33 * is verified)</li>
34 * <li>or 'Z', where Z is minimum and maximum is calculated as (minimum of
35 * adjacent range - 1). Maximum of the last range is never calculated. Range
36 * stays unbound at maximum side if maximum value is not provided.</li>
37 * </ul>
38 * Minimum and maximum values can be from interval &lt;1, Integer.MAX_VALUE-1&gt;
39 * <p>
40 * Examples:</br> 
41 * '1, 15, 25, 38, 55-60' is equal to '1-14, 15-24, 25-37, 38-54, 55-60' </br> 
42 * '36, 14, 1-10, 15, 49-57' is equal to '36-48, 14-14, 1-10, 15-35, 49-57'
43 * <p>
44 * Property editor also allows to validate whether ranges are disjoint. Validation
45 * can be turned on/off by using {@link #setForceDisjointRanges(boolean)}. By default 
46 * validation is turned off.
47 * 
48 * @author peter.zozom
49 */
50public class RangeArrayPropertyEditor extends PropertyEditorSupport {
51        
52        private boolean forceDisjointRanges = false;
53        
54        /**
55         * Set force disjoint ranges. If set to TRUE, ranges are validated to be disjoint.
56         * For example: defining ranges '1-10, 5-15' will cause IllegalArgumentException in
57         * case of forceDisjointRanges=TRUE.  
58         * @param forceDisjointRanges 
59         */
60        public void setForceDisjointRanges(boolean forceDisjointRanges) {
61                this.forceDisjointRanges = forceDisjointRanges;
62        }
63 
64    @Override
65        public void setAsText(String text) throws IllegalArgumentException {
66                
67                //split text into ranges
68                String[] strRanges = text.split(",");
69                Range[] ranges = new Range[strRanges.length];
70                
71                //parse ranges and create array of Range objects 
72                for (int i = 0; i < strRanges.length; i++) {                        
73                        String[] range = strRanges[i].split("-");
74                
75                        int min;
76                        int max;
77                        
78                        if ((range.length == 1) && (StringUtils.hasText(range[0]))) {
79                                min = Integer.parseInt(range[0].trim());
80                                // correct max value will be assigned later
81                                ranges[i] = new Range(min);
82                        } else if ((range.length == 2) && (StringUtils.hasText(range[0]))
83                                        && (StringUtils.hasText(range[1]))) {
84                                min = Integer.parseInt(range[0].trim());
85                                max = Integer.parseInt(range[1].trim());
86                                ranges[i] = new Range(min,max);
87                        } else {
88                                throw new IllegalArgumentException("Range[" + i + "]: range (" + strRanges[i] + ") is invalid");
89                        }                        
90                        
91                }
92        
93                setMaxValues(ranges);
94                setValue(ranges);
95        }
96        
97    @Override
98        public String getAsText() {
99                Range[] ranges = (Range[])getValue();
100                
101                StringBuffer sb = new StringBuffer();
102 
103                for (int i = 0; i < ranges.length; i++) {
104                        if(i>0) {
105                                sb.append(", ");
106                        }
107                        sb.append(ranges[i]);
108                }
109                return sb.toString();
110        }
111        
112        private void setMaxValues(final Range[] ranges) {
113                
114                // Array of integers to track range values by index
115                Integer[] c = new Integer[ranges.length];
116                for (int i=0; i<c.length; i++) {
117                        c[i] = i;
118                }
119                
120                //sort array of Ranges
121                Arrays.sort(c, new Comparator<Integer>() {
122                @Override
123                                public int compare(Integer r1, Integer r2) {
124                                        return ranges[r1].getMin()-ranges[r2].getMin();
125                                }                                                                
126                        }
127                );
128                
129                //set max values for all unbound ranges (except last range)
130                for (int i = 0; i < c.length - 1; i++) {
131                        if (!ranges[c[i]].hasMaxValue()) {
132                                //set max value to (min value - 1) of the next range
133                                ranges[c[i]] = new Range(ranges[c[i]].getMin(),ranges[c[i+1]].getMin() - 1);
134                        }
135                }
136                
137                if (forceDisjointRanges) {
138                        verifyRanges(ranges);
139                }
140        }
141        
142        
143        private void verifyRanges(Range[] ranges) {
144                //verify that ranges are disjoint                
145                for(int i = 1; i < ranges.length;i++) {
146                        Assert.isTrue(ranges[i-1].getMax() < ranges[i].getMin(),
147                                        "Ranges must be disjoint. Range[" + (i-1) + "]: (" + ranges[i-1] + 
148                                        ") Range[" + i +"]: (" + ranges[i] + ")");
149                }
150        }
151}

[all classes][org.springframework.batch.item.file.transform]
EMMA 2.0.5312 (C) Vladimir Roubtsov