1 | /******************************************************************************* |
2 | * Copyright (c) 2007, 2009 IBM Corporation and others. |
3 | * All rights reserved. This program and the accompanying materials |
4 | * are made available under the terms of the Eclipse Public License v1.0 |
5 | * which accompanies this distribution, and is available at |
6 | * http://www.eclipse.org/legal/epl-v10.html |
7 | * |
8 | * Contributors: |
9 | * IBM Corporation - initial API and implementation |
10 | *******************************************************************************/ |
11 | package org.eclipse.pde.api.tools.internal.util; |
12 | |
13 | import java.util.regex.Matcher; |
14 | import java.util.regex.Pattern; |
15 | |
16 | import org.osgi.framework.Version; |
17 | |
18 | /** |
19 | * Version identifier for @since tags. It consists of an optional bundle name followed by a |
20 | * version string that follows the format defined in the class {@link Version} |
21 | * |
22 | * @since 3.4 |
23 | */ |
24 | public class SinceTagVersion { |
25 | private String prefixString; |
26 | private Version version; |
27 | private String versionString; |
28 | private String postfixString; |
29 | private static final Pattern VERSION_PATTERN = Pattern.compile("([0-9]+\\.?[0-9]?\\.?[0-9]?\\.?[A-Za-z0-9]*)");; //$NON-NLS-1$ |
30 | |
31 | /** |
32 | * Creates a new instance. |
33 | * |
34 | * @param value the given since tag value |
35 | * @throws IllegalArgumentException if the given value is null |
36 | */ |
37 | public SinceTagVersion(String value) { |
38 | if (value == null) { |
39 | throw new IllegalArgumentException("The given value cannot be null"); //$NON-NLS-1$ |
40 | } |
41 | char[] chars = value.toCharArray(); |
42 | final int READ_VERSION = 0; |
43 | final int INSIDE_VERSION = 1; |
44 | |
45 | int mode = READ_VERSION; |
46 | |
47 | loop: for (int i = 0, max = chars.length; i < max; i++) { |
48 | char currentChar = chars[i]; |
49 | switch(mode) { |
50 | case READ_VERSION : |
51 | switch(currentChar) { |
52 | case '0' : |
53 | case '1' : |
54 | case '2' : |
55 | case '3' : |
56 | case '4' : |
57 | case '5' : |
58 | case '6' : |
59 | case '7' : |
60 | case '8' : |
61 | case '9' : |
62 | mode = INSIDE_VERSION; |
63 | i--; |
64 | break; |
65 | default : |
66 | } |
67 | break; |
68 | case INSIDE_VERSION : |
69 | // read sequence of digits |
70 | int start = i; |
71 | loop2 : while (i < max) { |
72 | if (Character.isWhitespace(currentChar)) { |
73 | break loop2; |
74 | } |
75 | if (Character.isLetterOrDigit(currentChar) |
76 | || currentChar == '.') { |
77 | currentChar = chars[i]; |
78 | i++; |
79 | } else { |
80 | break loop2; |
81 | } |
82 | } |
83 | // extract "version string" |
84 | String potentialVersion = null; |
85 | if (i == max) { |
86 | potentialVersion= value.substring(start, i); |
87 | } else { |
88 | potentialVersion= value.substring(start, i - 1); |
89 | } |
90 | // check if it matches |
91 | Matcher m = VERSION_PATTERN.matcher(potentialVersion); |
92 | if (m.find()) { |
93 | this.versionString = potentialVersion; |
94 | if (start != 0) { |
95 | this.prefixString = value.substring(0, start); |
96 | // if prefixString doesn't end with a space, this is a wrong version |
97 | if (Character.isLetterOrDigit(value.charAt(start - 1))) { |
98 | this.versionString = null; |
99 | this.prefixString = null; |
100 | continue loop; |
101 | } |
102 | } |
103 | if (i != max) { |
104 | this.postfixString = value.substring(i - 1); |
105 | } |
106 | try { |
107 | this.version = new Version(this.versionString); |
108 | } catch (IllegalArgumentException e) { |
109 | // ignore - wrong format |
110 | } |
111 | return; |
112 | } |
113 | mode = READ_VERSION; |
114 | } |
115 | } |
116 | if (this.versionString == null) { |
117 | this.postfixString = value; |
118 | } |
119 | } |
120 | |
121 | /** |
122 | * Returns the version part of the @since tag as a string. null if the given version did not have the right format |
123 | * |
124 | * @return the version part of the @since tag |
125 | */ |
126 | public String getVersionString() { |
127 | return this.versionString; |
128 | } |
129 | |
130 | /** |
131 | * Returns the version part of the @since tag. null if the given version did not have the right format |
132 | * |
133 | * @return the version part of the @since tag |
134 | */ |
135 | public Version getVersion() { |
136 | return this.version; |
137 | } |
138 | |
139 | /** |
140 | * Returns the prefix part of the @since tag. It can be null. |
141 | * |
142 | * @return the prefix part of the @since tag |
143 | */ |
144 | public String prefixString() { |
145 | return this.prefixString; |
146 | } |
147 | /** |
148 | * Returns the postfix part of the @since tag. It can be null. |
149 | * |
150 | * @return the postfix part of the @since tag |
151 | */ |
152 | public String postfixString() { |
153 | return this.postfixString; |
154 | } |
155 | } |