class LexicalCrawlMapper extends CrawlMapper {
    @SuppressWarnings("unused")
    private static final long serialVersionUID = 2L;

    /**
     * Path to map specification file. Each line should include 2
     * whitespace-separated tokens: the first a key indicating the end of a
     * range, the second the crawler node to which URIs in the key range should
     * be mapped.  This setting is ignored if MAP_URI is specified.
     */
    protected ConfigPath mapPath = new ConfigPath("map specification file","lexicalcrawlmapper.config");
    public ConfigPath getMapPath() {
        return this.mapPath;
    }
    public void setMapPath(ConfigPath path) {
        this.mapPath = path; 
    }


    /**
     * URI to map specification file. Each line should include 2
     * whitespace-separated tokens: the first a key indicating the end of a
     * range, the second the crawler node to which URIs in the key range should
     * be mapped.  This setting takes precedence over MAP_PATH; if both are
     * specified, then MAP_PATH is ignored.
     */
    protected String mapUri = "";
    public String getMapUri() {
        return this.mapUri;
    }
    public void setMapUri(String uri) {
        this.mapUri = uri; 
    }

    protected Frontier frontier;
    public Frontier getFrontier() {
        return this.frontier;
    }
    @Autowired
    public void setFrontier(Frontier frontier) {
        this.frontier = frontier;
    }

    /**
     * Mapping of classKey ranges (as represented by their start) to 
     * crawlers (by abstract name/filename)
     */
    protected TreeMap<String, String> map = new TreeMap<String, String>();
    
    /**
     * Constructor.
     */
    public LexicalCrawlMapper() {
        super();
    }


    /**
     * Look up the crawler node name to which the given CrawlURI 
     * should be mapped. 
     * 
     * @param cauri CrawlURI to consider
     * @return String node name which should handle URI
     */
    protected String map(CrawlURI cauri) {
        // get classKey, via frontier to generate if necessary
        String classKey = frontier.getClassKey(cauri);
        SortedMap<String,String> tail = map.tailMap(classKey);
        if(tail.isEmpty()) {
            // wraparound
            tail = map;
        }
        // target node is value of nearest subsequent key
        return (String) tail.get(tail.firstKey());
    }

    public void start() {
        super.start();
        try {
            loadMap();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * Retrieve and parse the mapping specification from a local path or
     * HTTP URL. 
     * 
     * @throws IOException
     */
    protected void loadMap() throws IOException {<FILL_FUNCTION_BODY>}
}

        map.clear();
        String uri = getMapUri();
        Reader reader = null;
        if (uri.trim().length() == 0) {
            File source = getMapPath().getFile();
            reader = new FileReader(source);
        } else {
            URLConnection conn = (new URL(uri)).openConnection();
            reader = new InputStreamReader(conn.getInputStream());
        }
        reader = new BufferedReader(reader);
        Iterator<String> iter = 
            new RegexLineIterator(
                    new LineReadingIterator((BufferedReader) reader),
                    RegexLineIterator.COMMENT_LINE,
                    RegexLineIterator.TRIMMED_ENTRY_TRAILING_COMMENT,
                    RegexLineIterator.ENTRY);
        while (iter.hasNext()) {
            String[] entry = ((String) iter.next()).split("\\s+");
            map.put(entry[0],entry[1]);
        }
        reader.close();
    
<methods>public void <init>() ,public boolean getCheckOutlinks() ,public boolean getCheckUri() ,public org.archive.spring.ConfigPath getDiversionDir() ,public java.lang.String getLocalName() ,public org.archive.modules.deciderules.DecideRule getOutlinkRule() ,public int getRotationDigits() ,public boolean isRunning() ,public void setCheckOutlinks(boolean) ,public void setCheckUri(boolean) ,public void setDiversionDir(org.archive.spring.ConfigPath) ,public void setLocalName(java.lang.String) ,public void setOutlinkRule(org.archive.modules.deciderules.DecideRule) ,public void setRotationDigits(int) ,public void start() ,public void stop() <variables>protected org.archive.util.fingerprint.ArrayLongFPCache cache,protected boolean checkOutlinks,protected boolean checkUri,protected org.archive.spring.ConfigPath diversionDir,protected HashMap<java.lang.String,java.io.PrintWriter> diversionLogs,protected java.lang.String localName,protected java.lang.String logGeneration,protected org.archive.modules.deciderules.DecideRule outlinkRule,protected int rotationDigits