package org.activityinfo.geoadmin.locations;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import com.google.common.math.IntMath;
import net.miginfocom.swing.MigLayout;
import org.activityinfo.geoadmin.ImportFeature;
import org.activityinfo.geoadmin.ImportSource;
import org.activityinfo.geoadmin.Sql;
import org.activityinfo.geoadmin.model.*;
import org.activityinfo.geoadmin.util.GenericTableModel;
import org.activityinfo.geoadmin.util.GenericTableModel.Builder;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.vividsolutions.jts.geom.Point;
public class LocationImportWindow extends JFrame {
private LocationImportForm importForm;
private JTable table;
private List<LocationFeature> locations;
private ActivityInfoClient client;
private List<AdminLevel> levels;
private ImportSource source;
private GenericTableModel<LocationFeature> tableModel;
private int locationTypeId;
public LocationImportWindow(JFrame parent, ActivityInfoClient client,
int locationTypeId,
List<AdminLevel> levels, ImportSource source) throws Exception {
super("Import - " + source.getFile().getName());
setSize(650, 350);
setLocationRelativeTo(parent);
this.client = client;
this.levels = levels;
this.source = source;
this.locationTypeId = locationTypeId;
importForm = new LocationImportForm(source, levels);
importForm.guessLevelColumns(client);
locations = createRows();
tableModel = createTableModel();
table = new JTable(tableModel);
// table.getColumnModel().getColumn(ImportTableModel.PARENT_COLUMN).setCellEditor(
// new DefaultCellEditor(parentComboBox));
// table.getColumnModel().getColumn(ImportTableModel.ACTION_COLUMN).setCellEditor(
// new DefaultCellEditor(actionComboBox));
table.setDefaultRenderer(Object.class,
new LocationImportTableCellRenderer(tableModel));
table.setAutoCreateRowSorter(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
onSelectionChanged(e);
}
});
JLabel countLabel = new JLabel(source.getFeatureCount() + " features");
JPanel panel = new JPanel(new MigLayout("fill"));
panel.add(importForm, "wrap");
panel.add(new JScrollPane(table,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), "span, wrap,grow");
panel.add(countLabel);
getContentPane().add(createToolBar(), BorderLayout.PAGE_START);
getContentPane().add(panel, BorderLayout.CENTER);
}
private List<LocationFeature> createRows() {
Random random = new Random();
List<LocationFeature> locations = Lists.newArrayList();
for(int i=0;i!=source.getFeatureCount();++i) {
ImportFeature feature = source.getFeatures().get(i);
System.out.println("Matching " + feature);
LocationFeature location = new LocationFeature(feature);
location.setId(random.nextInt(Integer.MAX_VALUE));
locations.add(location);
}
return locations;
}
private GenericTableModel<LocationFeature> createTableModel() {
Builder<LocationFeature> model = GenericTableModel.newModel(locations);
for(final AdminLevel level : levels) {
model.addColumn(level.getName(), String.class, new Function<LocationFeature, String>() {
public String apply(LocationFeature location) {
AdminEntity entity = location.getEntities().get(level.getId());
if(entity == null) {
return null;
}
return entity.getName();
}
});
}
for(int i=0;i!=source.getAttributeCount();++i) {
final int attributeindex = i;
model.addColumn(source.getAttributes().get(i).getName().getLocalPart(), Object.class, new Function<LocationFeature, Object>() {
public Object apply(LocationFeature location) {
return location.getFeature().getAttributeValue(attributeindex);
}
});
}
return model.build();
}
private void onSelectionChanged(ListSelectionEvent e) {
}
private JToolBar createToolBar() {
JButton matchButton = new JButton("Match Admin Levels");
matchButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
doMatch();
}
});
JButton updateButton = new JButton("Import");
updateButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doImport();
}
});
JButton updateSQLButton = new JButton("Generate Import SQL");
updateSQLButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
doImportSql();
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
JToolBar toolBar = new JToolBar();
toolBar.setFloatable(false);
toolBar.add(matchButton);
toolBar.add(updateButton);
toolBar.add(updateSQLButton);
toolBar.addSeparator();
return toolBar;
}
private void doMatch() {
LocationAdminMatcher matcher = new LocationAdminMatcher(client, levels);
for(AdminLevel level : levels) {
matcher.setLevelAttribute(level, importForm.getLevelAttributeIndex(level));
}
for(LocationFeature location : locations) {
location.getEntities().clear();
for(AdminEntity entity : matcher.forFeature(location.getFeature())) {
location.getEntities().put(entity.getLevelId(), entity);
}
}
tableModel.fireTableDataChanged();
}
private void doImportSql() throws IOException {
int nameIndex = importForm.getNameAttributeIndex();
int codeIndex = importForm.getCodeAttributeIndex();
File locationsFile = File.createTempFile("location", ".sql");
try(FileWriter writer = new FileWriter(locationsFile)) {
writer.append("BEGIN;\n");
writer.append("INSERT INTO location (LocationID, LocationTypeID, Name, Axe, X, Y, timeEdited) VALUES");
boolean needsComma = false;
for (LocationFeature location : locations) {
Point point = location.getPoint();
writer.append(needsComma ? ",\n" : "\n");
writer.append(String.format("(%d, %d, %s, %s, %f, %f, %d)",
location.getId(),
locationTypeId,
Sql.quote(truncate(location.getFeature().getAttributeStringValue(nameIndex))),
Sql.quote(truncate(location.getFeature().getAttributeStringValue(codeIndex))),
point.getX(),
point.getY(),
new Date().getTime()));
needsComma = true;
}
writer.append(";\n");
writer.append("INSERT INTO locationadminlink (LocationID, AdminEntityID) VALUES");
needsComma = false;
for (LocationFeature location : locations) {
for (AdminEntity entity : location.getEntities().values()) {
writer.append(needsComma ? "\n," : "\n");
writer.append(String.format("(%d, %d)",
location.getId(),
entity.getId()));
needsComma = true;
}
}
writer.append(";");
writer.append("COMMIT;\n");
}
System.out.println("Wrote to " + locationsFile.getAbsolutePath());
}
private void doImport() {
int nameIndex = importForm.getNameAttributeIndex();
List<NewLocation> newLocations = Lists.newArrayList();
for(LocationFeature location : locations) {
Point point = location.getPoint();
NewLocation newLocation = new NewLocation();
newLocation.setName(truncate(location.getFeature().getAttributeStringValue(nameIndex)));
newLocation.setLongitude(point.getX());
newLocation.setLatitude(point.getY());
for(AdminEntity entity : location.getEntities().values()) {
newLocation.getAdminEntityIds().add(entity.getId());
}
newLocations.add(newLocation);
}
client.postNewLocations(locationTypeId, newLocations);
setVisible(false);
}
private String truncate(String name) {
if(name.length() < 50) {
return name;
}
return name.substring(0, 50);
}
}