package org.netbeans.gradle.project.properties;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nonnull;
import org.jtrim.utils.ExceptionHelper;
import org.netbeans.gradle.project.tasks.vars.StringResolver;
public final class GradleLocationDef {
public static final GradleLocationDef DEFAULT = new GradleLocationDef(GradleLocationDefault.DEFAULT_REF, false);
private static final String PREFER_WRAPPER_KEY = "W";
private final GradleLocationRef locationRef;
private final boolean preferWrapper;
public GradleLocationDef(GradleLocationRef locationRef, boolean preferWrapper) {
ExceptionHelper.checkNotNullArgument(locationRef, "locationRef");
// Performance hack: as is now we won't pass different resolvers, so we can cache the location value.
this.locationRef = cachedRef(locationRef);
this.preferWrapper = preferWrapper;
}
private static GradleLocationRef cachedRef(final GradleLocationRef src) {
return new GradleLocationRef() {
private final AtomicReference<GradleLocation> cache = new AtomicReference<>(null);
@Override
public String getUniqueTypeName() {
return src.getUniqueTypeName();
}
@Override
public String asString() {
return src.asString();
}
@Override
public GradleLocation getLocation(StringResolver resolver) {
GradleLocation result = cache.get();
if (result == null) {
result = src.getLocation(resolver);
if (!cache.compareAndSet(null, result)) {
result = cache.get();
}
}
return result;
}
};
}
public static GradleLocationDef fromVersion(String versionStr, boolean preferWrapper) {
return new GradleLocationDef(GradleLocationVersion.getLocationRef(versionStr), preferWrapper);
}
private static void appendKeyValue(String key, String value, StringBuilder result) {
result.append('?');
result.append(key);
result.append('=');
result.append(value);
}
private static void appendLocation(GradleLocationRef location, StringBuilder result) {
String value = location.asString();
if (value == null) {
return;
}
appendKeyValue(location.getUniqueTypeName(), value, result);
}
public String toStringFormat() {
StringBuilder result = new StringBuilder(64);
if (preferWrapper) {
appendKeyValue(PREFER_WRAPPER_KEY, "", result);
}
appendLocation(locationRef, result);
return result.toString();
}
private static KeyValue trySplitKeyValue(String str) {
if (!str.startsWith("?")) {
return null;
}
int sepIndex = str.indexOf('=');
if (sepIndex < 0) {
return null;
}
String key = str.substring(1, sepIndex);
String value = str.substring(sepIndex + 1, str.length());
return new KeyValue(key, value);
}
private static GradleLocationRef getLocation(KeyValue keyValue) {
String typeName = keyValue.key;
String value = keyValue.value;
if (GradleLocationDefault.UNIQUE_TYPE_NAME.equalsIgnoreCase(typeName)) {
return GradleLocationDefault.DEFAULT_REF;
}
if (GradleLocationVersion.UNIQUE_TYPE_NAME.equalsIgnoreCase(typeName)) {
return GradleLocationVersion.getLocationRef(value);
}
if (GradleLocationDirectory.UNIQUE_TYPE_NAME.equalsIgnoreCase(typeName)) {
return GradleLocationDirectory.getLocationRef(value);
}
if (GradleLocationDistribution.UNIQUE_TYPE_NAME.equalsIgnoreCase(typeName)) {
return GradleLocationDistribution.getLocationRef(value);
}
return null;
}
private static GradleLocationRef parseLocation(String str) {
KeyValue keyValue = trySplitKeyValue(str);
if (keyValue != null) {
GradleLocationRef result = getLocation(keyValue);
if (result != null) {
return result;
}
}
return getRawLocation(str);
}
private static GradleLocationRef getRawLocation(String locationPath) {
if (locationPath.isEmpty()) {
return GradleLocationDefault.DEFAULT_REF;
}
else {
return GradleLocationDirectory.getLocationRef(locationPath);
}
}
public static GradleLocationDef parseFromString(String locationDefStr) {
ExceptionHelper.checkNotNullArgument(locationDefStr, "locationDefStr");
String normDef = locationDefStr.trim();
KeyValue keyValue = trySplitKeyValue(normDef);
if (keyValue == null) {
return new GradleLocationDef(getRawLocation(normDef), false);
}
GradleLocationRef locationRef;
boolean preferWrapper;
if (keyValue.key.equalsIgnoreCase(PREFER_WRAPPER_KEY)) {
locationRef = parseLocation(keyValue.value);
preferWrapper = true;
}
else {
preferWrapper = false;
locationRef = getLocation(keyValue);
if (locationRef == null) {
locationRef = getRawLocation(normDef);
}
}
return new GradleLocationDef(locationRef, preferWrapper);
}
@Nonnull
public GradleLocationRef getLocationRef() {
return locationRef;
}
@Nonnull
public GradleLocation getLocation(StringResolver resolver) {
return locationRef.getLocation(resolver);
}
public boolean isPreferWrapper() {
return preferWrapper;
}
@Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + Objects.hashCode(this.locationRef);
hash = 97 * hash + (this.preferWrapper ? 1 : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (obj == this) return true;
if (getClass() != obj.getClass()) return false;
final GradleLocationDef other = (GradleLocationDef)obj;
return Objects.equals(this.locationRef, other.locationRef)
&& this.preferWrapper == other.preferWrapper;
}
private static final class KeyValue {
public final String key;
public final String value;
public KeyValue(String key, String value) {
this.key = key;
this.value = value;
}
}
}