Package framework.beans.address

Source Code of framework.beans.address.DirectoryKladrBean

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package framework.beans.address;

import framework.beans.directory.DirectoryBean;
import framework.beans.GenericEntity;
import framework.beans.address.entities.AddressDetails;
import framework.beans.address.entities.AddressObject;
import framework.beans.address.entities.AddressObjectDetails;
import framework.beans.address.entities.AddressObjectType;
import framework.generic.ClipsServerException;
import framework.security.UserRight;
import framework.security.UserRightsSetAbstract;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.ejb.Stateful;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
*  FIXME разобраться с добавлением удалением и переименованием
* @author petr
*/
@Stateful(mappedName="clips-beans/DirectoryKladrBean")
public class DirectoryKladrBean
        extends DirectoryBean<AddressObject, AddressObjectDetails>
        implements DirectoryKladrBeanRemote{

    public final static long RUSSIA_CODE = 643;
    public final static String OTHER_CODE_PREFIX = "-";


    private static final String pattern1 = "^[НЧ]{1}\\([0-9]{1,}-[0-9]{1,}\\)$";
    private static final String pattern3 = "^[0-9]{1,}-[0-9]{1,}$";
   
    private int updateCount = 0;
    private int persistCount = 0;
//    private HashSet<Integer> toDelete;
   
   
    public DirectoryKladrBean() {
        super(AddressObject.class, "адресуемый объект");
    }

    @Override
    protected UserRight getRightForCreateDirectoryItem() {
        return UserRightsSetAbstract.CREATE_DIRECTORY_COMMON_ITEM;
    }

    @Override
    protected UserRight getRightForWriteToDirectory() {
        return UserRightsSetAbstract.WRITE_REGION_ADMIN_DIRECTORY;
    }


    /**
     * Вернёт список корневых элементов
     * @return список стран
     */
    @Override
    public List<AddressObjectDetails> getDirectory() {
        Field[] f = new Field[1];
        f[0] = new Field("parent", null, Field.OPERATOR_IS_NULL);
        Iterator<AddressObject> it = findEntityList(AddressObject.class, f).iterator();
        ArrayList<AddressObjectDetails> list = new ArrayList<AddressObjectDetails>();
        while (it.hasNext()) {
            AddressObject object = it.next();
            list.add(object.getDetails(this));
        }
        return list;
    }

    /**
     * FIXME
     * @param entity
     * @param details
     * @throws ClipsServerException
     */
    @Override
    protected void set(AddressObject entity, AddressObjectDetails details) throws ClipsServerException {
        AddressObjectDetails d = details;
        AddressObject ao = entity;
        ao.setActual(false);
        ao.setIfnsCode(d.ifnsCode);
        ao.setIfnsLocalCode(d.ifnsLocalCode);
        ao.setOkato(d.okato);
        ao.setParent(d.parentItem == 0 ? null : findAddressObject(d.parentItem));
        if (d.parentItem != 0){//так обновляются дети
            //Бубен, т.к. поле кода уникальное
            Iterator it = findEntityWhat("a.kladrCode",
                                        AddressObject.class,
                                        new Field[]{new Field("actual", false),
                                                    new Field("parent", ao.getParent()),
                                                    new Field("kladrCode", "%.%", Field.OPERATOR_LIKE)},
                                        "").iterator();
            int c = 0;
            boolean hasChildren = false;
            while (it.hasNext()) {
                hasChildren = true;
                String s =(String)it.next();
                int c1 = Integer.parseInt(s.substring(s.lastIndexOf(".")+1));
                if (c1 > c){
                    c = c1;
                }
            }
            if (hasChildren){
                ao.setKladrCode(ao.getParent().getKladrCode() + "." + (c + 1));
            }else{
                ao.setKladrCode(ao.getParent().getKladrCode() + ".1");
            }
        }else{//так обновляются родители (страны)
            String code = ao.getKladrCode();
            ao.setKladrCode(d.kladrCode);
            List<AddressObject> addressObjects
                    = findEntityList(AddressObject.class,
                                    new Field[]{new Field("parent", null, Field.OPERATOR_NOT_NULL),
                                                new Field("actual", false),
                                                new Field("kladrCode", code + ".%", Field.OPERATOR_LIKE)});

            if (ao.getId() != AddressObject.ADDRESS_OBJECT_RUSSIA){
                for (AddressObject addressObject : addressObjects) {
                    String kladrCode = addressObject.getKladrCode();
                    int point = kladrCode.indexOf(".");
                    kladrCode = ao.getKladrCode() + kladrCode.substring(point);
                    addressObject.setKladrCode(kladrCode);
                }
            }

        }
        ao.setPostIndex(d.postIndex);
        ao.setTitle(d.title);
        //ao.setDirty(details.dirty);
        ao.setType(findAddressObjectType(d.typeId));
    }

    @Override
    public List<AddressObjectDetails> getItems(int parentId) throws ClipsServerException {
        AddressObject parent = findAddressObject(parentId);
        ArrayList<AddressObjectDetails> list = new ArrayList<AddressObjectDetails>();
        List<AddressObject> it = findEntityList(AddressObject.class, "parent", parent, "ORDER by a.id");
//        System.out.println("KLADR BEAN getItems for " + parent.getTitle());
        for (AddressObject addressObject : it) {
            System.out.println("          " + addressObject.getTitle());
            list.add(addressObject.getDetails(this));
        }
        return list;
    }

    @Override
    public List<AddressObjectDetails> getPath(int itemId) throws ClipsServerException {
        AddressObject object = findAddressObject(itemId);
        ArrayList<AddressObjectDetails> list = new ArrayList<AddressObjectDetails>();
        while(object != null){
            list.add(0, object.getDetails(this));
            object = object.getParent();
        }
        return list;
    }

    /**
     * синхронизует кладр
     * @param roots
     * @throws framework.generic.ClipsServerException
     */
    @Override
    public void syncDirectory(List<KladrItem> roots, Map<KladrCode, KladrCode> altnames) throws ClipsServerException {
//        toDelete = new HashSet<Integer>();
        Field[] f = new Field[]{new Field("kladrCode", altnames.values(), Field.OPERATOR_IN)};
        Iterator iterator = findEntityList(AddressObject.class, f).iterator();
        while (iterator.hasNext()) {
            AddressObject ao = (AddressObject)iterator.next();
            ao.setKladrCode(altnames.get(new KladrCode(ao.getKladrCode())).toString());
            ao.setActual(false);
            manager.merge(ao);
        }
        manager.flush();
        for (KladrItem root : roots) {
            syncRoot(root);
        }
    }

    private AddressObject findAddressObject(int id) throws ClipsServerException {
        return findEntity(AddressObject.class, id);
    }

    private AddressObjectType findAddressObjectType(int id) throws ClipsServerException {
        return findEntity(AddressObjectType.class, id);
    }


    /**
     * Синхронизует дерево начиная от корня
     * @param roots
     * @throws generic.ClipsServerException
     */
    private void syncRoot(KladrItem root) throws ClipsServerException {

        System.out.println("DIRECTORYCLADRBEAN update region: " + root);
        AddressItem region = new AddressItem(root);
        AddressObject russia = findAddressObject(AddressObject.ADDRESS_OBJECT_RUSSIA);
        Field[] f = new Field[]{new Field("kladrCode", root.kladrCode.toString().substring(0, 2).toString()+"%", Field.OPERATOR_LIKE)/*,
                                new Field("kladrCode", nextCode, Field.OPERATOR_LESS)*/};
        Iterator iterator = findEntityList(AddressObject.class, f).iterator();

        System.out.println("DIRECTORYCLADRBEAN load from db");
        int num = 0;
        while (iterator.hasNext()) {
            num++;
            if (num % 1000 == 0){
                System.out.println("DIRECTORYCLADRBEAN process records: " + num);
            }
            AddressObject addressObject = (AddressObject) iterator.next();
            KladrCode code = new KladrCode(addressObject.getKladrCode());
            AddressItem item = region.getChlidByCode(code);
            if (item == null){
                if (code.equals(root.kladrCode)){
                    region.entity = addressObject;
                }else{
                //remove this entity
//                    toDelete.add(addressObject.getId());
                    addressObject.setActual(false);
                }
            }else{
                item.entity = addressObject;
            }
        }
        System.out.println("DIRECTORYCLADRBEAN loded records: " + num);

        System.out.println("DIRECTORYCLADRBEAN update");
        updateCount = 0;
        if (region.entity == null) {
            region.entity = new AddressObject();
        }
        region.changed = fillEntity(region, russia);
         if (region.changed){
            if (region.entity.getId() == 0){
                manager.persist(region.entity);
            }else{
                region.entity = manager.merge(region.entity);
            }
        }
        updateRecoursive(region);
        System.out.println("DIRECTORYCLADRBEAN process update: " + updateCount);

//        throw new RuntimeException("Всё нормально, просто не обновляем");
        manager.flush();
        manager.flush();
        manager.flush();

//        if(!toDelete.isEmpty()){
//            System.out.println("DIRECTORYCLADRBEAN delete: " + toDelete);
//            Field[] del = new Field[]{new Field("id", toDelete, Field.OPERATOR_IN)};
//            deleteEntityList(AddressObject.class.getSimpleName(), del);
//            System.out.println("DIRECTORYCLADRBEAN process delete: " + toDelete.size());
//        }

    }



    /**
     * рекурсивно апдейтит детей
     * @param item
     * @throws generic.ClipsServerException
     */
    private void updateRecoursive(AddressItem item) throws ClipsServerException{
        for(AddressItem child : item.children){
            if (child.entity == null) {
                child.entity = new AddressObject();
            }

            child.changed = fillEntity(child, item.entity);

            if (child.changed){
                AddressObject addressObject = child.entity;
                if (addressObject.getId() == 0){
                    manager.persist(addressObject);
                }else{
                    child.entity = manager.merge(addressObject);
                }

            }
        }

        for(AddressItem child : item.children){
            if (child.children != null){
                updateRecoursive(child);
            }
        }
    }


    /**
     * Проверка на наличие циклических ссылок
     * @param object
     * @throws generic.ClipsServerException
     */
    public void checkCicrcle(AddressObject object) throws ClipsServerException{
        AddressObject current = object.getParent();
        while (current != null) {
            if (current.getKladrCode().equals(object.getKladrCode())){

                //
                ArrayList<String> items = new ArrayList<String>(0){

                    @Override
                    public String toString() {
                        String s = new String();
                        for (Object object1 : this) {
                            s+=object1;
                        }
                        return s;
                    }

                };
                items.add(object.toString());
                AddressObject current1 = object.getParent();
                while (current1 != null) {
                    if (current.getKladrCode().equals(object.getKladrCode())){
                        items.add(current1.toString());
                    }
                    current1 = current1.getParent();
                }
                throw  new ClipsServerException("Циклическая ссылка: " + items + ", замыкается на элементе: " + current);
            }
            current = current.getParent();
        }
    }

    /**
     * Заполняет сущность переданными данными
     *
     * @param entity сущность
     * @param item итем с данными
     * @param title сущность названия
     * @return was entity updated
     * @throws generic.ClipsServerException
     */
    private boolean fillEntity(AddressItem item,
                            AddressObject parent) throws ClipsServerException{

        AddressObjectType type = findAddressObjectType(item.item.typeId);
//        if ((item.entity.getParent() != null)
//                && (item.entity.getParent().getKladrCode().equals(item.entity.getKladrCode()))){
//            System.out.println("FUCKING 498: "+ item);
//        }
        if (type == null){
            throw new ClipsServerException("недопустимый тип адресуемого объекта: "
                    + item.item.title + " type id: " + item.item.typeId
                    + " обновите справочник типов");
        }
        if (item == null || item.entity == null || item.item == null){
            throw new ClipsServerException("FUCKING NULL");
        }
        if (item.entity.getIfnsCode() != item.item.ifnsCode
                || item.entity.getIfnsLocalCode() != item.item.ifnsLocalCode
                || item.entity.getOkato() != item.item.okato
                || item.entity.getPostIndex() != item.item.postIndex
                || item.entity.getTitle() == null
                    || !item.entity.getTitle().equals(item.item.title)
                || item.entity.getType() != type
                || item.entity.getKladrCode() == null
                    || !item.entity.getKladrCode().equals(item.item.kladrCode.toString())
                || item.entity.getParent() != parent
                || !item.entity.isActual()){

            updateCount++;

            item.entity.setIfnsCode(item.item.ifnsCode);
            item.entity.setIfnsLocalCode(item.item.ifnsLocalCode);
            item.entity.setOkato(item.item.okato);
            item.entity.setPostIndex(item.item.postIndex);
            item.entity.setTitle(item.item.title);
            item.entity.setType(type);
            item.entity.setKladrCode(item.item.kladrCode.toString());
            item.entity.setParent(parent);
            item.entity.setActual(true);

            checkCicrcle(item.entity);

            if (updateCount % 1000 == 0){
                System.out.println("DIRECTORYCLADRBEAN process update: " + updateCount);
            }
            return true;
        }else{
            return false;
        }

    }

    @Override
    public int getItemIDByCode(String code) throws ClipsServerException{
        while (code.length() < 19) {
            code = code + "0";
        }
        List<AddressObject> list = findEntityList(AddressObject.class, "kladrCode", code);
        if (list.size() > 0) {
            return list.get(0).getId();
        } else {
            return 0;
        }
    }

    @Override
    protected int saveEntity(GenericEntity entity) {
        return super.saveEntity(entity);
    }

    /**
     * Правит код объекта ориентируясь по номеру дома, но если передана не улица, то занулит
     * @param details
     * @return обновленные детали
     * @throws ClipsServerException
     */
    @Override
    public AddressDetails correctDetails(AddressDetails details) throws ClipsServerException {
        AddressObject street = findEntity(AddressObject.class, details.objectId);
        //really street?
        if (street != null && street.getType().getLevel() > AddressObjectType.ADDRESS_OBJECT_LEVEL_STREET){//block
            //do nothing
        }else if (street != null && street.getType().getLevel() == AddressObjectType.ADDRESS_OBJECT_LEVEL_STREET){//street
            List<AddressObject> blocks = findEntityList(AddressObject.class, "parent", street, "ORDER by a.id");
            for (AddressObject block : blocks) {
                if (include(block, details.building)){
                    details.objectId = block.getId();
                    break;
                }
            }
        }else{//not block not street - затереть данные о квартире и доме
            details.building = "";
            details.flat = "";
        }

        if (details.building.equals("0")){
            details.building = "";
        }
        if (details.flat.equals("0")){
            details.flat = "";
        }

        return details;
    }

    /**
     * Проверяет входит ли дом с данным номером в квартал
     * @param block
     * @param buildingNumber
     * @return
     */
    private boolean include(AddressObject block, String buildingNumberString){
        if (block.getType().getLevel() <= AddressObjectType.ADDRESS_OBJECT_LEVEL_STREET){
            throw new IllegalArgumentException("Переданный адресуемый объект не является кварталом: " + block);
        }else{
            int buildingNumber = 0;

            Pattern compiled = Pattern.compile("(^[0-9]+).*");
            Matcher matcher = compiled.matcher(buildingNumberString);
            boolean found = matcher.find();
            if (found) {
                String s = matcher.replaceAll("$1");
                buildingNumber = Integer.parseInt(s);
            }

            ArrayList<String> numbers = createNumbers(block);
            String s;
           
            if (!buildingNumberString.equalsIgnoreCase("" + buildingNumber)){
                for (int i = 0; i < numbers.size(); i++) {
                    s = numbers.get(i);
                    if (!Pattern.matches(pattern1, s) && !Pattern.matches(pattern3, s)) {//s не диапазон
                        if (s.equalsIgnoreCase(buildingNumberString)){
                            return true;
                        }
                    }
                }
            }

            if (buildingNumber > 0){
                for (int i = 0; i < numbers.size(); i++) {
                    s = numbers.get(i);
                    if (Pattern.matches(pattern1, s)) {//указана сторона
                        int breakPos = s.indexOf("-");
                        int start = Integer.parseInt(s.substring(2, breakPos));
                        int end = Integer.parseInt(s.substring(breakPos + 1, s.length() - 1));
                        if (buildingNumber % 2 == start % 2 &&  start <= buildingNumber && buildingNumber <= end){
                            return true;
                        }
                    } else if (Pattern.matches(pattern3, s)) {//без указания стороны
                        int breakPos = s.indexOf("-");
                        int start = Integer.parseInt(s.substring(0, breakPos));
                        int end = Integer.parseInt(s.substring(breakPos + 1, s.length()));
                        if (start <= buildingNumber && buildingNumber <= end){
                            return true;
                        }
                    }
                }
            }

            for (int i = 0; i < numbers.size(); i++) {
                s = numbers.get(i);
                matcher = compiled.matcher(s);
                found = matcher.find();
                if (found) {
                    s = matcher.replaceAll("$1");
                    if (Integer.parseInt(s) == buildingNumber){
                        return true;
                    }
                }
            }

            return false;
        }
    }

    private ArrayList<String> createNumbers(AddressObject block) {
        if (block.getType().getLevel() <= AddressObjectType.ADDRESS_OBJECT_LEVEL_STREET){
            throw new IllegalArgumentException("Переданный адресуемый объект не является кварталом");
        }else{
            String title = block.getTitle().trim();
            ArrayList<String> res = new ArrayList<String>(0);
            String s = "";
            for (int i = 0; i < title.length(); i++) {
                if (title.charAt(i) == ',') {
                    res.add(s.trim());
                    s = "";
                } else {
                    s += title.charAt(i);
                }
            }
            res.add(s.trim());
            return res;
        }
    }

    /**
     * Принимает строку в формате <субъект РФ><разделитель><район><разделитель><город><разделитель><сельслвет><разделитель><населённый пункт>
     *                              <разделитель><улица><разделитель><№ дома><разделитель><№ кормуса/строения>
     * @param address
     * @return
     */
    @Override
    public int[] findAddressObject(String address, String br){
        String[] split = address.split(br);
        int lastLevel = 0;
        ArrayList<String> compactTitles = new ArrayList<String>();
        for (int i = split.length - 1; i >= 0; i--) {
            String string = split[i].trim();
            if (!string.isEmpty() && !string.startsWith("ДОМ") && !string.startsWith("кв.")){
                compactTitles.add(string.trim());
                if (lastLevel == 0){
                    lastLevel = i + 1;
                }
            }
        }

        ArrayList<Field> fields = new ArrayList<Field>();
        String parent = "";
        for (String string : compactTitles) {
            fields.add(new Field(parent +"title", string));
            parent += "parent.";
        }
//        fields.remove(0);
//        fields.add(new Field("title", compactTitles.get(compactTitles.size()-1)));
        fields.add(new Field("type.level", lastLevel));

        List<AddressObject> list = findEntityList(AddressObject.class, fields);
       
        int[] result = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            result[i] = list.get(i).getId();
        }

        return result;
    }

}
TOP

Related Classes of framework.beans.address.DirectoryKladrBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.