Skip to content

Commit 45f21ca

Browse files
committed
migrate deprecated api, make cache collectable
1 parent 05b6830 commit 45f21ca

File tree

5 files changed

+174
-78
lines changed

5 files changed

+174
-78
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
version = 1.0.0
2-
ideaVersion = IC-2019.1
2+
ideaVersion = IC-2018.3
33
customUtilBuild = 194.*
44
isEAP = false
55
pluginChannels = nightly

src/main/java/com/chuntung/plugin/gistsnippet/dto/SnippetNodeDTO.java

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212
import javax.swing.*;
1313
import java.net.MalformedURLException;
1414
import java.net.URL;
15-
import java.util.ArrayList;
16-
import java.util.List;
17-
import java.util.Map;
15+
import java.util.*;
1816
import java.util.concurrent.ConcurrentHashMap;
1917
import java.util.regex.Matcher;
2018
import java.util.regex.Pattern;
@@ -165,12 +163,21 @@ private Icon findAvatar(String url) {
165163
@NotNull
166164
protected PresentationData createPresentation() {
167165
PresentationData presentation = new PresentationData();
166+
render(presentation);
167+
return presentation;
168+
}
169+
170+
@Override
171+
protected void update(PresentationData presentation) {
172+
render(presentation);
173+
}
168174

175+
private void render(PresentationData presentation) {
169176
if (ScopeEnum.OWN.equals(scope)) {
170-
setIcon(isPublic ? publicIcon : secretIcon);
177+
presentation.setIcon(isPublic ? publicIcon : secretIcon);
171178
} else {
172179
// refer to github plugin to lazy load avatar icon
173-
setIcon(isPublic ? publicIcon : secretIcon);
180+
presentation.setIcon(isPublic ? publicIcon : secretIcon);
174181
}
175182

176183
// Text format: tags TITLE Description n files
@@ -194,8 +201,6 @@ protected PresentationData createPresentation() {
194201
String activeAt = updatedAt != null ? updatedAt : createdAt;
195202
String tooltip = String.format("Last active at %s by %s", activeAt, owner.getLogin());
196203
presentation.setTooltip(tooltip);
197-
198-
return presentation;
199204
}
200205

201206
static SnippetNodeDTO of(GistDTO dto, ScopeEnum scope) {
@@ -210,7 +215,15 @@ static SnippetNodeDTO of(GistDTO dto, ScopeEnum scope) {
210215
node.setFilesCount(dto.getFiles().size());
211216
node.setFiles(new ArrayList<>(dto.getFiles().values()));
212217

218+
parseDescription(dto, node);
219+
220+
return node;
221+
}
222+
223+
private static void parseDescription(GistDTO dto, SnippetNodeDTO node) {
213224
if (dto.getDescription() == null || dto.getDescription().isEmpty()) {
225+
node.setTitle(null);
226+
node.setTags(null);
214227
// set description as first file name if empty
215228
for (GistFileDTO fileDTO : dto.getFiles().values()) {
216229
node.setDescription(fileDTO.getFilename());
@@ -238,7 +251,44 @@ static SnippetNodeDTO of(GistDTO dto, ScopeEnum scope) {
238251

239252
node.setDescription(txt.trim());
240253
}
254+
}
241255

242-
return node;
256+
public boolean update(GistDTO dto) {
257+
boolean updated = false;
258+
if (!Objects.equals(createdAt, dto.getCreatedAt()) || !Objects.equals(updatedAt, dto.getUpdatedAt())) {
259+
parseDescription(dto, this);
260+
261+
setPublic(dto.getPublic());
262+
setCreatedAt(dto.getCreatedAt());
263+
setUpdatedAt(dto.getUpdatedAt());
264+
265+
updated = true;
266+
}
267+
268+
// merge files
269+
setFilesCount(dto.getFiles().size());
270+
Set<String> children = new HashSet<>();
271+
// traverse tree structure to remove non-existing items
272+
Iterator<GistFileDTO> iterator = getFiles().iterator();
273+
while (iterator.hasNext()) {
274+
GistFileDTO fileDTO = iterator.next();
275+
if (dto.getFiles().containsKey(fileDTO.getFilename())) {
276+
fileDTO.setContent(dto.getFiles().get(fileDTO.getFilename()).getContent());
277+
children.add(fileDTO.getFilename());
278+
} else {
279+
updated = true;
280+
iterator.remove();
281+
}
282+
}
283+
284+
// traverse latest files to add missing items if gist changed
285+
for (GistFileDTO fileDTO : dto.getFiles().values()) {
286+
if (!children.contains(fileDTO.getFilename())) {
287+
updated = true;
288+
getFiles().add(fileDTO);
289+
}
290+
}
291+
292+
return updated;
243293
}
244294
}

src/main/java/com/chuntung/plugin/gistsnippet/service/GistSnippetService.java

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@
55
import com.intellij.openapi.components.ServiceManager;
66
import com.intellij.openapi.diagnostic.Logger;
77
import com.intellij.openapi.project.Project;
8+
import com.intellij.util.containers.ContainerUtil;
89
import org.jetbrains.plugins.github.api.GithubApiRequest;
910
import org.jetbrains.plugins.github.api.GithubApiRequestExecutor;
1011
import org.jetbrains.plugins.github.api.GithubApiRequestExecutorManager;
1112
import org.jetbrains.plugins.github.authentication.accounts.GithubAccount;
1213

13-
import javax.xml.bind.annotation.XmlTransient;
1414
import java.io.IOException;
15+
import java.util.ArrayList;
1516
import java.util.List;
1617
import java.util.Map;
17-
import java.util.concurrent.ConcurrentHashMap;
18+
import java.util.concurrent.atomic.AtomicReference;
1819

1920
public class GistSnippetService {
2021
public static final Logger logger = Logger.getInstance(GistSnippetService.class);
@@ -24,11 +25,9 @@ public class GistSnippetService {
2425
public static final String STARRED_GISTS_URL = "https://api.github.com/gists/starred";
2526
public static final String GIST_DETAIL_URL = "https://api.github.com/gists/%s";
2627

27-
// Just cache in memory
28-
@XmlTransient
29-
private Map<String, List<GistDTO>> scopeCache = new ConcurrentHashMap<>();
30-
@XmlTransient
31-
private Map<String, GistDTO> gistCache = new ConcurrentHashMap<>();
28+
// cache in memory, can be collected
29+
private Map<String, List<String>> scopeCache = ContainerUtil.createConcurrentSoftValueMap();
30+
private Map<String, GistDTO> gistCache = ContainerUtil.createConcurrentSoftValueMap();
3231

3332
public static GistSnippetService getInstance() {
3433
return ServiceManager.getService(GistSnippetService.class);
@@ -38,52 +37,85 @@ public static GistSnippetService getInstance() {
3837
public List<GistDTO> queryOwnGist(GithubAccount account, boolean forced) {
3938
String key = account.toString() + "#own";
4039
if (forced) {
41-
List<GistDTO> gistDTOS = scopeCache.computeIfPresent(key, (k, v) -> scopeCache.remove(k));
42-
if (gistDTOS != null) {
43-
for (GistDTO gistDTO : gistDTOS) {
44-
gistCache.remove(gistDTO.getId());
45-
}
46-
}
40+
List<String> gists = scopeCache.computeIfPresent(key, (k, v) -> scopeCache.remove(k));
41+
removeFromCache(gists);
4742
}
4843

49-
return scopeCache.computeIfAbsent(key, (k) -> {
44+
AtomicReference<List<GistDTO>> result = new AtomicReference<>();
45+
List<String> idList = scopeCache.computeIfAbsent(key, (k) -> {
5046
try {
5147
GithubApiRequest.Get.JsonList request = new GithubApiRequest.Get.JsonList(OWN_GISTS_URL, GistDTO.class, MIME_TYPE);
5248
GithubApiRequestExecutor executor = GithubApiRequestExecutorManager.getInstance().getExecutor(account);
53-
List<GistDTO> result = (List<GistDTO>) executor.execute(request);
54-
return result;
49+
List<GistDTO> gistList = (List<GistDTO>) executor.execute(request);
50+
result.set(gistList);
51+
return putIntoCache(gistList);
5552
} catch (IOException e) {
5653
logger.info("Failed to query own gist, error: " + e.getMessage());
5754
notifyWarn("Failed to load own Gist, " + e.getMessage(), null);
5855
return null;
5956
}
6057
});
58+
59+
return decideResult(account, result, idList);
60+
}
61+
62+
private void removeFromCache(List<String> gists) {
63+
if (gists != null) {
64+
for (String gistId : gists) {
65+
gistCache.remove(gistId);
66+
}
67+
}
68+
}
69+
70+
private List<String> putIntoCache(List<GistDTO> gistList) {
71+
if (gistList != null) {
72+
List<String> list = new ArrayList<>(gistList.size());
73+
for (GistDTO gistDTO : gistList) {
74+
list.add(gistDTO.getId());
75+
gistCache.putIfAbsent(gistDTO.getId(), gistDTO);
76+
}
77+
return list;
78+
}
79+
return null;
80+
}
81+
82+
private List<GistDTO> decideResult(GithubAccount account, AtomicReference<List<GistDTO>> result, List<String> idList) {
83+
if (result.get() == null && idList != null) {
84+
// N + 1
85+
List<GistDTO> gistList = new ArrayList<>(idList.size());
86+
for (String gistId : idList) {
87+
gistList.add(getGistDetail(account, gistId, false));
88+
}
89+
result.set(gistList);
90+
}
91+
92+
return result.get();
6193
}
6294

6395
// queryStarredGist
6496
public List<GistDTO> queryStarredGist(GithubAccount account, boolean forced) {
6597
String key = account.toString() + "#starred";
6698
if (forced) {
67-
List<GistDTO> gistDTOS = scopeCache.computeIfPresent(key, (k, v) -> scopeCache.remove(k));
68-
if (gistDTOS != null) {
69-
for (GistDTO gistDTO : gistDTOS) {
70-
gistCache.remove(gistDTO.getId());
71-
}
72-
}
99+
List<String> gists = scopeCache.computeIfPresent(key, (k, v) -> scopeCache.remove(k));
100+
removeFromCache(gists);
73101
}
74102

75-
return scopeCache.computeIfAbsent(key, (k) -> {
103+
AtomicReference<List<GistDTO>> result = new AtomicReference<>();
104+
List<String> list = scopeCache.computeIfAbsent(key, (k) -> {
76105
try {
77106
GithubApiRequest.Get.JsonList<GistDTO> request = new GithubApiRequest.Get.JsonList<>(STARRED_GISTS_URL, GistDTO.class, MIME_TYPE);
78107
GithubApiRequestExecutor executor = GithubApiRequestExecutorManager.getInstance().getExecutor(account);
79-
List<GistDTO> result = (List<GistDTO>) executor.execute(request);
80-
return result;
108+
List<GistDTO> gistList = (List<GistDTO>) executor.execute(request);
109+
result.set(gistList);
110+
return putIntoCache(gistList);
81111
} catch (IOException e) {
82112
logger.info("Failed to query starred gist, error: " + e.getMessage());
83113
notifyWarn("Failed to load starred Gist, " + e.getMessage(), null);
84114
return null;
85115
}
86116
});
117+
118+
return decideResult(account, result, list);
87119
}
88120

89121
// queryPublicGist

src/main/java/com/chuntung/plugin/gistsnippet/view/CustomDropDownLink.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.intellij.openapi.ui.popup.ListPopup;
55
import com.intellij.openapi.ui.popup.PopupStep;
66
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
7+
import com.intellij.ui.JBColor;
78
import com.intellij.ui.awt.RelativePoint;
89
import com.intellij.ui.components.JBComboBoxLabel;
910
import com.intellij.util.SmartList;
@@ -33,7 +34,8 @@ class CustomDropDownLink extends JBComboBoxLabel {
3334
this.icons.addAll(Arrays.asList(icons));
3435
}
3536

36-
setForeground(JBUI.CurrentTheme.Link.linkColor());
37+
// setForeground(JBColor.link());
38+
3739
addMouseListener(new MouseAdapter() {
3840
@Override
3941
public void mousePressed(MouseEvent e) {
@@ -93,6 +95,11 @@ public PopupStep onChosen(String selectedValue, boolean finalChoice) {
9395
public int getDefaultOptionIndex() {
9496
return items.indexOf(selectedItem);
9597
}
98+
99+
// @Override
100+
// public Color getForegroundFor(String val) {
101+
// return JBColor.link();
102+
// }
96103
};
97104

98105
final ListPopup popup = JBPopupFactory.getInstance().createListPopup(list);

0 commit comments

Comments
 (0)