• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jiangxincode / ApkToolBoxGUI / #831

28 Aug 2024 02:56PM UTC coverage: 3.138% (-0.002%) from 3.14%
#831

push

jiangxincode
fix #17: add finish dialog for i18n tool

0 of 42 new or added lines in 3 files covered. (0.0%)

2 existing lines in 1 file now uncovered.

236 of 7520 relevant lines covered (3.14%)

0.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/edu/jiangxin/apktoolbox/android/i18n/I18nAddPanel.java
1
/**
2
 * 
3
 */
4
package edu.jiangxin.apktoolbox.android.i18n;
5

6
import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
7
import edu.jiangxin.apktoolbox.swing.extend.listener.SelectDirectoryListener;
8
import edu.jiangxin.apktoolbox.utils.Constants;
9
import org.apache.commons.collections4.map.HashedMap;
10
import org.apache.commons.io.FileUtils;
11
import org.apache.commons.lang3.StringUtils;
12
import org.jdom2.Document;
13
import org.jdom2.Element;
14
import org.jdom2.JDOMException;
15
import org.jdom2.input.SAXBuilder;
16
import org.jdom2.output.Format;
17
import org.jdom2.output.XMLOutputter;
18

19
import javax.swing.*;
20
import java.awt.*;
21
import java.io.*;
22
import java.util.ArrayList;
23
import java.util.Arrays;
24
import java.util.List;
25
import java.util.Map;
26

27
/**
28
 * @author jiangxin
29
 * @author 2019-04-12
30
 *
31
 */
32
public class I18nAddPanel extends EasyPanel {
33
    
34
    @Serial
35
    private static final long serialVersionUID = 1L;
36
    
37
    private static final String CHARSET = "UTF-8";
38

39
    private static final boolean REMOVE_LAST_LF_OPEN = true;
40

NEW
41
    private static final Map<String, String> replace = new HashedMap<>();
×
42

43
    private JTextField srcTextField;
44

45
    private JTextField targetTextField;
46

47
    private JTextField itemTextField;
48

NEW
49
    private int operationCount = 0;
×
50

51
    static {
52
        replace.put("&quot;", "jiangxin001");
×
53
        replace.put("&#160;", "jiangxin002");
×
54
    }
×
55
    
56
    public I18nAddPanel() throws HeadlessException {
57
        super();
×
58
    }
×
59

60
    @Override
61
    public void initUI() {
62
        BoxLayout boxLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
×
63
        setLayout(boxLayout);
×
64

65
        createSourcePanel();
×
66
        add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
67
        createTargetPanel();
×
68
        add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
69
        createItemPanel();
×
70
        add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
71
        createOperationPanel();
×
72
    }
×
73

74
    private void createOperationPanel() {
75
        JPanel operationPanel = new JPanel();
×
76
        operationPanel.setLayout(new BoxLayout(operationPanel, BoxLayout.X_AXIS));
×
77
        add(operationPanel);
×
78

79
        JButton addButton = new JButton(bundle.getString("android.i18n.add.title"));
×
NEW
80
        addButton.addActionListener(e -> {
×
NEW
81
            String srcPath = checkAndGetDirContent(srcTextField, "android.i18n.add.src.dir", "Source directory is invalid");
×
NEW
82
            if (srcPath == null) {
×
NEW
83
                return;
×
84
            }
85

NEW
86
            String targetPath = checkAndGetDirContent(targetTextField, "android.i18n.add.target.dir", "Target directory is invalid");
×
NEW
87
            if (targetPath == null) {
×
NEW
88
                return;
×
89
            }
90

NEW
91
            String itemStr = checkAndGetStringContent(itemTextField, "android.i18n.add.items", "Items is empty");
×
NEW
92
            if (itemStr == null) {
×
NEW
93
                return;
×
94
            }
95

NEW
96
            List<String> items = new ArrayList<>(Arrays.asList(itemStr.split(";")));
×
NEW
97
            operationCount = 0;
×
98

NEW
99
            for (String item : items) {
×
NEW
100
                int ret = innerProcessor(srcPath, targetPath, item);
×
NEW
101
                if (ret != 0) {
×
NEW
102
                    Toolkit.getDefaultToolkit().beep();
×
NEW
103
                    JOptionPane.showMessageDialog(I18nAddPanel.this, "Failed, please see the log", "ERROR",
×
104
                            JOptionPane.ERROR_MESSAGE);
NEW
105
                    return;
×
106
                }
107
            }
×
NEW
108
            String message = String.format("Success: items: %d", operationCount);
×
NEW
109
            JOptionPane.showMessageDialog(I18nAddPanel.this, message, "INFO", JOptionPane.INFORMATION_MESSAGE);
×
UNCOV
110
        });
×
111

112
        operationPanel.add(addButton);
×
113
    }
×
114

115
    private void createItemPanel() {
116
        JPanel itemPanel = new JPanel();
×
117
        itemPanel.setLayout(new BoxLayout(itemPanel, BoxLayout.X_AXIS));
×
118
        add(itemPanel);
×
119
        
120
        itemTextField = new JTextField();
×
121
        itemTextField.setText(conf.getString("android.i18n.add.items"));
×
122

123
        JLabel itemLabel = new JLabel("Items");
×
124

125
        itemPanel.add(itemTextField);
×
126
        itemPanel.add(Box.createHorizontalGlue());
×
127
        itemPanel.add(itemLabel);
×
128
    }
×
129

130
    private void createTargetPanel() {
131
        JPanel targetPanel = new JPanel();
×
132
        targetPanel.setLayout(new BoxLayout(targetPanel, BoxLayout.X_AXIS));
×
133
        add(targetPanel);
×
134
        
135
        targetTextField = new JTextField();
×
136
        targetTextField.setText(conf.getString("android.i18n.add.target.dir"));
×
137

138
        JButton targetButton = new JButton("Save Directory");
×
139
        targetButton.addActionListener(new SelectDirectoryListener("save to", targetTextField));
×
140

141
        targetPanel.add(targetTextField);
×
142
        targetPanel.add(Box.createHorizontalGlue());
×
143
        targetPanel.add(targetButton);
×
144
    }
×
145

146
    private void createSourcePanel() {
147
        JPanel sourcePanel = new JPanel();
×
148
        sourcePanel.setLayout(new BoxLayout(sourcePanel, BoxLayout.X_AXIS));
×
149
        add(sourcePanel);
×
150
        
151
        srcTextField = new JTextField();
×
152
        srcTextField.setText(conf.getString("android.i18n.add.src.dir"));
×
153

154
        JButton srcButton = new JButton("Source Directory");
×
155
        srcButton.addActionListener(new SelectDirectoryListener("select a directory", srcTextField));
×
156

157
        sourcePanel.add(srcTextField);
×
158
        sourcePanel.add(Box.createHorizontalGlue());
×
159
        sourcePanel.add(srcButton);
×
160
    }
×
161

162
    private int innerProcessor(String sourceBaseStr, String targetBaseStr, String itemName) {
163
        if (StringUtils.isAnyEmpty(sourceBaseStr, targetBaseStr, itemName)) {
×
NEW
164
            logger.error("params are invalid: sourceBaseStr: {}, targetBaseStr: {}, itemName: {}", sourceBaseStr, targetBaseStr, itemName);
×
UNCOV
165
            return -1;
×
166
        }
167
        File sourceBaseFile = new File(sourceBaseStr);
×
168
        File targetBaseFile = new File(targetBaseStr);
×
169
        int count = 0;
×
170

171
        File[] sourceParentFiles = sourceBaseFile.listFiles(new FileFilter() {
×
172
            @Override
173
            public boolean accept(File pathname) {
174
                return pathname.getName().startsWith("values");
×
175
            }
176
        });
177
        if (sourceParentFiles == null) {
×
178
            logger.error("sourceParentFiles is null");
×
179
            return -1;
×
180
        }
181
        for (File sourceParentFile : sourceParentFiles) {
×
182
            File sourceFile = new File(sourceParentFile, "strings.xml");
×
183

184
            Element sourceElement = getSourceElement(sourceFile, itemName);
×
185
            if (sourceElement == null) {
×
NEW
186
                logger.warn("sourceElement is null: {}", sourceFile);
×
187
                continue;
×
188
            }
189

190
            File targetFile = new File(new File(targetBaseFile, sourceParentFile.getName()), "strings.xml");
×
191
            if (!targetFile.exists()) {
×
NEW
192
                logger.warn("targetFile does not exist: {}", sourceFile);
×
193
                continue;
×
194
            }
195
            try {
NEW
196
                preProcess(targetFile);
×
197
            } catch (IOException e) {
×
NEW
198
                logger.error("preProcess failed.", e);
×
199
                return -1;
×
200
            }
×
201
            boolean res = setTargetElement(targetFile, sourceElement, itemName);
×
202
            if (!res) {
×
203
                logger.error("setTargetElement failed.");
×
204
                return -1;
×
205
            }
206
            try {
207
                postProcess(targetFile);
×
208
            } catch (IOException e) {
×
209
                logger.error("postProcess failed.", e);
×
210
                return -1;
×
211
            }
×
NEW
212
            logger.info("count: {}, in path: {}, out path: {}", ++count, sourceFile, targetFile);
×
213
        }
NEW
214
        operationCount += count;
×
215
        logger.info("finish one cycle");
×
216
        return 0;
×
217
    }
218

219
    private Element getSourceElement(File sourceFile, String itemName) {
220
        if (!sourceFile.exists()) {
×
NEW
221
            logger.warn("sourceFile does not exist: {}", sourceFile);
×
222
            return null;
×
223
        }
224
        SAXBuilder builder = new SAXBuilder();
×
225
        Document sourceDoc = null;
×
226
        try (InputStream in = new FileInputStream(sourceFile)) {
×
227
            sourceDoc = builder.build(in);
×
NEW
228
            logger.info("build source document: {}", sourceFile);
×
229
        } catch (JDOMException | IOException e) {
×
NEW
230
            logger.error("build source document failed: {}", sourceFile);
×
231
            return null;
×
232
        }
×
233
        if (sourceDoc == null) {
×
234
            logger.error("sourceDoc is null");
×
235
            return null;
×
236
        }
237
        Element sourceElement = null;
×
238
        for (Element sourceChild : sourceDoc.getRootElement().getChildren()) {
×
239
            String sourceValue = sourceChild.getAttributeValue("name");
×
240
            if (sourceValue != null && sourceValue.equals(itemName)) {
×
241
                sourceElement = sourceChild.clone();
×
242
                break;
×
243
            }
244
        }
×
245
        return sourceElement;
×
246
    }
247

248
    private boolean setTargetElement(File targetFile, Element sourceElement, String itemName) {
249
        SAXBuilder builder = new SAXBuilder();
×
250
        Document targetDoc;
251
        try {
252
            targetDoc = builder.build(targetFile);
×
NEW
253
            logger.info("build target document: {}", targetFile);
×
254
        } catch (JDOMException | IOException e) {
×
NEW
255
            logger.error("build target document failed: {}", targetFile);
×
256
            return false;
×
257
        }
×
258
        Element targetRoot = targetDoc.getRootElement();
×
259
        boolean isFinished = false;
×
260
        for (Element targetChild : targetRoot.getChildren()) {
×
261
            String targetValue = targetChild.getAttributeValue("name");
×
262
            if (targetValue != null && targetValue.equals(itemName)) {
×
263
                targetChild.setText(sourceElement.getText());
×
264
                isFinished = true;
×
265
                break;
×
266
            }
267
        }
×
268
        if (!isFinished) {
×
269
            targetRoot.addContent("    ");
×
270
            targetRoot.addContent(sourceElement);
×
271
            targetRoot.addContent("\n");
×
272
        }
273
        XMLOutputter out = new XMLOutputter();
×
274
        Format format = Format.getRawFormat();
×
275
        format.setEncoding("UTF-8");
×
276
        format.setLineSeparator("\n");
×
277
        out.setFormat(format);
×
278
        OutputStream os = null;
×
279
        try {
280
            os = new FileOutputStream(targetFile);
×
281
            out.output(targetDoc, os);
×
282
        } catch (IOException e) {
×
283
            logger.error("output fail", e);
×
284
            return false;
×
285
        } finally {
286
            if (os != null) {
×
287
                try {
288
                    os.close();
×
289
                } catch (IOException e) {
×
290
                    logger.error("close output stream exception", e);
×
291
                }
×
292
            }
293
        }
294
        return true;
×
295
    }
296

297
    private static void preProcess(File file) throws IOException {
298
        String content = FileUtils.readFileToString(file, CHARSET);
×
299
        for (Map.Entry<String, String> entry : replace.entrySet()) {
×
300
            content = content.replaceAll(entry.getKey(), entry.getValue());
×
301
        }
×
302
        FileUtils.writeStringToFile(file, content, CHARSET);
×
303
    }
×
304

305
    private static void postProcess(File file) throws IOException {
306
        String content = FileUtils.readFileToString(file, CHARSET);
×
307
        for (Map.Entry<String, String> entry : replace.entrySet()) {
×
308
            content = content.replaceAll(entry.getValue(), entry.getKey());
×
309
        }
×
310
        if (REMOVE_LAST_LF_OPEN) {
311
            content = StringUtils.removeEnd(content, "\n");
×
312
        }
313
        FileUtils.writeStringToFile(file, content, CHARSET);
×
314
    }
×
315

316
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc