/* * Copyright 2013 Joseph Spencer. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.spencernetdevelopment; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * This class isn't thread safe. * * @author Joseph Spencer */ public class Breadcrumbs { public final Pattern CRUMB_REGEX; private final List<Breadcrumb> crumbs; private final String browserPrefix; private final String domainRelativeHtmlPagePath; private final BreadcrumbFactory factory; private boolean crumbsAreFilled; //used to prevent an infinite loop in crumb processing private int crumbsProcessed; private int maxCrumbs = 20; public Breadcrumbs( String browserPrefix, String domainRelativeHtmlPagePath, BreadcrumbFactory factory ) { if(browserPrefix == null){ throw new NullPointerException("browserPrefix was null"); } if(domainRelativeHtmlPagePath == null){ throw new NullPointerException("domainRelativeHtmlPagePath was null"); } if(browserPrefix.endsWith("/")){ throw new IllegalArgumentException("browserPrefix ended with \"/\"."); } this.browserPrefix=browserPrefix; this.domainRelativeHtmlPagePath=domainRelativeHtmlPagePath; this.crumbs = new ArrayList<>(); this.factory=factory; this.CRUMB_REGEX=Pattern .compile("^/(?:(?:[^/]+/)*([^/]+)/)?([^/]+)\\.html$"); } public boolean isEmpty(){ fillCrumbs(); return crumbs.isEmpty(); } public int size(){ fillCrumbs(); return crumbs.size(); } public Breadcrumb take(){ fillCrumbs(); return crumbs.remove(0); } /** * It's not safe to call this without obtaining a lock on crumbs first. * @throws IllegalArgumentException if maxCrumbs is exceeded during crumb * processing. */ private void fillCrumbs(){ String crumb=domainRelativeHtmlPagePath; if( !crumbsAreFilled && crumb != null ){ crumbsAreFilled = true; while(!crumb.isEmpty()){ crumbsProcessed++; if(crumbsProcessed > maxCrumbs){ throw new IllegalArgumentException( "The max number of crumbs to process was exceeded." ); } switch(crumb){ case "": case "/": case "/index.html": return; default: Matcher matcher = CRUMB_REGEX.matcher(crumb); if(matcher.find()){ String dirname = matcher.group(1); String filename = matcher.group(2); if("index".equals(filename)){ String pageLink = crumb.replaceFirst("index.html$", ""); String xmlPath = crumb .replaceFirst("index.html$", "index.xml") .replaceFirst("^/", ""); crumbs.add(0, factory.makeBreadcrumb( dirname, browserPrefix+pageLink, xmlPath )); crumb = crumb .replaceFirst(dirname+"/index.html$", "index.html"); } else { String xmlPath = crumb .replaceFirst(".html$", ".xml") .replaceFirst("^/", ""); crumbs.add(0, factory.makeBreadcrumb( filename, browserPrefix+crumb, xmlPath )); crumb = crumb .replaceFirst(filename+".html$", "index.html"); } } else { return; } } } } } }