package io.lumify.core.model.ontology;
import com.google.common.collect.ImmutableList;
import io.lumify.core.exception.LumifyException;
import io.lumify.web.clientapi.model.ClientApiOntology;
import io.lumify.web.clientapi.model.PropertyType;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.securegraph.type.GeoCircle;
import org.securegraph.type.GeoPoint;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public abstract class OntologyProperty {
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
public static final SimpleDateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");
public static final Pattern GEO_LOCATION_FORMAT = Pattern.compile("POINT\\((.*?),(.*?)\\)", Pattern.CASE_INSENSITIVE);
public static final Pattern GEO_LOCATION_ALTERNATE_FORMAT = Pattern.compile("(.*?),(.*)", Pattern.CASE_INSENSITIVE);
static {
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
DATE_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
}
public abstract String getTitle();
public abstract String getDisplayName();
public abstract boolean getUserVisible();
public abstract boolean getSearchable();
public abstract boolean getAddable();
public abstract PropertyType getDataType();
public abstract Double getBoost();
public abstract Map<String, String> getPossibleValues();
public abstract String getDisplayType();
public abstract String getPropertyGroup();
public abstract String getValidationFormula();
public abstract String getDisplayFormula();
public abstract ImmutableList<String> getDependentPropertyIris();
public abstract String[] getIntents();
public static Collection<ClientApiOntology.Property> toClientApiProperties(Iterable<OntologyProperty> properties) {
Collection<ClientApiOntology.Property> results = new ArrayList<ClientApiOntology.Property>();
for (OntologyProperty property : properties) {
results.add(property.toClientApi());
}
return results;
}
public ClientApiOntology.Property toClientApi() {
try {
ClientApiOntology.Property result = new ClientApiOntology.Property();
result.setTitle(getTitle());
result.setDisplayName(getDisplayName());
result.setUserVisible(getUserVisible());
result.setSearchable(getSearchable());
result.setAddable(getAddable());
result.setDataType(getDataType());
result.setDisplayType(getDisplayType());
result.setPropertyGroup(getPropertyGroup());
result.setValidationFormula(getValidationFormula());
result.setDisplayFormula(getDisplayFormula());
result.setDependentPropertyIris(getDependentPropertyIris());
if (getPossibleValues() != null) {
result.getPossibleValues().putAll(getPossibleValues());
}
if (getIntents() != null) {
result.getIntents().addAll(Arrays.asList(getIntents()));
}
return result;
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
public Object convertString(String valueStr) throws ParseException {
PropertyType dataType = getDataType();
Object value = valueStr;
switch (dataType) {
case DATE:
try {
value = DATE_TIME_FORMAT.parse(valueStr);
} catch (ParseException ex) {
value = DATE_FORMAT.parse(valueStr);
}
break;
case GEO_LOCATION:
value = parseGeoLocation(valueStr);
break;
case CURRENCY:
value = new BigDecimal(valueStr);
break;
case DOUBLE:
value = Double.parseDouble(valueStr);
break;
case INTEGER:
value = Integer.parseInt(valueStr);
break;
case BOOLEAN:
value = Boolean.parseBoolean(valueStr);
break;
}
return value;
}
public static Object convert(JSONArray values, PropertyType propertyDataType, int index) throws ParseException {
switch (propertyDataType) {
case DATE:
String valueStr = values.getString(index);
try {
return DATE_TIME_FORMAT.parse(valueStr);
} catch (ParseException ex) {
return DATE_FORMAT.parse(valueStr);
}
case GEO_LOCATION:
return new GeoCircle(
values.getDouble(index),
values.getDouble(index + 1),
values.getDouble(index + 2)
);
case CURRENCY:
return new BigDecimal(values.getString(index));
case INTEGER:
return values.getInt(index);
case DOUBLE:
return values.getDouble(index);
case BOOLEAN:
return values.getBoolean(index);
}
return values.getString(index);
}
protected static Object parseGeoLocation(String valueStr) {
try {
JSONObject json = new JSONObject(valueStr);
double latitude = json.getDouble("latitude");
double longitude = json.getDouble("longitude");
String altitudeString = json.optString("altitude");
Double altitude = (altitudeString == null || altitudeString.length() == 0) ? null : Double.parseDouble(altitudeString);
String description = json.optString("description");
return new GeoPoint(latitude, longitude, altitude, description);
} catch (Exception ex) {
Matcher match = GEO_LOCATION_FORMAT.matcher(valueStr);
if (match.find()) {
double latitude = Double.parseDouble(match.group(1).trim());
double longitude = Double.parseDouble(match.group(2).trim());
return new GeoPoint(latitude, longitude);
}
match = GEO_LOCATION_ALTERNATE_FORMAT.matcher(valueStr);
if (match.find()) {
double latitude = Double.parseDouble(match.group(1).trim());
double longitude = Double.parseDouble(match.group(2).trim());
return new GeoPoint(latitude, longitude);
}
throw new LumifyException("Could not parse location: " + valueStr);
}
}
public boolean hasDependentPropertyIris() {
return getDependentPropertyIris() != null && getDependentPropertyIris().size() > 0;
}
}