1 package edu.jiangxin.apktoolbox.android.i18n;
2
3 import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
4 import edu.jiangxin.apktoolbox.swing.extend.listener.SelectDirectoryListener;
5 import edu.jiangxin.apktoolbox.utils.Constants;
6 import org.apache.commons.collections4.CollectionUtils;
7 import org.apache.commons.lang3.StringUtils;
8 import org.jdom2.Document;
9 import org.jdom2.Element;
10 import org.jdom2.JDOMException;
11 import org.jdom2.input.SAXBuilder;
12
13 import javax.swing.*;
14 import java.awt.*;
15 import java.awt.event.ActionEvent;
16 import java.awt.event.ActionListener;
17 import java.io.File;
18 import java.io.FileFilter;
19 import java.io.IOException;
20 import java.io.Serial;
21 import java.util.ArrayList;
22 import java.util.List;
23
24
25
26
27
28
29 public class I18nFindLongestPanel extends EasyPanel {
30 @Serial
31 private static final long serialVersionUID = 1L;
32
33 private final transient List<I18nInfo> infos = new ArrayList<>();
34
35 private JTextField srcTextField;
36
37 private JTextField itemTextField;
38
39 public I18nFindLongestPanel() throws HeadlessException {
40 super();
41 }
42
43 @Override
44 public void initUI() {
45 BoxLayout boxLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
46 setLayout(boxLayout);
47
48 createSourcePanel();
49 add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
50 createItemPanel();
51 add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
52 createOperationPanel();
53 }
54
55 private void createOperationPanel() {
56 JPanel operationPanel = new JPanel();
57 operationPanel.setLayout(new BoxLayout(operationPanel, BoxLayout.X_AXIS));
58 add(operationPanel);
59
60 JButton findButton = new JButton(bundle.getString("android.i18n.longest.find"));
61 findButton.addActionListener(new ActionListener() {
62 @Override
63 public void actionPerformed(ActionEvent e) {
64 infos.clear();
65
66 String srcPath = checkAndGetDirContent(srcTextField, "android.i18n.longest.src.dir", "Source directory is invalid");
67 if (StringUtils.isEmpty(srcPath)) {
68 return;
69 }
70
71 String item = checkAndGetStringContent(itemTextField, "android.i18n.longest.items", "Item is empty");
72 if (StringUtils.isEmpty(item)) {
73 return;
74 }
75
76 sort(srcPath, itemTextField.getText());
77 if (CollectionUtils.isEmpty(infos)) {
78 Toolkit.getDefaultToolkit().beep();
79 JOptionPane.showMessageDialog(I18nFindLongestPanel.this, "Failed, please see the log", "ERROR",
80 JOptionPane.ERROR_MESSAGE);
81 } else {
82 I18nInfo info = infos.get(0);
83 StringBuilder sb = new StringBuilder();
84 sb.append("length: ").append(info.length).append(System.lineSeparator())
85 .append("text: ").append(info.text).append(System.lineSeparator())
86 .append("path: ").append(info.path);
87 Toolkit.getDefaultToolkit().beep();
88 JOptionPane.showMessageDialog(I18nFindLongestPanel.this, sb.toString(), "INFO",
89 JOptionPane.INFORMATION_MESSAGE);
90 }
91
92 }
93 });
94
95 operationPanel.add(findButton);
96 }
97
98 private void createItemPanel() {
99 JPanel itemPanel = new JPanel();
100 itemPanel.setLayout(new BoxLayout(itemPanel, BoxLayout.X_AXIS));
101 add(itemPanel);
102
103 itemTextField = new JTextField();
104 itemTextField.setText(conf.getString("android.i18n.longest.items"));
105
106 JLabel itemLabel = new JLabel("Items");
107
108 itemPanel.add(itemTextField);
109 itemPanel.add(Box.createHorizontalGlue());
110 itemPanel.add(itemLabel);
111 }
112
113 private void createSourcePanel() {
114 JPanel sourcePanel = new JPanel();
115 sourcePanel.setLayout(new BoxLayout(sourcePanel, BoxLayout.X_AXIS));
116 add(sourcePanel);
117
118 srcTextField = new JTextField();
119 srcTextField.setText(conf.getString("android.i18n.longest.src.dir"));
120
121 JButton srcButton = new JButton("Source Directory");
122 srcButton.addActionListener(new SelectDirectoryListener("select a directory", srcTextField));
123
124 sourcePanel.add(srcTextField);
125 sourcePanel.add(Box.createHorizontalGlue());
126 sourcePanel.add(srcButton);
127 }
128
129 private String getCanonicalPath(File file) {
130 if (file == null) {
131 logger.error("file is null");
132 return null;
133 }
134 try {
135 return file.getCanonicalPath();
136 } catch (IOException e) {
137 logger.error("getCanonicalPath failed: {}", file.getAbsolutePath());
138 return null;
139 }
140 }
141
142 private void sort(String sourceBaseStr, String itemName) {
143 File[] sourceParentFiles = new File(sourceBaseStr).listFiles(new FileFilter() {
144 @Override
145 public boolean accept(File pathname) {
146 return pathname.getName().startsWith("values");
147 }
148 });
149 if (sourceParentFiles == null) {
150 logger.error("None valid directory found");
151 return;
152 }
153 for (File sourceParentFile : sourceParentFiles) {
154 File sourceFile = new File(sourceParentFile, "strings.xml");
155 if (sourceFile.exists()) {
156 SAXBuilder builder = new SAXBuilder();
157 Document sourceDoc;
158 try {
159 sourceDoc = builder.build(sourceFile);
160 } catch (JDOMException | IOException e) {
161 logger.error("build failed: {}", sourceFile);
162 continue;
163 }
164 Element sourceRoot = sourceDoc.getRootElement();
165 for (Element child : sourceRoot.getChildren()) {
166 String value = child.getAttributeValue("name");
167 if (value != null && value.equals(itemName)) {
168 String text = child.getText();
169 if (text != null) {
170 I18nInfo info = new I18nInfo(getCanonicalPath(sourceFile), text, text.length());
171 infos.add(info);
172 break;
173 }
174 }
175 }
176
177 }
178
179 }
180 infos.sort((o1, o2) -> o2.length - o1.length);
181
182 logger.info(infos);
183 }
184
185 static class I18nInfo {
186 String path;
187 String text;
188 int length;
189
190 public I18nInfo(String path, String text, int length) {
191 this.path = path;
192 this.text = text;
193 this.length = length;
194 }
195
196 @Override
197 public String toString() {
198 return "I18NInfo [path=" + path + ", text=" + text + ", length=" + length + "]";
199 }
200 }
201 }