package de.ovgu.cide.mining.database.recommendationengine.substrings;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.ovgu.cide.features.IFeature;
import de.ovgu.cide.mining.database.model.AElement;
import de.ovgu.cide.mining.database.model.AICategories;
import de.ovgu.cide.mining.database.recommendationengine.AAbstractElementRecommender;
import de.ovgu.cide.mining.database.recommendationengine.ARecommendationContext;
public class SubStringElementRecommender extends AAbstractElementRecommender {
private static final double TRESHOLD = 0.05;
private static final double ATTENUATOR = 0.1;
private static final AICategories[] primaryElement = new AICategories[] {
AICategories.TYPE, AICategories.METHOD, AICategories.FIELD,
AICategories.LOCAL_VARIABLE };
Map<AElement, Map<AElement, ARecommendationContext>> cache;
public SubStringElementRecommender() {
super();
cache = new HashMap<AElement, Map<AElement, ARecommendationContext>>();
}
@Override
public String getRecommendationType() {
return "TPE";
}
private boolean isPrimaryElement(AElement element) {
for (int i = 0; i < primaryElement.length; i++) {
if (primaryElement[i] == element.getCategory())
return true;
}
return false;
}
private int matchCount(String source, String substring) {
if (source == null || source.isEmpty() || substring == null
|| substring.isEmpty())
return 0;
int count = 0;
for (int pos = 0; (pos = source.indexOf(substring, pos)) != -1; count++)
pos += substring.length();
return count;
}
private List<String> getSubStrings(String source) {
List<String> substrings = new ArrayList<String>();
String curSubString = "";
char curChar;
boolean curUpper, lastUpper = false;
int changer = 1;
for (int i = 0; i < source.length(); i++) {
curChar = source.charAt(i);
curUpper = Character.isUpperCase(curChar);
if (lastUpper != curUpper && i > changer) {
substrings.add(curSubString.toUpperCase());
changer = i + 1;
curSubString = "";
}
if (Character.isLetter(curChar))
curSubString += curChar;
lastUpper = curUpper;
}
// add last element
substrings.add(curSubString.toUpperCase());
return substrings;
}
private String removeNamingConvention(String source) {
String[] filter = source.split(":");
// filter naming convention for elements
if (filter.length == 2)
source = filter[1].substring(1);
return source;
}
public Map<AElement, ARecommendationContext> getRecommendations(
AElement element, IFeature color) {
Map<AElement, ARecommendationContext> recommendations;
if (cache.containsKey(element)) {
recommendations = cache.get(element);
if (recommendations != null)
return filterValidRecommendations(color, recommendations);
return new HashMap<AElement, ARecommendationContext>();
}
// mark element as handled
cache.put(element, null);
recommendations = new HashMap<AElement, ARecommendationContext>();
if (!isPrimaryElement(element))
return recommendations;
String source = removeNamingConvention(element.getShortName());
List<String> subStrings = getSubStrings(source);
for (AElement curElement : AC.getAllElements()) {
// do not check with itself
if (curElement.equals(element))
continue;
// check only primary elements
if (!isPrimaryElement(curElement))
continue;
String targetString = removeNamingConvention(
curElement.getShortName()).toUpperCase();
int matchChars = 0;
for (String subString : subStrings) {
matchChars += matchCount(targetString, subString)
* subString.length();
}
double support = (double) matchChars
/ (double) targetString.length() * ATTENUATOR
* (double) matchChars;
if (support > 1)
support = 1;
if (support >= TRESHOLD) {
ARecommendationContext context = new ARecommendationContext(
element, "Text Match", getRecommendationType(), support);
recommendations.put(curElement, context);
}
}
// CHECK IF RECOMMENDATION IS ALREADY IN COLOR!
// cache results for element
if (recommendations.size() > 0) {
cache.put(element, recommendations);
}
return filterValidRecommendations(color, recommendations);
}
}