1 /*******************************************************************************
2  *  Copyright (c) 2014, 2017 SAP AG and others.
3  *
4  *  This program and the accompanying materials
5  *  are made available under the terms of the Eclipse Public License 2.0
6  *  which accompanies this distribution, and is available at
7  *  https://www.eclipse.org/legal/epl-2.0/
8  *
9  *  SPDX-License-Identifier: EPL-2.0
10  *
11  *  Contributors:
12  *      SAP AG - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.equinox.internal.p2.director.app;
15 
16 import java.util.*;
17 import java.util.regex.Pattern;
18 import org.eclipse.equinox.p2.metadata.IInstallableUnit;
19 
20 /**
21  * Formats a set of {@link IInstallableUnit}s to a string specified
22  * by a format string.  The format string's syntax is
23  * <code>${&lt;property&gt;}</code>, where <code>&lt;property&gt;</code>
24  * is one of the unit's {@link IInstallableUnit#getProperties() properties constants}.
25  * Two special properties are supported:
26  * <ul>
27  * <li>{@link IInstallableUnit#getId() IU id}: <code>${id}</code></li>
28  * <li>{@link IInstallableUnit#getVersion() IU version}: <code>${version}</code></li>
29  * </ul>
30  */
31 public class IUListFormatter {
32 
33 	private static final String PREFIX = "${"; //$NON-NLS-1$
34 	private static final String LINE_SEP = System.lineSeparator();
35 
36 	private String formatString;
37 	private Collection<String> properties;
38 
IUListFormatter(String formatString)39 	public IUListFormatter(String formatString) {
40 		this.formatString = formatString;
41 		this.properties = parse(formatString);
42 	}
43 
format(Collection<IInstallableUnit> ius)44 	public String format(Collection<IInstallableUnit> ius) {
45 		StringBuilder result = new StringBuilder();
46 		for (IInstallableUnit iu : ius) {
47 			format(iu, result);
48 		}
49 
50 		if (result.length() > 0)
51 			result.setLength(result.length() - LINE_SEP.length()); //remove trailing newline
52 		return result.toString();
53 	}
54 
format(IInstallableUnit iu, StringBuilder result)55 	private void format(IInstallableUnit iu, StringBuilder result) {
56 		String s = formatString;
57 		for (String property : properties) {
58 			Pattern pattern = Pattern.compile(String.format("\\$\\{%s\\}", property)); //$NON-NLS-1$
59 			if (null == property) {
60 				String value = iu.getProperty(property, "df_LT"); //$NON-NLS-1$
61 				if (value == null)
62 					value = ""; //$NON-NLS-1$ unknown property
63 				s = insert(value, pattern, s);
64 			} else switch (property) {
65 				case "id": //$NON-NLS-1$
66 					s = insert(iu.getId(), pattern, s);
67 					break;
68 				case "version": //$NON-NLS-1$
69 					s = insert(iu.getVersion().toString(), pattern, s);
70 					break;
71 				default:
72 					String value = iu.getProperty(property, "df_LT"); //$NON-NLS-1$
73 					if (value == null)
74 						value = ""; //$NON-NLS-1$ unknown property
75 					s = insert(value, pattern, s);
76 					break;
77 			}
78 		}
79 
80 		result.append(s);
81 		result.append(LINE_SEP);
82 	}
83 
insert(String replacement, Pattern template, String s)84 	private static String insert(String replacement, Pattern template, String s) {
85 		return template.matcher(s).replaceAll(replacement);
86 	}
87 
88 	/*
89 	 * Finds all IU properties in the format string
90 	 */
parse(String string)91 	private static Collection<String> parse(String string) {
92 		Set<String> properties = new HashSet<>(5);
93 		int start = 0;
94 		while (start < string.length() && (start = string.indexOf(PREFIX, start)) > -1) {
95 			int end = string.indexOf('}', start + PREFIX.length());
96 			if (end > start) {
97 				String property = string.substring(start + PREFIX.length(), end);
98 				properties.add(property);
99 				start = end + 1;
100 			} else {
101 				// malformed input, be permissive and go on
102 				start++;
103 			}
104 		}
105 		return properties;
106 	}
107 
108 }
109