EMMA Coverage Report (generated Sat Oct 08 11:41:37 CEST 2011)
[all classes][net.sf.jomic.tools]

COVERAGE SUMMARY FOR SOURCE FILE [NumberedName.java]

nameclass, %method, %block, %line, %
NumberedName.java100% (1/1)100% (10/10)88%  (413/469)94%  (80.7/86)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class NumberedName100% (1/1)100% (10/10)88%  (413/469)94%  (80.7/86)
getName (boolean): String 100% (1/1)75%  (52/69)91%  (8.2/9)
<static initializer> 100% (1/1)80%  (12/15)80%  (0.8/1)
NumberedName (String): void 100% (1/1)90%  (321/357)94%  (64.7/69)
getFullName (): String 100% (1/1)100% (3/3)100% (1/1)
getPage (): String 100% (1/1)100% (3/3)100% (1/1)
getPath (): String 100% (1/1)100% (3/3)100% (1/1)
getPrefix (): String 100% (1/1)100% (3/3)100% (1/1)
getSuffix (): String 100% (1/1)100% (3/3)100% (1/1)
numbersAreNeightbors (int, int): boolean 100% (1/1)100% (10/10)100% (1/1)
usesPotentiallyMoronicNumbering (): boolean 100% (1/1)100% (3/3)100% (1/1)

1// Jomic - a viewer for comic book archives.
2// Copyright (C) 2004-2011 Thomas Aglassinger
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16package net.sf.jomic.tools;
17 
18 
19/**
20 *  Representation of a name with a optional path, prefix, number and suffix. Examples:
21 *  <ul>
22 *    <li> "images/hugo12.png" splits to path="images/", prefix="hugo", page="12", suffix=".png"
23 *    </li>
24 *    <li> "images/hugo00title.png" splits to path="images/", prefix="hugo00title", page="",
25 *    suffix=".png".</li>
26 *    <li> "images/hugo12-13.png" splits to path="images/", prefix="hugo", page="12-13",
27 *    suffix=".png".</li>
28 *  </ul>
29 *
30 *
31 * @author    Thomas Aglassinger
32 */
33public class NumberedName
34{
35    /**
36     *  Possible separators for double pages.
37     */
38    public static final String DOUBLE_PAGE_SEPARATORS = "+-_";
39    public static final String PATH_SEPARATORS = "/\\";
40    private static final int MORONIC_DOUBLE_PAGE_LENGTH = 4;
41    private static final int MORONIC_SINGLE_PAGE_LENGTH = 2;
42 
43    private String fullName;
44    private String page;
45    private String path;
46    private String prefix;
47    private String suffix;
48    private boolean usesPotentiallyMoronicNumbering;
49 
50    public NumberedName(String newFullName) {
51        assert newFullName != null;
52        LocaleTools localeTools = LocaleTools.instance();
53 
54        fullName = newFullName;
55 
56        int lastIndex = fullName.length() - 1;
57 
58        // Find the path.
59        int pathIndex = -1;
60 
61        for (int i = 0; i < PATH_SEPARATORS.length(); i += 1) {
62            int index = fullName.lastIndexOf(PATH_SEPARATORS.charAt(i));
63 
64            if (index > pathIndex) {
65                pathIndex = index;
66            }
67        }
68        if (pathIndex == -1) {
69            path = "";
70        } else {
71            assert pathIndex >= 0;
72            if (pathIndex == lastIndex) {
73                String message = localeTools.getMessage(
74                        "errors.fileNameMustNotEndWithPathSeperator", fullName);
75 
76                throw new IllegalArgumentException(message);
77            }
78            path = fullName.substring(0, pathIndex + 1);
79            assert PATH_SEPARATORS.indexOf(path.charAt(path.length() - 1)) != -1;
80        }
81 
82        String name = fullName.substring(pathIndex + 1, lastIndex + 1);
83        int dotIndex = name.lastIndexOf('.');
84 
85        lastIndex = name.length() - 1;
86        if (dotIndex == -1) {
87            // Check that the file name contains a dot to seperate the suffix.
88            // This is not really a requirement, but simplifies parsing and in
89            // practice is ensured by the fact that images extracted from the
90            // archive must have a suffix to be recognized as images at all.
91            String message = localeTools.getMessage(
92                    "errors.fileNameMustHaveSuffix", name);
93 
94            throw new IllegalArgumentException(message);
95        } else if (dotIndex == 0) {
96            // The whole name is the suffix; silly, but possible.
97            prefix = "";
98            page = "";
99            suffix = name;
100        } else {
101            assert dotIndex > 0;
102            suffix = name.substring(dotIndex, lastIndex + 1);
103 
104            int pageEndIndex = dotIndex - 1;
105            int pageStartIndex;
106 
107            // Extract page number.
108            StringTools stringTools = StringTools.instance();
109 
110            page = stringTools.extractNumberBackwards(name, pageEndIndex);
111            pageStartIndex = pageEndIndex - page.length() + 1;
112 
113            // Extract second page number.
114            if ((page.length() > 0) && (pageStartIndex > 0)) {
115                char charBeforePage = name.charAt(pageStartIndex - 1);
116 
117                if (DOUBLE_PAGE_SEPARATORS.indexOf(charBeforePage) >= 0) {
118                    String leftPage = stringTools.extractNumberBackwards(name, pageStartIndex - 2);
119 
120                    int leftLength = leftPage.length();
121                    int rightLength = page.length();
122 
123                    if ((leftLength > 0) && (rightLength == leftLength)) {
124                        int rightNumber = Integer.parseInt(page);
125                        int leftNumber = Integer.parseInt(leftPage);
126 
127                        if (numbersAreNeightbors(leftNumber, rightNumber)) {
128                            page = leftPage + charBeforePage + page;
129                            pageStartIndex = pageEndIndex - page.length() + 1;
130                        }
131                    }
132                }
133            }
134 
135            prefix = name.substring(0, pageStartIndex);
136        }
137 
138        // Check for moronic numbering.
139        int pageLength = page.length();
140 
141        if ((pageLength == MORONIC_SINGLE_PAGE_LENGTH) || (pageLength == MORONIC_DOUBLE_PAGE_LENGTH)) {
142            int i = 0;
143 
144            usesPotentiallyMoronicNumbering = true;
145            while (usesPotentiallyMoronicNumbering && (i < pageLength)) {
146                char ch = page.charAt(i);
147 
148                if (!Character.isDigit(ch)) {
149                    usesPotentiallyMoronicNumbering = false;
150                } else {
151                    i += 1;
152                }
153            }
154            if (usesPotentiallyMoronicNumbering && (pageLength == MORONIC_DOUBLE_PAGE_LENGTH)) {
155                // Check that two pages are consecutive, for example 0304 but not 0305.
156                String leftPage = page.substring(0, MORONIC_SINGLE_PAGE_LENGTH);
157                String rightPage = page.substring(MORONIC_SINGLE_PAGE_LENGTH, MORONIC_DOUBLE_PAGE_LENGTH);
158                int leftNumber = Integer.parseInt(leftPage);
159                int rightNumber = Integer.parseInt(rightPage);
160 
161                if (!numbersAreNeightbors(leftNumber, rightNumber)) {
162                    usesPotentiallyMoronicNumbering = false;
163                }
164            }
165        }
166 
167        assert path != null;
168        assert prefix != null;
169        assert page != null;
170        assert suffix != null;
171    }
172 
173    /**
174     *  Get theoriginal full name.
175     */
176    public String getFullName() {
177        return fullName;
178    }
179 
180    /**
181     *  Get the name (without the path).
182     *
183     * @param  demoronized  if true, page numbers like "1718" are converted to "17+18".
184     */
185    public String getName(boolean demoronized) {
186        if (demoronized) {
187            assert usesPotentiallyMoronicNumbering
188                    : "demoronized=" + demoronized
189                    + ", usesPotentiallyMoronicNumbering" + usesPotentiallyMoronicNumbering;
190        }
191        String result;
192        String pageNumbers = getPage();
193 
194        if (demoronized && pageNumbers.length() == MORONIC_DOUBLE_PAGE_LENGTH) {
195            String leftPage = pageNumbers.substring(0, MORONIC_SINGLE_PAGE_LENGTH);
196            String rightPage = pageNumbers.substring(MORONIC_SINGLE_PAGE_LENGTH, MORONIC_DOUBLE_PAGE_LENGTH);
197 
198            pageNumbers = leftPage + "+" + rightPage;
199        }
200        result = prefix + pageNumbers + suffix;
201        return result;
202    }
203 
204    /**
205     *  Get the page of the name. Example: "path/name0023.png" yields "0023".
206     */
207    public String getPage() {
208        return page;
209    }
210 
211    /**
212     *  Get the path of the name. Example: "path/name0023.png" yields "path/".
213     */
214    public String getPath() {
215        return path;
216    }
217 
218    /**
219     *  Get the prefix before the page of the name. Example: "path/name0023.png" yields "name".
220     */
221    public String getPrefix() {
222        return prefix;
223    }
224 
225    /**
226     *  Get the suffix after the page of the name. Example: "path/name0023.png" yields ".png".
227     */
228    public String getSuffix() {
229        return suffix;
230    }
231 
232    public boolean usesPotentiallyMoronicNumbering() {
233        return usesPotentiallyMoronicNumbering;
234    }
235 
236    private boolean numbersAreNeightbors(int leftNumber, int rightNumber) {
237        return Math.abs(leftNumber - rightNumber) == 1;
238    }
239}

[all classes][net.sf.jomic.tools]
EMMA 2.0.4217 (C) Vladimir Roubtsov