View Javadoc
1   package fr.ifremer.quadrige3.core.dao.technical;
2   
3   /*
4    * #%L
5    * Reef DB :: Core
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2014 - 2015 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   *
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   *
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  import org.apache.commons.collections4.CollectionUtils;
27  import org.apache.commons.lang3.StringUtils;
28  
29  import java.util.*;
30  import java.util.regex.Matcher;
31  import java.util.regex.Pattern;
32  
33  /**
34   * String iterator with pattern
35   * <p/>
36   * Created by Ludovic on 16/07/2015.
37   */
38  public class StringIterator implements Iterator<String> {
39  
40      public static final String DEFAULT_PATTERN = "%s";
41      private final String pattern;
42  
43      private int number;
44  
45      /**
46       * Create a new StringIterator
47       *
48       * @param objects      a {@link Collection} object.
49       * @param propertyName a {@link String} object.
50       * @return a {@link fr.ifremer.quadrige3.core.dao.technical.StringIterator} object.
51       */
52      public static StringIterator newStringIteratorByProperty(Collection<?> objects, String propertyName) {
53          return newStringIteratorByProperty(objects, propertyName, null);
54      }
55  
56      /**
57       * Create a new StringIterator
58       *
59       * @param objects         a {@link Collection} object.
60       * @param propertyName    a {@link String} object.
61       * @param preferredPrefix a {@link String} object.
62       * @return a {@link fr.ifremer.quadrige3.core.dao.technical.StringIterator} object.
63       */
64      public static StringIterator newStringIteratorByProperty(Collection<?> objects, String propertyName, String preferredPrefix) {
65  
66          // compute preferred pattern
67          String preferredPattern = StringUtils.isNotBlank(preferredPrefix) ? preferredPrefix + DEFAULT_PATTERN : null;
68  
69          if (CollectionUtils.isEmpty(objects) || StringUtils.isBlank(propertyName)) {
70              return StringUtils.isNotBlank(preferredPattern)
71                      ? new StringIterator(preferredPattern, 0)
72                      : new StringIterator();
73          }
74  
75          Map<String, Integer> patternMap = new HashMap<>();
76          if (StringUtils.isNotBlank(preferredPattern)) {
77              patternMap.put(preferredPattern, 0);
78          }
79  
80          for (Object object : objects) {
81              String property = Beans.getProperty(object, propertyName);
82              if (StringUtils.isNotBlank(property)) {
83  
84                  // find by regex
85                  Matcher matcher = Pattern.compile("(\\d+)(?!.*\\d)").matcher(property);
86                  if (matcher.find()) {
87  
88                      // build pattern
89                      int thisIncrement = Integer.parseInt(matcher.group(1));
90                      String thisPattern = matcher.replaceAll(DEFAULT_PATTERN);
91                      Integer actualIncrement = patternMap.get(thisPattern);
92                      if (actualIncrement != null) {
93                          thisIncrement = Math.max(actualIncrement, thisIncrement);
94                      }
95                      patternMap.put(thisPattern, thisIncrement);
96  
97                  } else {
98  
99                      // only a string
100                     int thisIncrement = 0;
101                     String thisPattern = property + DEFAULT_PATTERN;
102                     Integer actualIncrement = patternMap.get(thisPattern);
103                     if (actualIncrement != null) {
104                         thisIncrement = Math.max(actualIncrement, thisIncrement);
105                     }
106                     patternMap.put(thisPattern, thisIncrement);
107                 }
108             }
109         }
110 
111         if (StringUtils.isNotBlank(preferredPattern)) {
112 
113             // choose the preferred pattern
114             return new StringIterator(preferredPattern, patternMap.get(preferredPattern));
115         }
116 
117         if (!patternMap.isEmpty()) {
118 
119             String pattern;
120             if (patternMap.size() == 1) {
121 
122                 // only one pattern
123                 pattern = patternMap.keySet().iterator().next();
124 
125             } else {
126 
127                 // choose the lexically highest pattern
128                 List<String> patterns = new ArrayList<>(patternMap.keySet());
129                 Collections.sort(patterns);
130                 pattern = patterns.get(patterns.size() - 1);
131             }
132             return new StringIterator(pattern, patternMap.get(pattern));
133         }
134 
135         return new StringIterator();
136     }
137 
138     /**
139      * <p>Constructor for StringIterator.</p>
140      */
141     public StringIterator() {
142         this(DEFAULT_PATTERN, 0);
143     }
144 
145     /**
146      * <p>Constructor for StringIterator.</p>
147      *
148      * @param pattern a {@link String} object.
149      * @param number  a int.
150      */
151     public StringIterator(String pattern, int number) {
152         this.pattern = pattern;
153         this.number = number;
154     }
155 
156     /**
157      * {@inheritDoc}
158      */
159     @Override
160     public boolean hasNext() {
161         return true;
162     }
163 
164     /**
165      * {@inheritDoc}
166      */
167     @Override
168     public String next() {
169         number++;
170         return String.format(pattern, number);
171     }
172 
173     /**
174      * {@inheritDoc}
175      */
176     @Override
177     public void remove() {
178         // do nothing
179     }
180 
181     public String getPattern() {
182         return pattern;
183     }
184 
185     public String getPrefix() {
186         return pattern.replace(DEFAULT_PATTERN, "");
187     }
188 
189 }