View Javadoc
1   /*
2    * dpkg - Debian Package library and the Debian Package Maven plugin
3    * (c) Copyright 2016 Gerrit Hohl
4    *
5    * This program is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU General Public License
7    * as published by the Free Software Foundation; either version 2
8    * of the License, or (at your option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with this program; if not, write to the Free Software
17   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18   */
19  package net.sourceforge.javadpkg.control.impl;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import net.sourceforge.javadpkg.Context;
25  import net.sourceforge.javadpkg.ParseException;
26  import net.sourceforge.javadpkg.control.PackageDependency;
27  import net.sourceforge.javadpkg.control.PackageDependency.Condition;
28  import net.sourceforge.javadpkg.control.PackageDependencyParser;
29  import net.sourceforge.javadpkg.control.PackageName;
30  import net.sourceforge.javadpkg.control.PackageNameParser;
31  import net.sourceforge.javadpkg.control.PackageVersion;
32  import net.sourceforge.javadpkg.control.PackageVersionParser;
33  import net.sourceforge.javadpkg.control.PackageVersionRelationOperator;
34  import net.sourceforge.javadpkg.control.PackageVersionRelationOperatorParser;
35  
36  
37  /**
38   * <p>
39   * A {@link PackageDependencyParser} implementation.
40   * </p>
41   *
42   * @author Gerrit Hohl (gerrit-hohl@users.sourceforge.net)
43   * @version <b>1.0</b>, 01.01.2016 by Gerrit Hohl
44   * @version <b>1.1</b>, 23.01.2018 by Gerrit Hohl
45   */
46  public class PackageDependencyParserImpl implements PackageDependencyParser {
47  
48  
49  	/** The parser for the package names. */
50  	private PackageNameParser						packageNameParser;
51  	/** The parser for the relation operator. */
52  	private PackageVersionRelationOperatorParser	packageVersionRelationOperatorParser;
53  	/** The parser for the package version. */
54  	private PackageVersionParser					packageVersionParser;
55  
56  
57  	/**
58  	 * <p>
59  	 * Creates a parser.
60  	 * </p>
61  	 *
62  	 * @param packageNameParser
63  	 *            The parser for the package names.
64  	 * @param packageVersionRelationOperatorParser
65  	 *            The parser for the relation operator.
66  	 * @param packageVersionParser
67  	 *            The parser for the package version.
68  	 * @throws IllegalArgumentException
69  	 *             If any of the parameters are <code>null</code>.
70  	 */
71  	public PackageDependencyParserImpl(PackageNameParser packageNameParser,
72  			PackageVersionRelationOperatorParser packageVersionRelationOperatorParser,
73  			PackageVersionParser packageVersionParser) {
74  
75  		super();
76  
77  		if (packageNameParser == null)
78  			throw new IllegalArgumentException("Argument packageNameParser is null.");
79  		if (packageVersionRelationOperatorParser == null)
80  			throw new IllegalArgumentException("Argument packageVersionRelationOperatorParser is null.");
81  		if (packageVersionParser == null)
82  			throw new IllegalArgumentException("Argument packageVersionParser is null.");
83  
84  		this.packageNameParser = packageNameParser;
85  		this.packageVersionRelationOperatorParser = packageVersionRelationOperatorParser;
86  		this.packageVersionParser = packageVersionParser;
87  	}
88  
89  
90  	@Override
91  	public PackageDependency parsePackageDependency(String value, Context context) throws ParseException {
92  		PackageDependency dependency;
93  		List<PackageDependency> dependencies;
94  		String[] parts;
95  		PackageName packageName;
96  		PackageVersionRelationOperator relationOperator = null;
97  		PackageVersion version = null;
98  		String part;
99  		
100 		
101 		if (value == null)
102 			throw new IllegalArgumentException("Argument value is null.");
103 		if (context == null)
104 			throw new IllegalArgumentException("Argument context is null.");
105 
106 		// --- Does the value contain an OR condition? ---
107 		parts = value.split("\\|");
108 		if (parts.length > 1) {
109 			dependencies = new ArrayList<>();
110 			for (String p : parts) {
111 				try {
112 					dependency = this.parsePackageDependency(p.trim(), context);
113 				} catch (ParseException e) {
114 					throw new ParseException("Couldn't parse dependencies |" + value + "|: " + e.getMessage(), e);
115 				}
116 				dependencies.add(dependency);
117 			}
118 			dependency = new PackageDependencyImpl(Condition.OR, dependencies);
119 		}
120 		// --- Otherwise it is a normal value ---
121 		else {
122 			parts = value.split("[ \\t]+", 2);
123 			try {
124 				// --- Get name ---
125 				packageName = this.packageNameParser.parsePackageName(parts[0], context);
126 				// --- Do we also have a version and maybe a relational operator? ---
127 				if (parts.length > 1) {
128 					// --- Get parts ---
129 					part = parts[1];
130 					if (part.startsWith("(") && part.endsWith(")")) {
131 						part = part.substring(1, part.length() - 1);
132 						parts = part.split(" ", 2);
133 						// --- Maybe there is no whitespace ---
134 						if (parts.length == 1) {
135 							// --- Then we split the part before the 1st number from the part starting at that number ---
136 							parts = part.split("([0-9]){1}", 2);
137 							if ((parts.length == 1) || (parts[0].length() == 0)) {
138 								parts = new String[] { part };
139 							} else {
140 								parts[1] = part.substring(parts[0].length());
141 							}
142 						}
143 					} else
144 						throw new ParseException("Expected a version criteria, but found |" + part + "|.");
145 
146 					// --- Do we have a relational operator? ---
147 					if (parts.length > 1) {
148 						relationOperator = this.packageVersionRelationOperatorParser
149 								.parsePackageVersionRelationOperator(parts[0]);
150 						version = this.packageVersionParser.parsePackageVersion(parts[1], context);
151 					}
152 					// --- Otherwise parse only the version ---
153 					else {
154 						version = this.packageVersionParser.parsePackageVersion(parts[0], context);
155 					}
156 				}
157 			} catch (ParseException e) {
158 				throw new ParseException("Couldn't parse package dependency |" + value + "|: " + e.getMessage(), e);
159 			}
160 			dependency = new PackageDependencyImpl(packageName, relationOperator, version);
161 		}
162 		return dependency;
163 	}
164 	
165 	
166 	@Override
167 	public List<PackageDependency> parsePackageDependencies(String values, Context context) throws ParseException {
168 		List<PackageDependency> dependencies;
169 		String[] parts;
170 		PackageDependency dependency;
171 		
172 		
173 		if (values == null)
174 			throw new IllegalArgumentException("Argument values is null.");
175 		if (context == null)
176 			throw new IllegalArgumentException("Argument context is null.");
177 
178 		dependencies = new ArrayList<>();
179 		parts = values.split(",");
180 		for (String part : parts) {
181 			try {
182 				dependency = this.parsePackageDependency(part.trim(), context);
183 			} catch (ParseException e) {
184 				throw new ParseException("Couldn't parse dependencies |" + values + "|: " + e.getMessage(), e);
185 			}
186 			dependencies.add(dependency);
187 		}
188 		return dependencies;
189 	}
190 	
191 	
192 	/* **********************************************************************
193 	 * **********************************************************************
194 	 * **********************************************************************
195 	 * **********************************************************************
196 	 * **********************************************************************
197 	 */
198 	
199 	
200 	/**
201 	 * <p>
202 	 * The {@link PackageDependency} implementation of this class.
203 	 * </p>
204 	 *
205 	 * @author Gerrit Hohl (gerrit-hohl@users.sourceforge.net)
206 	 * @version <b>1.0</b>, 01.01.2016 by Gerrit Hohl
207 	 */
208 	private class PackageDependencyImpl implements PackageDependency {
209 
210 
211 		/** The condition. */
212 		private Condition						condition;
213 		/** The package dependencies for the condition. */
214 		private List<PackageDependency>			packageDependencies;
215 		/** The name of the package. */
216 		private PackageName						packageName;
217 		/** The relational operator (optional). */
218 		private PackageVersionRelationOperator	relationOperator;
219 		/** The version (optional). */
220 		private PackageVersion					version;
221 
222 
223 		/**
224 		 * <p>
225 		 * Creates a package dependency.
226 		 * </p>
227 		 *
228 		 * @param condition
229 		 *            The condition.
230 		 * @param packageDependencies
231 		 *            The package dependencies for the condition.
232 		 */
233 		public PackageDependencyImpl(Condition condition, List<PackageDependency> packageDependencies) {
234 			super();
235 			
236 			this.condition = condition;
237 			this.packageDependencies = new ArrayList<>(packageDependencies);
238 			this.packageName = null;
239 			this.relationOperator = null;
240 			this.version = null;
241 		}
242 
243 
244 		/**
245 		 * <p>
246 		 * Creates a package dependency.
247 		 * </p>
248 		 *
249 		 * @param packageName
250 		 *            The name of the package.
251 		 * @param relationOperator
252 		 *            The relational operator (optional).
253 		 * @param version
254 		 *            The version (optional).
255 		 */
256 		public PackageDependencyImpl(PackageName packageName, PackageVersionRelationOperator relationOperator,
257 				PackageVersion version) {
258 
259 			super();
260 			
261 			this.condition = null;
262 			this.packageDependencies = new ArrayList<>();
263 			this.packageName = packageName;
264 			this.relationOperator = relationOperator;
265 			this.version = version;
266 		}
267 
268 
269 		@Override
270 		public boolean isCondition() {
271 			return (this.condition != null);
272 		}
273 
274 
275 		@Override
276 		public Condition getCondition() {
277 			return this.condition;
278 		}
279 
280 
281 		@Override
282 		public List<PackageDependency> getConditionPackageDependencies() {
283 			return (new ArrayList<>(this.packageDependencies));
284 		}
285 
286 
287 		@Override
288 		public PackageName getPackage() {
289 			return this.packageName;
290 		}
291 
292 
293 		@Override
294 		public PackageVersionRelationOperator getRelationOperator() {
295 			return this.relationOperator;
296 		}
297 
298 
299 		@Override
300 		public PackageVersion getVersion() {
301 			return this.version;
302 		}
303 
304 
305 	}
306 
307 
308 }