Java tutorial
/** * Copyright 2011 Nikolche Mihajlovski * * This file is part of JAnnocessor. * * JAnnocessor is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JAnnocessor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with JAnnocessor. If not, see <http://www.gnu.org/licenses/>. */ package org.jannocessor.service.imports; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.jannocessor.service.api.ImportOrganizer; public class ImportOrganizerImpl implements ImportOrganizer { private static final String JAVA_LANG = "java.lang."; private Set<String> importedSimple = new HashSet<String>(); private Set<String> importedFull = new HashSet<String>(); @Override public String[] getTypeImports(String type) { List<String> imports = new ArrayList<String>(); calculateTypeImports(type, imports); return imports.toArray(new String[imports.size()]); } private void calculateTypeImports(String type, List<String> imports) { ParsedTypeName parsedName = parseType(type); String simpleName = parsedName.getClassName(); String genericType = parsedName.getGenericType(); if (!parsedName.isSimple() && !genericType.startsWith(JAVA_LANG)) { if (!importedSimple.contains(simpleName)) { importedSimple.add(simpleName); importedFull.add(genericType); imports.add(genericType); } } for (ParsedTypeNameParam generic : parsedName.getParams()) { calculateTypeImports(generic.getType(), imports); } } @Override public String getTypeUsage(String type) { ParsedTypeName parsedName = parseType(type); String simpleName = parsedName.getClassName(); String genericType = parsedName.getGenericType(); if (!parsedName.isSimple()) { if (genericType.startsWith(JAVA_LANG) || importedFull.contains(genericType)) { return simpleName + renderParams(parsedName.getParams()) + parsedName.getArrayPart(); } else { return type + renderParams(parsedName.getParams()); } } else { return type; // a simple type } } private String renderParams(List<ParsedTypeNameParam> params) { if (!params.isEmpty()) { StringBuilder sb = new StringBuilder(); sb.append("<"); for (Iterator<ParsedTypeNameParam> it = params.iterator(); it.hasNext();) { ParsedTypeNameParam type = (ParsedTypeNameParam) it.next(); if (StringUtils.isNotEmpty(type.getWildcard())) { sb.append(type.getWildcard()); sb.append(" "); } sb.append(getTypeUsage(type.getType())); if (it.hasNext()) { sb.append(", "); } } sb.append(">"); return sb.toString(); } else { return ""; } } private ParsedTypeName parseType(String type) { String regex = "^(?:([^<>]+)\\.)?([^.<>]+?)(?:\\s?<(.*)>)?((?:\\[\\])*)?$"; Matcher matcher = Pattern.compile(regex).matcher(type); if (matcher.matches()) { List<ParsedTypeNameParam> params = extractParams(matcher.group(3)); int arrayDimensions = calculateArrayDimensions(matcher.group(4)); return new ParsedTypeName(matcher.group(1), matcher.group(2), params, arrayDimensions); } else { throw new IllegalArgumentException("Cannot parse type!"); } } private int calculateArrayDimensions(String dim) { return StringUtils.isNotEmpty(dim) ? dim.length() / 2 : 0; } private List<ParsedTypeNameParam> extractParams(String params) { List<ParsedTypeNameParam> parts = new ArrayList<ParsedTypeNameParam>(); if (StringUtils.isNotEmpty(params)) { StringBuffer sb = new StringBuffer(params); Pattern pattern = Pattern.compile("<[^<>]+?>"); Matcher m = pattern.matcher(sb.toString()); while (m.find()) { for (int i = m.start(); i < m.end(); i++) { sb.setCharAt(i, ' '); } m = pattern.matcher(sb.toString()); } String projection = sb.toString(); int from = 0; int pos = projection.indexOf(','); while (pos > 0) { String part = params.substring(from, pos).trim(); parts.add(typeParam(part)); from = pos + 1; pos = projection.indexOf(',', pos + 1); } String part = params.substring(from).trim(); parts.add(typeParam(part)); } return parts; } private ParsedTypeNameParam typeParam(String type) { String regex = "^((?:\\?|[\\w$]+)\\s(?:extends|super))\\s+(.*)$"; Matcher matcher = Pattern.compile(regex).matcher(type); if (matcher.matches()) { return new ParsedTypeNameParam(matcher.group(1), matcher.group(2)); } else { return new ParsedTypeNameParam("", type); } } }