View Javadoc

1   package net.sourceforge.argval.version;
2   
3   import java.util.ArrayList;
4   import java.util.HashMap;
5   import java.util.Iterator;
6   import java.util.List;
7   import java.util.Map;
8   import java.util.Set;
9   import java.util.SortedSet;
10  import java.util.TreeSet;
11  import java.util.regex.Matcher;
12  import java.util.regex.Pattern;
13  
14  import net.sourceforge.argval.collection.CollectionUtil;
15  import net.sourceforge.argval.utils.StringUtil;
16  
17  import org.slf4j.Logger;
18  import org.slf4j.LoggerFactory;
19  
20  /**
21   *  
22   * 
23   * @author <a  href="http://sourceforge.net/users/verhagent/">T. Verhagen</a>
24   */
25  public class VersionHierarchyImpl implements VersionHierarchy
26  {
27      protected Logger logger = LoggerFactory.getLogger(VersionHierarchyImpl.class);
28      private final String versionPartSeparator;
29      private final Map<String, VersionHierarchyImpl> versionMap = new HashMap<String, VersionHierarchyImpl>(); 
30      
31      public VersionHierarchyImpl()
32      {
33          this(VersionHierarchy.VERSION_PART_SEPARATOR);
34      }
35      public VersionHierarchyImpl(String versionPartSeparator) {
36          super();
37          this.versionPartSeparator = versionPartSeparator;
38      }
39  
40  
41      public String getVersionPartSeparator() {
42          return versionPartSeparator;
43      }
44  
45  
46      public void addVersion(VersionNumber version)
47      {
48          addVersion(version.getPartitionedVersion());
49      }
50  
51      public void addVersion(final String versionStr) {
52          addVersion(convertVersion(versionStr));
53      }
54      
55      public void addVersion(final List<String> version)
56      {
57          if (version == null || version.size() == 0)
58          {
59              return;
60          }
61          final ArrayList<String> versionList = (version instanceof ArrayList<?>)
62                  ? (ArrayList<String>)version
63                  : new ArrayList<String>(version);
64          
65          final String part = versionList.remove(0);
66          if (! this.versionMap.containsKey(part))
67          {
68              this.versionMap.put(part, new VersionHierarchyImpl());
69          }
70          this.versionMap.get(part).addVersion(versionList);
71      }
72  
73      public List<String> convertVersion(final String versionStr) {
74          return StringUtil.convertToList(versionStr, getVersionPartSeparator());
75      }
76      
77      
78      public boolean isCompatible(VersionNumber version) {
79          return isCompatible(version.getPartitionedVersion());
80      }
81  
82      
83      public boolean isCompatible(String versionStr) {
84          return isCompatible(convertVersion(versionStr));
85      }
86      
87      
88      public boolean isCompatible(List<String> version) {
89          if (version == null || version.size() == 0) {
90              throw new IllegalArgumentException("Argument 'version' can not be null or an empty list.");
91          }
92          boolean isCompatibel = isCompatibel(version, 0);
93          logger.trace("isCompatible( " + CollectionUtil.toString(version) + " )  " + isCompatibel);
94          return isCompatibel;
95      }
96      
97      private boolean isCompatibel(List<String> version, int index) {
98          final boolean isCompatibel;
99          if (index >= version.size()) {
100             isCompatibel = this.versionMap.size() == 0;
101         }
102         else {
103             if (this.versionMap.containsKey(version.get(index))) {
104                 isCompatibel = this.versionMap.get(version.get(index)).isCompatibel(version, index + 1);
105             }
106             else {
107                 if (this.versionMap.size() > 0) {
108                     SortedSet<String> set = new TreeSet<String>(this.versionMap.keySet());
109 //                    System.out.println("last: " + set.last() + "  part: " + version.get(index) 
110 //                            + "  compareTo: " + set.last().compareTo(version.get(index))
111 //                            + "  compareTo: " + version.get(index).compareTo(set.last()));
112                     Pattern pattern = Pattern.compile("(\\d*)");
113                     Matcher matcherA = pattern.matcher(version.get(index));
114                     Matcher matcherB = pattern.matcher(set.last());
115                     if (matcherA.matches() && matcherB.matches())
116                     {
117                         Integer valueA = Integer.valueOf(version.get(index));
118                         Integer valueB = Integer.valueOf(set.last());
119                         isCompatibel = valueA >= valueB;
120                     }
121                     else
122                     {
123                         isCompatibel = version.get(index).compareTo(set.last()) >= 0;
124                     }
125                 }
126                 else {
127                     isCompatibel = true;
128                 }
129             }
130         }
131         
132         return isCompatibel;
133     }
134     
135     public String toString() {
136         List<String> allVersions = getRegisteredVersionAsStings();
137         return CollectionUtil.toString(allVersions);
138     }
139     
140     public List<String> getRegisteredVersionAsStings()
141     {
142         final List<String> versionList = new ArrayList<String>();
143         visit("", versionList);
144         return versionList;
145     }
146 
147     private void visit(final String versionStr, final List<String> versionList) {
148         if (this.versionMap.size() == 0) {
149             versionList.add(versionStr);
150             return;
151         }
152         
153         for (final String part : new TreeSet<String>(versionMap.keySet())) {
154             versionMap.get(part).visit(versionStr + ((versionStr.length() > 0) ? VERSION_PART_SEPARATOR : "") + part, versionList);
155         }
156     }
157 
158     private void visit(final List<String> singleVersion, final List<VersionNumber> versionList) {
159         if (this.versionMap.size() == 0) {
160             versionList.add(new VersionNumberImpl(singleVersion));
161             return;
162         }
163         
164         Set<Integer> orderedNumbers = createOrderedNumberSet(versionMap.keySet());
165         if (orderedNumbers.size() > 0) {
166             //System.out.println("numbers only: " + orderedNumbers);
167             for (final Integer part : orderedNumbers) {
168                 ArrayList<String> newSingleList = new ArrayList<String>(singleVersion);
169                 newSingleList.add(part.toString());
170                 versionMap.get(part.toString()).visit(newSingleList, versionList);
171             }
172         }
173         else {
174             for (final String part : new TreeSet<String>(versionMap.keySet())) {
175                 ArrayList<String> newSingleList = new ArrayList<String>(singleVersion);
176                 newSingleList.add(part);
177                 versionMap.get(part).visit(newSingleList, versionList);
178             }
179         }
180     }
181 
182     private Set<Integer> createOrderedNumberSet(Set<String> versionStrSet) {
183         final TreeSet<Integer> numbers = new TreeSet<Integer>();
184         boolean isOnlyNumbers = true;
185         for (Iterator<String> iter = versionStrSet.iterator(); iter.hasNext(); ) {
186             String versionStr = iter.next();
187             if (Pattern.matches("\\d*", versionStr)) {
188                 numbers.add(Integer.valueOf(versionStr));
189             }
190             else {
191                 isOnlyNumbers = false;
192             }
193         }
194         
195         if (! isOnlyNumbers) {
196             numbers.clear();
197         }
198         return numbers; 
199     }
200     
201     //@Override
202     public List<VersionNumber> getRegisteredVersionNumbers() {
203         final List<VersionNumber> versionList = new ArrayList<VersionNumber>();
204         visit(new ArrayList<String>(), versionList);
205         return versionList;
206     }
207 
208     //@Override
209     public void accept(VersionNumberVisitor visitor) {
210         final List<VersionNumber> versionList = getRegisteredVersionNumbers();
211         for (VersionNumber versionNumber : versionList) {
212             visitor.visit(versionNumber);
213         }
214     }
215     
216 }