All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.unlaxer.jaddress.parser.processor.PrefectureToTownNameTokenizer Maven / Gradle / Ivy

package org.unlaxer.jaddress.parser.processor;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.unlaxer.jaddress.entity.standard.定義済みRange階層要素;
import org.unlaxer.jaddress.entity.standard.階層要素;
import org.unlaxer.jaddress.entity.zip.ZipBasedAddress;
import org.unlaxer.jaddress.parser.AddressContext;
import org.unlaxer.jaddress.parser.AddressElement;
import org.unlaxer.jaddress.parser.AddressElementFactory;
import org.unlaxer.jaddress.parser.AddressProcessor;
import org.unlaxer.jaddress.parser.IntermediateResult;
import org.unlaxer.jaddress.parser.ParsingState;
import org.unlaxer.jaddress.parser.ParsingTarget;
import org.unlaxer.jaddress.parser.ResolverResultKind;
import org.unlaxer.jaddress.parser.ResolverResultKindOfMatchKind;
import org.unlaxer.jaddress.parser.SeparatorKind;
import org.unlaxer.jaddress.parser.StringAndCharacterKinds;
import org.unlaxer.jaddress.parser.StringIndex;
import org.unlaxer.jaddress.parser.TargetStateAndElement;
import org.unlaxer.util.collection.TreeNode;
import org.unlaxer.util.function.Unchecked;

public class PrefectureToTownNameTokenizer implements AddressProcessor {

	@Override
	public ParsingState targetState() {
		return ParsingState.都道府県から町名までを分割する;
	}

	@Override
	public TargetStateAndElement process(ParsingTarget parsingTarget) {
		
		AddressContext addressContext = parsingTarget.addressContext();
		IntermediateResult intermediateResult = parsingTarget.intermediateResult();
		
		TreeNode targetNode = targetNode(parsingTarget);
		
		StringAndCharacterKinds address = addressContext.addressString();
		
		List> allResults = new ArrayList<>();
		
		
		for (ZipBasedAddress zipBasedAddress : intermediateResult.zipBasedAddressesFromZip()) {
			
			StringIndex currentIndex = new StringIndex(0);
			List results = new ArrayList<>();
			
			// 1:都道府県 その他
			currentIndex = search(parsingTarget , addressContext, targetNode, address, 
				currentIndex,zipBasedAddress.kenName()  ,results ,  階層要素.都道府県)
					.map(SearchResult::next)
					.orElse(currentIndex);
			
			// 2 市, 東京23区, 政令指定市, 群
			currentIndex = search(parsingTarget , addressContext, targetNode, address, 
				currentIndex, zipBasedAddress.cityName() ,results , 階層要素.市)
					.map(SearchResult::next)
					.orElse(currentIndex);


			// 3:区,町村
			currentIndex = search(parsingTarget , addressContext, targetNode, address, 
				currentIndex, zipBasedAddress.townName() , results , 階層要素.町村)
					.map(SearchResult::next)
					.orElse(currentIndex);
			
			// 4:町または大字 ?
// FIXME!!
//			currentIndex = search(parsingTarget , addressContext, targetNode, address, 
//				currentIndex, zipBasedAddress.kyotoStreet() , results , 階層要素.町または大字)
//					.map(SearchResult::next)
//					.orElse(currentIndex);
			
			boolean allMatch = results.stream()
				.allMatch(SearchResult::isValid);
			
			if(allMatch && results.size() ==4) {
				return process(addressContext , targetNode , results);
			}else {
				allResults.add(results);
			}
		}
		List results = select(allResults);
		
		return process(addressContext , targetNode , results);
	}
	
	private List select(List> allResults) {
		allResults.sort(
			(list1,list2)->
				level(list2) - level(list1)
		);
		List list = allResults.get(0);
		return list;
	}
	
	public int level(List results) {
		return results.isEmpty() ?
				0 :
				results.get(results.size()-1).next.value;
	}

	private TargetStateAndElement process(
			AddressContext addressContext,
			TreeNode targetNode, List results) {
		
		if(results.isEmpty()) {
			return new TargetStateAndElement(ParsingState.町名分割エラー , 定義済みRange階層要素.全体);
		}
		
		SearchResult lastSearchResult = results.get(results.size()-1);
		
		if(lastSearchResult._階層要素.level <= 階層要素.区.level) {
			return new TargetStateAndElement(ParsingState.町名分割エラー , 定義済みRange階層要素.全体);
		}
		
		
		results.stream()
			.forEach(SearchResult::run);
		
		StringIndex next = lastSearchResult.next();
		
		StringAndCharacterKinds substring = 
				addressContext.addressString().substring(next, SeparatorKind.domainSpecificSeparator, SeparatorKind.terminator);
		
		addressContext.addChild(
			targetNode, 
			AddressElementFactory.of(substring, 定義済みRange階層要素.町名より後 , 
				SeparatorKind.domainSpecificSeparator , SeparatorKind.domainSpecificSeparator 
			)
		);
		
		return new TargetStateAndElement(ParsingState.町名から丁目の階層種類をDBを用いて求める , 定義済みRange階層要素.町名より後);
	}

	private Optional search(
			ParsingTarget parsingTarget,
			AddressContext addressContext, 
			TreeNode targetNode,
			StringAndCharacterKinds address, 
			StringIndex currentIndex, 
			String nameOfPart,
			List results,
			階層要素 _階層要素) {
		
		Optional search = 
				search(addressContext, targetNode, address, currentIndex, nameOfPart, _階層要素);
		
		search.ifPresent(result->{
			results.add(result);
			ResolverResultKind resolverResultKind = null;
			switch (_階層要素) {
			case 都道府県:
				resolverResultKind = ResolverResultKindOfMatchKind.郵便番号辞書match都道府県;
				break;
			case 市:
				resolverResultKind = ResolverResultKindOfMatchKind.郵便番号辞書match市;
				break;
			case 町村:
				resolverResultKind = ResolverResultKindOfMatchKind.郵便番号辞書match町村;
				break;
			case 町または大字:
				resolverResultKind = ResolverResultKindOfMatchKind.郵便番号辞書match町または大字;
				break;
			default:
				throw new IllegalArgumentException();
			}
			parsingTarget.addResolverResult(resolverResultKind);
		});
		return search;
	}


	private Optional search(
			AddressContext addressContext, 
			TreeNode targetNode,
			StringAndCharacterKinds address, 
			StringIndex currentIndex, 
			String nameOfPart,
			階層要素 _階層要素) {
		
		if (false == isEmpty(nameOfPart)) {
			
			StringIndex indexOf = address.indexOf(nameOfPart, currentIndex);
			
			if(indexOf.isValid()) {
				return Optional.of( 
					new SearchResult(_階層要素 , indexOf, indexOf.plus(nameOfPart.length()), 
						()->{
							addressContext.addChild(
								targetNode, 
								AddressElementFactory.of(nameOfPart, _階層要素 , 
									SeparatorKind.domainSpecificSeparator , SeparatorKind.domainSpecificSeparator 
								)
							);
						}
					)
				);
			}else {
				Optional.of(
					new SearchResult(_階層要素 , StringIndex.invalid(), currentIndex,()->{})
				);
			}
		}
		return Optional.empty();
	}
	
	static class SearchResult implements Runnable{
		public final 階層要素 _階層要素;
		public final StringIndex indexOf;
		public final StringIndex next;
		public final Runnable runnable;
		public SearchResult(階層要素 _階層要素 , StringIndex indexOf, StringIndex next , Runnable runnable) {
			super();
			this._階層要素 = _階層要素;
			this.next = next;
			this.indexOf = indexOf;
			this.runnable = runnable;
		}
		public boolean isValid() {
			return indexOf.isValid();
		}
		
		public StringIndex next() {
			return next;
		}
		
		@Override
		public void run() {
			Unchecked.run(()->runnable.run());
		}
	}
	
	static boolean isEmpty(String word) {
		return word == null || word.equalsIgnoreCase("NULL") || word.isEmpty(); 
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy