# encoding: utf-8 # Version: 1.0.0-0 # Date: October 19, 2018 # License: GPLv3 # Country: Uruguay # Organization: gvSIG Uruguay Community # Developer: Carlos I. Colombana # Contact: carlos.colombana@gmail.com import gvsig import os import ssl import sys import time from geopy import geocoders from gvsig import geom from gvsig.libs.webbrowser.browserpanel import BrowserPanel from java.awt import Dimension from java.awt import Toolkit from java.beans import PropertyChangeEvent from java.beans import PropertyChangeListener from java.io import File from java.text import SimpleDateFormat from java.util import Date from org.gvsig.andami import PluginsLocator from org.gvsig.andami.ui.mdiManager import MDIManagerFactory from org.gvsig.app import ApplicationLocator from org.gvsig.app.project import DefaultProject from org.gvsig.app.project import ProjectNotification from org.gvsig.app.project.documents.table import TableDocument from org.gvsig.app.project.documents.table import TableManager from org.gvsig.fmap.dal.feature import FeatureStore from org.gvsig.fmap.dal.feature import FeatureStoreNotification from org.gvsig.fmap.dal.feature.impl import DefaultFeatureStore from org.gvsig.tools import ToolsLocator from org.gvsig.tools.dispose import DisposeUtils from org.gvsig.tools.observer import Observer from org.gvsig.tools.swing.api import ToolsSwingLocator from org.gvsig.tools.swing.api.windowmanager import WindowManager #from org.gvsig.webbrowser import WebBrowserFactory class OSMGeocoder(object): def __init__(self): self.i18nManager = ToolsLocator.getI18nManager() self.i18nManager.addResourceFamily("text", File(gvsig.getResource(__file__, "i18n"))) self.title = self.i18nManager.getTranslation("_OSM_Title") self.helpTitle = self.i18nManager.getTranslation("_OSM_Help_title") self.mdiManager = MDIManagerFactory().createManager() self.screenSize = Toolkit.getDefaultToolkit().getScreenSize() self.panel = None self.stopState = True def getI18nManager(self): return self.i18nManager def getTitle(self): return self.title def getHelpTitle(self): return self.helpTitle def getMdiManager(self): return self.mdiManager def getScreenSize(self): return self.screenSize def getPanel(self): return self.panel def setPanel(self, panel): self.panel = panel def getStopState(self): return self.stopState def setStopState(self, stopState): self.stopState = stopState def initProjectObserver(self): project = gvsig.currentProject() self.addProjectObserver(project, self.panel) def initStoreObservers(self): tables = self.getTables() for table in tables: store = table.getStore() self.addStoreObserver(store, self.panel) def initTableListeners(self): tables = self.getTables() for table in tables: self.addTableListener(table, self.panel) def getTables(self): inputTables = gvsig.currentProject().getDocuments("project.document.table") outputTables = list() for inputTable in inputTables: if inputTable.getStore().getProviderName() == "CSV": outputTables.append(inputTable) return outputTables def getFields(self, tableName): table = gvsig.currentProject().getTable(tableName) schema = table.getSchema() if schema != None: fields = list() for field in schema: if field.getDataTypeName() == "String": fields.append(field.getName()) else: fields = None return fields def addProjectObserver(self, project, panel): projectObserver = ProjectObserver(panel) project.deleteObservers() project.addObserver(projectObserver) def addStoreObserver(self, store, panel): storeObserver = StoreObserver(panel) store.deleteObservers() store.addObserver(storeObserver) def addTableListener(self, table, panel): tableListener = TableListener(panel) table.addPropertyChangeListener(tableListener) def launchHelpWindow(self): name = "OSMGeocoder" extension = ".html" locale = PluginsLocator.getLocaleManager().getCurrentLocale() tag = locale.getLanguage() helpPath = gvsig.getResource(__file__, "help", name + "_" + tag + extension) if not os.path.exists(helpPath): helpPath = gvsig.getResource(__file__, "help", name + "_en" + extension) helpUrl = "file:///" + helpPath.replace("\\", "/") ''' webBrowserFactory = WebBrowserFactory() webBrowserPanel = webBrowserFactory.createWebBrowserPanel() webBrowserPanel.asJComponent().setPreferredSize(Dimension(int(self.screenSize.getWidth() / 4), int(self.screenSize.getHeight() / 2))) webBrowserPanel.setPage(helpUrl) self.mdiManager.showWindow(webBrowserPanel, self.helpTitle, WindowManager.MODE.DIALOG) ''' browserPanel = BrowserPanel() browserPanel.asJComponent().setPreferredSize(Dimension(int(self.screenSize.getWidth() / 4), int(self.screenSize.getHeight() / 2))) browserPanel.setPage(helpUrl) browserPanel.showWindow(self.helpTitle, scriptEditor=False) def findWindow(self, targetTitle): targetWindow = None windows = self.mdiManager.getAllWindows() length = len(windows) i = 0 while i < length and targetWindow == None: title = windows[i].getWindowInfo().getTitle() if title == targetTitle: targetWindow = windows[i] i += 1 return targetWindow def geocodeAddress(self, address): geometry = None message = "" try: ssl._create_default_https_context = ssl._create_unverified_context geocoder = geocoders.get_geocoder_for_service("nominatim") location = geocoder().geocode(address, timeout=10) if location != None: if location.address.split(',', 1)[0] == "None": geometry = None else: geometry = geom.createPoint(geom.D2, location.longitude, location.latitude) except: ex = sys.exc_info()[1] message = ex.__class__.__name__ + " - " + str(ex) if geometry == None and message == "": message = self.i18nManager.getTranslation("_OSM_Invalid_address") return geometry, message def geocodeAddresses(self, tableName, fieldName): pointsLayer = None errorsDBF = None ex = None table = gvsig.currentProject().getTable(tableName) tableSchema = table.getSchema() layerSchema = gvsig.createSchema(tableSchema) if layerSchema.get("GEOMETRY") != None: layerSchema.remove(layerSchema.getAttributeDescriptor("GEOMETRY")) for field in layerSchema: if field.getDataTypeName() == "String": layerSchema.get(field.getName()).setSize(200) locationField = "_" + self.i18nManager.getTranslation("_OSM_Location") if layerSchema.get(locationField) == None: layerSchema.append(locationField, "STRING", 30) layerSchema.append("GEOMETRY", "GEOMETRY") layerSchema.get("GEOMETRY").setGeometryType(geom.POINT, geom.D2) pointsLayer = gvsig.createShape(layerSchema) ''' projection = gvsig.getCRS("EPSG:32721") pointsLayer.setProjection(projection) ''' errorsSchema = gvsig.createSchema(tableSchema) for field in errorsSchema: if field.getDataTypeName() == "String": errorsSchema.get(field.getName()).setSize(200) messageField = "_" + self.i18nManager.getTranslation("_OSM_Message") if errorsSchema.get(messageField) == None: errorsSchema.append(messageField, "STRING", 200) errorsDBF = gvsig.createDBF(errorsSchema) i = 0 iPoints = 0 iErrors = 0 fields = tableSchema.getAttrNames() features = table.features() try: maximum = features.getSize() self.panel.pgbMultipleSearch.setMaximum(maximum) self.panel.pgbMultipleSearch.setValue(i) self.panel.pgbMultipleSearch.setString(str(i) + " / " + str(maximum)) self.panel.pgbMultipleSearch.setStringPainted(True) pointsLayer.edit() errorsDBF.edit(FeatureStore.MODE_APPEND) iterableFeatures = features.iterator() while iterableFeatures.hasNext() and not self.stopState: feature = iterableFeatures.next() address = feature.get(fieldName) geometry, message = self.geocodeAddress(address) if geometry != None: newFeature = dict() for field in tableSchema: if field.getName() != "GEOMETRY": if feature.get(field.getName()) != None: if str(field.getDataTypeName()) != "Long": newFeature[field.getName()] = feature.get(field.getName()) else: newFeature[field.getName()] = long(feature.get(field.getName())) else: newFeature[field.getName()] = "" newFeature[locationField] = str(geometry.getY()) + "," + str(geometry.getX()) newFeature["GEOMETRY"] = geometry pointsLayer.append(newFeature) iPoints += 1 else: newFeature = errorsDBF.createNewFeature() for field in tableSchema: if feature.get(field.getName()) != None: newFeature.set(field.getName(), feature.get(field.getName())) newFeature.set(messageField, message) errorsDBF.insert(newFeature) iErrors += 1 i += 1 self.panel.pgbMultipleSearch.setValue(i) self.panel.pgbMultipleSearch.setString(str(i) + " / " + str(maximum)) self.panel.pgbMultipleSearch.setStringPainted(True) time.sleep(1) pointsLayer.commit() errorsDBF.commitChanges() if iPoints == 0: pointsLayer = None if iErrors == 0: errorsDBF = None except: ex = sys.exc_info()[1] finally: DisposeUtils.disposeQuietly(iterableFeatures) DisposeUtils.disposeQuietly(features) return pointsLayer, errorsDBF, ex def showResult(self, geometry, address): layerSchema = gvsig.createSchema() layerSchema.append("GEOMETRY", "GEOMETRY") layerSchema.get("GEOMETRY").setGeometryType(geom.POINT, geom.D2) pointLayer = gvsig.createShape(layerSchema) pointLayer.edit() pointLayer.append(GEOMETRY=geometry) pointLayer.commit() date = Date() dateFormat = SimpleDateFormat("yyyyMMdd_HHmmss") pointLayer.setName(address + " (" + dateFormat.format(date) + ")") project = gvsig.currentProject() view = project.getView(self.title) if view == None: view = project.createView(self.title) view.addLayer(pointLayer) view.getMapContext().getViewPort().setEnvelope(geometry.getEnvelope()) view.showWindow() def loadResults(self, tableName, pointsLayer, errorsDBF): if self.stopState == 0: date = Date() dateFormat = SimpleDateFormat("yyyyMMdd_HHmmss") if errorsDBF != None: documentManager = TableManager() errorsTable = TableDocument(documentManager, errorsDBF) errorsTable.setName(self.i18nManager.getTranslation("_OSM_Errors_table") + ": " + tableName + " (" + dateFormat.format(date) + ")") gvsig.currentProject().addDocument(errorsTable) self.mdiManager.addCentredWindow(errorsTable.getMainWindow()) if pointsLayer != None: pointsLayer.setName(tableName + " (" + dateFormat.format(date) + ")") project = gvsig.currentProject() view = project.getView(self.title) if view == None: view = project.createView(self.title) view.addLayer(pointsLayer) view.getMapContext().getViewPort().setEnvelope(pointsLayer.getFullEnvelope()) view.showWindow() self.setStopState(True) class ProjectObserver(Observer): def __init__(self, panel): self.panel = panel def update(self, observable, notification): if isinstance(observable, DefaultProject): table = notification.getDocument() store = table.getStore() notificationType = notification.getNotificationType() if store.getProviderName() == "CSV" and (notificationType == ProjectNotification.AFTER_ADD_DOCUMENT or notificationType == ProjectNotification.AFTER_REMOVE_DOCUMENT): if notificationType == ProjectNotification.AFTER_ADD_DOCUMENT: self.panel.getOSMGeocoder().addStoreObserver(store, self.panel) self.panel.getOSMGeocoder().addTableListener(table, self.panel) if self.panel.getOSMGeocoder().getStopState() and self.panel.rdbMultipleSearch.isSelected(): self.panel.loadTables() class StoreObserver(Observer): def __init__(self, panel): self.panel = panel def update(self, observable, notification): if isinstance(observable, DefaultFeatureStore): notificationType = notification.getType() if notificationType == FeatureStoreNotification.TRANSFORM_CHANGE: if self.panel.getOSMGeocoder().getStopState() and self.panel.rdbMultipleSearch.isSelected(): self.panel.loadTables() class TableListener(PropertyChangeListener): def __init__(self, panel): self.panel = panel def propertyChange(self, event): if isinstance(event, PropertyChangeEvent): if self.panel.getOSMGeocoder().getStopState() and self.panel.rdbMultipleSearch.isSelected(): self.panel.loadTables() def main(*args): pass