Конвертирование адреса
Материал из BiTel WiKi
По какой либо причине бывает адрес импортируется в формате текста, скрипт для конвертирования адреса из формата текст в формат адрес Разработка Bitel - dimOn
Внимание! Данное решение/метод/статья относится к версии 5.2,6.0 и для других версий может быть неактуальна! Вам нужно самостоятельно поправить решение под свои нужды или воспользоваться помощью на форуме. Будем признательны, если внизу страницы или отдельной статьёй вы разместите исправленное решение для другой версии или подсказки что надо исправить.
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import ru.bitel.bgbilling.common.BGException; import ru.bitel.bgbilling.kernel.container.managed.ServerContext; import ru.bitel.bgbilling.kernel.module.common.bean.User; import ru.bitel.bgbilling.server.util.Setup; import ru.bitel.common.Utils; import ru.bitel.common.sql.ConnectionSet; import ru.bitel.oss.kernel.directories.address.common.bean.House; import ru.bitel.oss.kernel.directories.address.common.bean.Street; import ru.bitel.oss.kernel.directories.address.common.service.AddressService; import bitel.billing.server.admin.bean.AddressStruct; import bitel.billing.server.admin.bean.AddressUtils; import bitel.billing.server.contract.bean.ContractAddressParamValue; import bitel.billing.server.contract.bean.ContractParameterManager; public class AddressConverter { int pidText = 35;//35 int pidAddress = 26;//26 int cityId = 1; AddressService addressService; ContractParameterManager parameterManager; Connection con; boolean test = false; public void execute( Setup setup, ConnectionSet connectionSet ) { try { con = connectionSet.getConnection(); this.run(); } catch( Exception e ) { e.printStackTrace(); } } private void run() throws SQLException, BGException { PreparedStatement ps = con.prepareStatement( "DROP TABLE IF EXISTS `_incorrectContractsAddressConvertor`" ); ps.execute(); ps.close(); ps = con.prepareStatement( "DROP TABLE IF EXISTS `_correctContractsAddressConvertorTEST`" ); ps.execute(); ps.close(); ps = con.prepareStatement( "CREATE TABLE IF NOT EXISTS `_incorrectContractsAddressConvertor` ( `cid` INT NOT NULL , `sourceParameter` VARCHAR(256) NULL , PRIMARY KEY (`cid`) )" ); ps.execute(); ps.close(); parameterManager = new ContractParameterManager( con ); addressService = ServerContext.get( ServerContext.class ).getService( AddressService.class, 0 ); if( test ) { ps = con.prepareStatement( "CREATE TABLE IF NOT EXISTS `_correctContractsAddressConvertorTEST` ( `cid` INT NOT NULL , `street` VARCHAR(128) NULL , `number` INT NULL , `korpus` VARCHAR(45) NULL , `kv` VARCHAR(45) NULL , `room` VARCHAR(45) NULL , `sourse` VARCHAR(256) NULL , PRIMARY KEY (`cid`) )" ); ps.execute(); ps.close(); ps = con.prepareStatement( "SELECT * FROM _contractaddressparamtest;" ); } else { ps = con.prepareStatement( "SELECT * FROM contract_parameter_type_1 WHERE pid=?" ); // добавить это " and cid=50110" к запросу если надо протестить на конкретном договоре. сид с лева от номера договора ps.setInt( 1, pidText ); } ResultSet rs = ps.executeQuery(); while( rs.next() ) { try { int cid = rs.getInt( "cid" ); String val = rs.getString( "val" ); if( !needToParse( cid, val ) ) continue; Entry entry = parse( val, cid ); if( entry.isError ) { if( test ) { PreparedStatement statement = con.prepareStatement( "INSERT INTO _correctContractsAddressConvertorTEST VALUES(?,?,?,?,?,?,?) " ); statement.setInt( 1, cid ); statement.setString( 2, entry.street ); statement.setInt( 3, entry.numberHome ); statement.setString( 4, entry.korpus ); statement.setString( 5, entry.apartment ); statement.setString( 6, entry.room ); statement.setString( 7, val ); statement.executeUpdate(); statement.close(); } else { ContractAddressParamValue param = new ContractAddressParamValue(); Street street = getStreet( entry ); int houseId = getHousId( entry, street ); String addressFull = AddressUtils.getAddress( Setup.getSetup(), getSruct( entry, houseId ), "default"); param.setAddress( addressFull ); param.setContractId( cid ); param.setHouseId( houseId ); param.setComment( "Конвертировано из текстового параметра" ); param.setFlat( entry.apartment ); param.setRoom( entry.room ); param.setFormatKey( "" ); parameterManager.updateAddressParam( cid, pidAddress, param, User.USER_SERVER ); } } else//заносим ошибочную запись в нашу таблицу. { PreparedStatement statement = con.prepareStatement( "INSERT INTO _incorrectContractsAddressConvertor VALUES(?,?) " ); statement.setInt( 1, cid ); statement.setString( 2, val ); statement.executeUpdate(); statement.close(); } } catch( Exception e ) { e.printStackTrace(); } } rs.close(); ps.close(); } /** Если нужно добавлять данную запись, вернет true. */ private boolean needToParse( int cid, String val ) { if( val.startsWith( "п. Сокол" ) ) return false; ContractAddressParamValue paramValue = parameterManager.getAddressParam( cid, pidAddress ); if( paramValue == null) return true; else return false; } private AddressStruct getSruct( Entry entry, int houseId ) throws BGException { AddressStruct struct = new AddressStruct(); struct.setCity( addressService.cityGet( cityId ).getTitle() ); struct.setStreet( entry.street ); String korp = Utils.parseInt( entry.korpus, -1 ) > 0 && entry.korpus != null ? "/" + entry.korpus : entry.korpus; if( korp == null ) korp = ""; struct.setFrac( korp ); struct.setHouse( Integer.toString( entry.numberHome) ); struct.setHouseId( houseId ); struct.setFlat( entry.apartment ); struct.setRoom( entry.room ); return struct; } private Entry parse( String str, int cid ) { Entry entry = new Entry(); String[] mas = getRealMas( str.replaceAll( " ", " " ).split( " " ) ); int index = 0; if( mas.length == 4 )//улица дом корпус квартира { entry.street = mas[index++].trim(); entry.numberHome = Utils.parseInt( mas[index++].trim() ); entry.korpus = mas[index++].trim(); entry.apartment = mas[index++].trim(); // раскидываем номер квартиры и номер комнаты entry = splitAppartmentAndRoom( entry, mas[mas.length - 1] ); if( entry.numberHome == 0 || !chekKv( entry.apartment ) ) { entry.isError = false; } } else if( mas.length == 3 )//улица дом квартира { entry.street = mas[index++].trim(); entry.numberHome = Utils.parseInt( mas[index++].trim() ); entry.apartment = mas[index++].trim(); // раскидываем номер квартиры и номер комнаты entry = splitAppartmentAndRoom( entry, mas[mas.length - 1] ); // Если квартира буква, то видимо это корпус, а квартиры нет. Их считаем неверными. Pattern pattern = Pattern.compile( "[А-Яа-яA-Za-z]?" ); Matcher matcher = pattern.matcher( entry.apartment ); if( matcher.lookingAt() ) { entry.isError = false; entry.korpus = entry.apartment; entry.apartment = null; } if( entry.numberHome == 0 || !chekKv( entry.apartment ) ) entry.isError = false; } else if( mas.length == 2 )//Номер квартиры пустой. { entry.street = mas[index++].trim(); entry.numberHome = Utils.parseInt( mas[index++].trim() ); if( entry.numberHome == 0 ) entry.isError = false; } else entry.isError = false; return entry; } private Entry splitAppartmentAndRoom( Entry entry, String value ) { String splitSymbol = null; if( value.indexOf( "/" ) > -1 ) splitSymbol = "/"; else if( value.indexOf( "-" ) > -1 ) splitSymbol = "-"; if( splitSymbol != null ) { String[] lMas = value.split( splitSymbol ); if( lMas.length == 2 ) { entry.apartment = lMas[0]; entry.room = lMas[1]; } } return entry; } /** Возвратит Street, если она существует, иначе создаст ее и вернет. */ private Street getStreet( Entry entry ) throws BGException { List<Street> streetList = addressService.streetList( cityId, entry.street ); if( streetList.size() > 0 ) { return streetList.get( 0 ); } else { Street street = new Street(); street.setCityId( cityId ); street.setCityTitle( addressService.cityGet( cityId ).getTitle() ); street.setTitle( entry.street ); street.setId( addressService.streetUpdate( street ) ); return street; } } /** * Возвращает ид дома, если он существует( проверка по названию города, дома и корпуса/дроби ) * Если дома нет, то дом будет добавлен, и возвратит его ид. * @throws BGException */ private int getHousId( Entry entry, Street street ) throws BGException { try { String korp = Utils.parseInt( entry.korpus, -1 ) > 0 && entry.korpus != null ? "/" + entry.korpus : entry.korpus; int houseId = get( street.getId(), entry.numberHome, entry.korpus == null ? "" : "/" + entry.korpus ); if( houseId > 0 ) return houseId; else { House house = new House(); house.setCityId( cityId ); house.setCityTitle( addressService.cityGet( cityId ).getTitle() ); if( entry.korpus != null ) house.setFrac( korp ); house.setStreetId( street.getId() ); house.setStreetTitle( street.getTitle() ); house.setHouse( entry.numberHome ); house.setComment( "Создан при конвертировании" ); return addressService.houseUpdate( house ); } } catch( BGException e ) { e.printStackTrace(); throw new BGException(); } catch( SQLException e ) { e.printStackTrace(); throw new BGException(); } } private String[] getRealMas( String[] mas ) { StringBuilder street = new StringBuilder(); ArrayList<String> list = new ArrayList<String>(); boolean flag = true; for( String str : mas ) { if( flag ) { if( Utils.parseInt( str, -5 ) > 0 ) { list.add( street.toString() ); list.add( str ); flag = false; } else street.append( str + " " ); } else list.add( str ); } return list.toArray( new String[1] ); } private boolean chekKv( String kv ) { if( kv == null ) return true; Pattern pattern = Pattern.compile( "\\d+[А-Яа-яA-Za-z]?" ); Matcher matcher = pattern.matcher( kv ); if( matcher.matches() ) return true; return false; } /** * Получение ид дома из таблицы домов по параметрам его. * @param streetid * @param house * @param frac * @return ид дома из таблицы address_house, или 0 если дом не найден * @throws SQLException */ private int get( int streetid, int house, String frac ) throws SQLException { int index = 1; int houseId = 0; StringBuffer query = new StringBuffer(); query.append( "SELECT id FROM address_house WHERE streetid=? AND house=?" ); //когда-то могли лобавлять просто дробь в отдельном редакторе, //а сейчас нельзя, но проверка все равно долдна быть на дробь //до сих пор не понимаю чем это удобнее (king).@костыль if( frac.startsWith( "/" ) ) { query.append( " AND ( frac=? OR frac=? )" ); } else { query.append( " AND frac=? " ); } PreparedStatement ps = con.prepareStatement( query.toString() ); ps.setInt( index++, streetid ); ps.setInt( index++, house ); ps.setString( index++, frac ); if( frac.startsWith( "/" ) ) { ps.setString( index++, frac.substring( 1 ) ); } ResultSet rs = ps.executeQuery(); if( rs.next() ) { houseId = rs.getInt( 1 ); } rs.close(); ps.close(); return houseId; } private class Entry { String street = null; int numberHome = 0; String korpus = null; String apartment = null; String room = new String(); boolean isError = true; } }