package org.infernus.idea.checkstyle.model; import com.intellij.openapi.project.Project; import java.util.Map; import java.util.WeakHashMap; import static org.infernus.idea.checkstyle.util.Strings.isBlank; /** * Factory for configuration location objects. */ public class ConfigurationLocationFactory { /** * We maintain a map of all current locations, to avoid recreating identical objects. * This allows us to ensure that updates to one location (e.g. a URL change) are visible * to other modules with a reference to the given location. */ private final Map<ConfigurationLocation, ConfigurationLocation> instanceCache = new WeakHashMap<>(); /** * Create a new location. * * @param project the project this location is associated with. * @param type the type. * @param location the location. * @param description the optional description. * @return the location. */ public ConfigurationLocation create(final Project project, final ConfigurationType type, final String location, final String description) { if (type == null) { throw new IllegalArgumentException("Type is required"); } ConfigurationLocation configurationLocation; switch (type) { case LOCAL_FILE: configurationLocation = new FileConfigurationLocation(project); break; case PROJECT_RELATIVE: configurationLocation = new RelativeFileConfigurationLocation(project); break; case HTTP_URL: configurationLocation = new HTTPURLConfigurationLocation(); break; case INSECURE_HTTP_URL: configurationLocation = new InsecureHTTPURLConfigurationLocation(); break; case CLASSPATH: configurationLocation = new ClassPathConfigurationLocation(); break; default: throw new IllegalArgumentException("Unknown type: " + type); } configurationLocation.setLocation(location); configurationLocation.setDescription(description); synchronized (instanceCache) { if (instanceCache.containsKey(configurationLocation)) { return instanceCache.get(configurationLocation); } else { instanceCache.put(configurationLocation, configurationLocation); } } return configurationLocation; } /** * Create a new location from a string representation. * * @param project the project this location is associated with. * @param stringRepresentation the toString of another ConfigurationLocation. * @return the location. */ public ConfigurationLocation create(final Project project, final String stringRepresentation) { if (project == null) { throw new IllegalArgumentException("A project is required"); } if (isBlank(stringRepresentation)) { throw new IllegalArgumentException("A non-blank representation is required"); } final int typeSplitIndex = stringRepresentation.indexOf(':'); if (indexIsOutOfBounds(typeSplitIndex, stringRepresentation)) { throw new IllegalArgumentException("Invalid string representation: " + stringRepresentation); } final String typeString = stringRepresentation.substring(0, typeSplitIndex); final int descriptionSplitIndex = stringRepresentation.lastIndexOf(':'); if (typeSplitIndex == descriptionSplitIndex || indexIsOutOfBounds(descriptionSplitIndex, stringRepresentation)) { throw new IllegalArgumentException("Invalid string representation: " + stringRepresentation); } final String location = stringRepresentation.substring(typeSplitIndex + 1, descriptionSplitIndex); String description = ""; if (descriptionSplitIndex < (stringRepresentation.length() - 1)) { description = stringRepresentation.substring(descriptionSplitIndex + 1); } final ConfigurationType type = ConfigurationType.parse(typeString); return create(project, type, location, description); } private boolean indexIsOutOfBounds(final int index, final String stringRepresentation) { return index <= 0 || index >= stringRepresentation.length() - 1; } }