1 /*******************************************************************************
2  * Copyright (c) 2016, 2017 Red Hat Inc. 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  *     Sopot Cela (Red Hat Inc.)
13  *     Lucas Bullen (Red Hat Inc.) - [Bug 531918] filter suggestions
14  *******************************************************************************/
15 package org.eclipse.pde.internal.genericeditor.target.extension.model;
16 
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21 
22 import org.eclipse.pde.internal.genericeditor.target.extension.p2.P2Fetcher;
23 
24 /**
25  * This class is used to cache the p2 repositories completion information order
26  * to minimize IO round trips and have instant completion for IUs and their
27  * versions.
28  *
29  * There will be only one cache shared between editors. In the future a function
30  * will be added for the user to be able to flush this cache.
31  */
32 public class RepositoryCache {
33 
34 	private static RepositoryCache instance;
35 
36 	Map<String, List<UnitNode>> cache = new HashMap<>();
37 
RepositoryCache()38 	private RepositoryCache() {
39 		//avoid instantiation
40 	}
41 
42 	/**
43 	 * @return default instance of this cache.
44 	 */
45 
getDefault()46 	public static RepositoryCache getDefault() {
47 		if (instance == null) {
48 			instance = new RepositoryCache();
49 		}
50 		return instance;
51 	}
52 
53 	/**
54 	 * Fetches information and caches it.
55 	 *
56 	 * @param repo
57 	 *            repository URL
58 	 * @param flush
59 	 *            whether a flush is needed
60 	 * @return list of IUs available in the 'repo' repository. Never
61 	 *         <code>null</code>.
62 	 */
fetchP2UnitsFromRepo(String repo, boolean flush)63 	public List<UnitNode> fetchP2UnitsFromRepo(String repo, boolean flush) {
64 		if ((flush) || (cache.get(repo) == null)) {
65 			List<UnitNode> units = P2Fetcher.fetchAvailableUnits(repo);
66 			cache.put(repo, units);
67 		}
68 		return cache.get(repo);
69 	}
70 
71 	/**
72 	 *
73 	 * Method used to narrow down proposals in case a prefix is provided.
74 	 * Example:
75 	 *
76 	 * <pre>
77 	 *  &ltunit id="org.^
78 	 * </pre>
79 	 *
80 	 * where ^ is an autocomplete call. Prefix in this case will be 'org.'
81 	 *
82 	 * @param repo
83 	 *            repository URL
84 	 * @param prefix
85 	 *            A prefix used to narrow down the match list
86 	 * @return A list of IUs whose id starts with 'prefix'
87 	 */
getUnitsByPrefix(String repo, String prefix)88 	public List<UnitNode> getUnitsByPrefix(String repo, String prefix) {
89 		List<UnitNode> allUnits = fetchP2UnitsFromRepo(repo, false);
90 		List<UnitNode> result = new ArrayList<>();
91 		for (UnitNode unit : allUnits) {
92 			if (unit.getId().startsWith(prefix)) {
93 				result.add(unit);
94 			}
95 		}
96 		return result;
97 	}
98 
99 	/**
100 	 *
101 	 * Method used to narrow down proposals in case a prefix is provided. Example:
102 	 *
103 	 * <pre>
104 	 *  &ltunit id="eclipse^
105 	 * </pre>
106 	 *
107 	 * where ^ is an autocomplete call. Search term in this case will be '*eclipse*'
108 	 *
109 	 * @param repo
110 	 *            repository URL
111 	 * @param searchTerm
112 	 *            A prefix used to narrow down the match list
113 	 * @return A list of IUs whose id contains 'searchTerm'
114 	 */
getUnitsBySearchTerm(String repo, String searchTerm)115 	public List<UnitNode> getUnitsBySearchTerm(String repo, String searchTerm) {
116 		List<UnitNode> allUnits = fetchP2UnitsFromRepo(repo, false);
117 		List<UnitNode> result = new ArrayList<>();
118 		for (UnitNode unit : allUnits) {
119 			if (unit.getId().contains(searchTerm)) {
120 				result.add(unit);
121 			}
122 		}
123 		return result;
124 	}
125 
126 	/**
127 	 * Classic cache up-to-date check.
128 	 *
129 	 * @param repo
130 	 *            repository URL
131 	 * @return whether the cache is up to date for this repo
132 	 */
isUpToDate(String repo)133 	public boolean isUpToDate(String repo) {
134 		return cache.get(repo) != null;
135 	}
136 
137 	/**
138 	 * Used to flush cache in case P2 repo information is considered stale.
139 	 */
flush()140 	public void flush() {
141 		cache.clear();
142 	}
143 }
144