package me.osm.gazetter; import groovy.lang.GroovyClassLoader; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import me.osm.gazetter.addresses.AddrLevelsComparator; import me.osm.gazetter.addresses.AddrLevelsSorting; import me.osm.gazetter.addresses.AddressesParser; import me.osm.gazetter.addresses.AddressesParserFactory; import me.osm.gazetter.addresses.NamesMatcher; import me.osm.gazetter.addresses.impl.AddrTextFormatterImpl; import me.osm.gazetter.addresses.impl.AddressesParserFactoryImpl; import me.osm.gazetter.addresses.impl.AddressesParserImpl; import me.osm.gazetter.addresses.impl.AddressesSchemesParserImpl; import me.osm.gazetter.addresses.impl.NamesMatcherImpl; import me.osm.gazetter.addresses.sorters.CityStreetHNComparator; import me.osm.gazetter.addresses.sorters.HNStreetCityComparator; import me.osm.gazetter.addresses.sorters.StreetHNCityComparator; import me.osm.gazetter.join.out_handlers.GazetteerOutWriter; import me.osm.gazetter.join.out_handlers.JoinOutHandler; import me.osm.gazetter.join.out_handlers.PrintJoinOutHandler; import me.osm.gazetter.out.CSVOutWriter; import org.apache.commons.lang3.StringUtils; /** * Stores command line provided options. * */ public class Options { /** * Options should be red once on startup * */ public static final class SecondaryOptionsInitializationException extends RuntimeException { private static final long serialVersionUID = -2739610432163207207L; } private static final Map<String, JoinOutHandler> predefinedJoinOutHandlers = new HashMap<String, JoinOutHandler>(); static { predefinedJoinOutHandlers.put(PrintJoinOutHandler.NAME, new PrintJoinOutHandler()); predefinedJoinOutHandlers.put(GazetteerOutWriter.NAME, new GazetteerOutWriter()); predefinedJoinOutHandlers.put(CSVOutWriter.NAME, new CSVOutWriter()); } /** * Names of JoinOutHandler available by name from command line. * * @return names * */ public static Collection<String> getPredefinedOutHandlers() { return predefinedJoinOutHandlers.keySet(); } private static volatile Options instance; private final AddrLevelsSorting sorting; private final AddressesParser addressesParser; private final NamesMatcher namesMatcher; private boolean findLangsLevel; private int nThreads = Runtime.getRuntime().availableProcessors(); private boolean compress = true; private List<JoinOutHandler> joinHandlers = new ArrayList<>(); private Options() { sorting = AddrLevelsSorting.HN_STREET_CITY; addressesParser = new AddressesParserImpl(); namesMatcher = new NamesMatcherImpl(); this.findLangsLevel = false; } private Options(AddrLevelsSorting sorting, AddressesParser addressesParser, NamesMatcher namesMatcher, boolean findLangs) { this.sorting = sorting; this.addressesParser = addressesParser; this.namesMatcher = namesMatcher; this.findLangsLevel = findLangs; } /** * Initialize singleton with parameters * * @param sorting * Sorter for addresses parts * @param groovyFormatter * Path to groovy file with {@link AddressesParserFactory} * @param skippInFullText * Addr levels which should be skipped at full address text generation * @param findLangs * Look for addresses translations * */ public static void initialize(AddrLevelsSorting sorting, String groovyFormatter, Set<String> skippInFullText, boolean findLangs) { if(instance != null) { throw new SecondaryOptionsInitializationException(); } AddressesParser adrParser = getAddrParser(groovyFormatter, sorting, skippInFullText, findLangs); instance = new Options(sorting, adrParser, new NamesMatcherImpl(), findLangs); } private static AddressesParser getAddrParser(String groovyFormatter, AddrLevelsSorting sorting, Set<String> skippInFullText, boolean findLangs) { AddressesParser adrParser = null; try { AddrLevelsComparator addrLevelComparator; if(AddrLevelsSorting.HN_STREET_CITY == sorting) { addrLevelComparator = new HNStreetCityComparator(); } else if (AddrLevelsSorting.CITY_STREET_HN == sorting) { addrLevelComparator = new CityStreetHNComparator(); } else { addrLevelComparator = new StreetHNCityComparator(); } if(!StringUtils.isEmpty(groovyFormatter)) { GroovyClassLoader gcl = new GroovyClassLoader(Options.class.getClassLoader()); try { Class<?> clazz = gcl.parseClass(new File(groovyFormatter)); Object aScript = clazz.newInstance(); if(aScript instanceof AddressesParserFactory) { AddressesParserFactory factory = (AddressesParserFactory) aScript; adrParser = factory.newAddressesParser( new AddressesSchemesParserImpl(), addrLevelComparator, new NamesMatcherImpl(), Arrays.asList("place:hamlet", "place:village", "place:town", "place:city", "boundary:8"), new AddrTextFormatterImpl(), sorting, skippInFullText, findLangs); } else if(aScript instanceof AddressesParser) { adrParser = (AddressesParser) aScript; } } finally { gcl.close(); } } else { AddressesParserFactory defFactory = new AddressesParserFactoryImpl(); adrParser = defFactory.newAddressesParser( new AddressesSchemesParserImpl(), addrLevelComparator, new NamesMatcherImpl(), Arrays.asList("place:hamlet", "place:village", "place:town", "place:city", "boundary:8"), new AddrTextFormatterImpl(), sorting, skippInFullText, findLangs); } } catch (Exception e) { throw new RuntimeException(e); } return adrParser; } /** * Instance getter * * @return initialized Options * */ public static Options get() { if(instance == null) { synchronized (Options.class) { if(instance == null) { instance = new Options(); } } } return instance; } /** * How to sort addresses parts * * @return {@link AddrLevelsSorting} * */ public AddrLevelsSorting getSorting() { return sorting; } /** * AddressesParser specified via groovy or default instance * * @return {@link AddressesParser} * */ public AddressesParser getAddressesParser() { return addressesParser; } /** * Names matcher * * @return {@link NamesMatcher} * */ public NamesMatcher getNamesMatcher() { return namesMatcher; } /** * Should we try to find addresses translations or not * * @return findLangs * */ public boolean isFindLangs() { return findLangsLevel; } /** * Number of threads available for ExecutorServices * * @return nThreads * */ public int getNumberOfThreads () { return this.nThreads; } /** * Number of threads available for ExecutorServices * * @param nThreads * Number of threads * */ public void setNThreads(int nThreads) { this.nThreads = nThreads; } /** * Use GunZip compression for tmp files * * @param compress * <code>true</code> use compression * */ public void setCompress(boolean compress) { this.compress = compress; } /** * Use GunZip compression for tmp files * * @return compress * */ public boolean isCompress() { return compress; } /** * Specify join handlers * * @See JoinOutHandler * * @param handlers * Handlers definition, name of groovy file path * */ public void setJoinHandlers(List<String> handlers) { try { if (handlers != null && !handlers.isEmpty()) { List<List<String>> groups = new ArrayList<List<String>>(); for(String sh : handlers) { if(sh.endsWith(".groovy") || predefinedJoinOutHandlers.keySet().contains(sh)) { groups.add(new ArrayList<String>()); } if(groups.isEmpty()) { return; } groups.get(groups.size() - 1).add(sh); } for(List<String> handlerDef : groups) { String handlerPath = handlerDef.remove(0); if(handlerPath.endsWith(".groovy")) { GroovyClassLoader gcl = new GroovyClassLoader(Options.class.getClassLoader()); try { Class<?> clazz = gcl.parseClass(new File(handlerPath)); Object aScript = clazz.newInstance(); if (aScript instanceof JoinOutHandler) { JoinOutHandler joinOutHandler = ((JoinOutHandler)aScript); joinOutHandler = joinOutHandler.initialize(joinOutHandler.parseHandlerOptions(handlerDef)); joinHandlers.add(joinOutHandler); } } finally { gcl.close(); } } else if (predefinedJoinOutHandlers.containsKey(handlerPath)){ JoinOutHandler joinOutHandler = predefinedJoinOutHandlers.get(handlerPath); joinHandlers.add(joinOutHandler.initialize(joinOutHandler.parseHandlerOptions(handlerDef))); } } } } catch (Exception e) { throw new RuntimeException(e); } if(joinHandlers.isEmpty()) { joinHandlers.add(predefinedJoinOutHandlers.get( GazetteerOutWriter.NAME).initialize( new GazetteerOutWriter().parseHandlerOptions(new ArrayList<String>()))); } } /** * Collection of parsed JoinOutHandler * * @see JoinOutHandler * * @return joinHandlers * */ public Collection<JoinOutHandler> getJoinOutHandlers() { return joinHandlers; } }