blob: b70e1d20470dbe4b9c4a55026a2a7deb0ed8c6ed [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
package org.jacoco.report.internal;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
/**
* Internal utility to create normalized file names from string ids. The file
* names generated by an instance of this class have the following properties:
*
* <ul>
* <li>The same input id is mapped to the same file name.</li>
* <li>Different ids are mapped to different file names.</li>
* <li>For safe characters the file name corresponds to the input id, other
* characters are replaced by <code>_</code> (underscore).</li>
* <li>File names are case aware, i.e. the same file name but with different
* upper/lower case characters is not possible.</li>
* <li>If unique filenames can't directly created from the ids, additional
* suffixes are appended.</li>
* </ul>
*/
class NormalizedFileNames {
private static final BitSet LEGAL_CHARS = new BitSet();
static {
final String legal = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWYXZ0123456789$-._";
for (final char c : legal.toCharArray()) {
LEGAL_CHARS.set(c);
}
}
private final Map<String, String> mapping = new HashMap<String, String>();
private final Set<String> usedNames = new HashSet<String>();
public String getFileName(final String id) {
String name = mapping.get(id);
if (name != null) {
return name;
}
name = replaceIllegalChars(id);
name = ensureUniqueness(name);
mapping.put(id, name);
return name;
}
private String replaceIllegalChars(final String s) {
final StringBuilder sb = new StringBuilder(s.length());
boolean modified = false;
for (int i = 0; i < s.length(); i++) {
final char c = s.charAt(i);
if (LEGAL_CHARS.get(c)) {
sb.append(c);
} else {
sb.append('_');
modified = true;
}
}
return modified ? sb.toString() : s;
}
private String ensureUniqueness(final String s) {
String unique = s;
String lower = unique.toLowerCase(Locale.ENGLISH);
int idx = 1;
while (usedNames.contains(lower)) {
unique = s + '~' + idx++;
lower = unique.toLowerCase(Locale.ENGLISH);
}
usedNames.add(lower);
return unique;
}
}