package com.revolsys.swing.map.layer.record.component;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Supplier;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import com.revolsys.properties.ObjectWithProperties;
import com.revolsys.record.schema.RecordDefinition;
import com.revolsys.swing.SwingUtil;
import com.revolsys.swing.field.Field;
import com.revolsys.swing.map.layer.record.AbstractRecordLayer;
import com.revolsys.util.Exceptions;
public class RecordLayerFields {
@SuppressWarnings("unchecked")
private static Supplier<Field> getFactory(final ObjectWithProperties properties,
final String propertyName, final String fieldName) {
final Map<String, Object> factories = getFieldFactoryMap(properties, propertyName);
final Object factoryDef = factories.get(fieldName);
if (factoryDef == null) {
return null;
} else if (factoryDef instanceof Supplier) {
return (Supplier<Field>)factoryDef;
} else {
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
final String script = factoryDef.toString();
try {
final SimpleBindings bindings = new SimpleBindings();
bindings.put("object", properties);
bindings.put("fieldName", fieldName);
return (Supplier<Field>)engine.eval(script, bindings);
} catch (final ScriptException e) {
throw Exceptions.wrap(e);
}
}
}
private static Map<String, Object> getFieldFactoryMap(final ObjectWithProperties properties,
final String propertyName) {
if (properties == null) {
return new TreeMap<>();
} else {
Map<String, Object> factories = properties.getProperty(propertyName);
if (factories == null) {
factories = new TreeMap<>();
properties.setProperty(propertyName, factories);
}
return factories;
}
}
public static <T extends Field> T newCompactField(final AbstractRecordLayer layer,
final String fieldName, final boolean editable) {
T field = newField((ObjectWithProperties)layer, "fieldFactories", fieldName, editable);
if (field == null) {
final RecordDefinition recordDefinition = layer.getRecordDefinition();
field = newField(recordDefinition, "fieldFactories", fieldName, editable);
if (field == null) {
field = SwingUtil.newField(recordDefinition, fieldName, editable);
}
}
field.setEditable(editable);
return field;
}
@SuppressWarnings("unchecked")
private static <T extends Field> T newField(final ObjectWithProperties properties,
final String propertyName, final String fieldName, final boolean editable) {
final Supplier<Field> factory = getFactory(properties, propertyName, fieldName);
if (factory == null) {
return null;
} else {
return (T)factory.get();
}
}
public static <T extends Field> T newFormField(final AbstractRecordLayer layer,
final String fieldName, final boolean editable) {
T field = newField((ObjectWithProperties)layer, "formFieldFactories", fieldName, editable);
if (field == null) {
final RecordDefinition recordDefinition = layer.getRecordDefinition();
field = newField(recordDefinition, "formFieldFactories", fieldName, editable);
if (field == null) {
field = newCompactField(layer, fieldName, editable);
}
}
field.setEditable(editable);
return field;
}
}