/*
GNU GENERAL PUBLIC LICENSE
Copyright (C) 2006 The Lobo Project
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
verion 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Contact info: lobochief@users.sourceforge.net
*/
package org.lobobrowser.gui;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lobobrowser.request.DomainValidation;
import org.lobobrowser.ua.NavigationEntry;
import org.lobobrowser.util.Urls;
/**
* This class stores navigation back/forward state for a frame.
* <p>
* Note: This class is not thread safe on its own.
*/
final public class NavigationEngine {
private static final Logger logger = Logger.getLogger(NavigationEngine.class.getName());
private final ArrayList<NavigationEntry> history = new ArrayList<>();
private int currentIndex = -1;
public NavigationEntry getCurrentEntry() {
try {
return this.history.get(this.currentIndex);
} catch (final IndexOutOfBoundsException iob) {
return null;
}
}
public void addNavigationEntry(final NavigationEntry entry) {
/*
if (logger.isLoggable(Level.INFO)) {
logger.info("addNavigationEntry(): entry=" + entry);
}
*/
final int newIndex = this.currentIndex + 1;
if (newIndex == this.history.size()) {
this.history.add(entry);
} else {
if (newIndex > this.history.size()) {
throw new IllegalStateException("currentIndex=" + this.currentIndex + ",size=" + this.history.size());
}
this.history.set(newIndex, entry);
}
this.currentIndex = newIndex;
final int nextIndex = newIndex + 1;
while (nextIndex < this.history.size()) {
this.history.remove(nextIndex);
}
}
public boolean hasNext() {
return (this.currentIndex + 1) < this.history.size();
}
public boolean hasPrev() {
return this.currentIndex > 0;
}
public boolean hasNextWithGET() {
return this.hasNewEntryWithGET(+1);
}
public boolean hasPrevWithGET() {
return this.hasNewEntryWithGET(-1);
}
public boolean hasNewEntryWithGET(final int offset) {
int nextIndex = this.currentIndex;
for (;;) {
nextIndex += offset;
if ((nextIndex >= 0) && (nextIndex < this.history.size())) {
final NavigationEntry entry = this.history.get(nextIndex);
if ("GET".equals(entry.getMethod())) {
return true;
} else {
continue;
}
} else {
return false;
}
}
}
public NavigationEntry back() {
return this.move(-1);
}
public NavigationEntry forward() {
return this.move(+1);
}
public NavigationEntry move(final int offset) {
final int nextIndex = this.currentIndex + offset;
if ((nextIndex >= 0) && (nextIndex < this.history.size())) {
this.currentIndex = nextIndex;
return this.history.get(this.currentIndex);
} else {
return null;
}
}
public boolean moveTo(final NavigationEntry entry) {
final int newIndex = this.history.indexOf(entry);
if (newIndex == -1) {
return false;
}
this.currentIndex = newIndex;
return true;
}
public List<NavigationEntry> getForwardNavigationEntries() {
final ArrayList<NavigationEntry> entries = new ArrayList<>();
int index = this.currentIndex + 1;
final int size = this.history.size();
while (index < size) {
entries.add(this.history.get(index));
index++;
}
return entries;
}
/**
* Gets prior navigation entries, in descending order.
*/
public List<NavigationEntry> getBackNavigationEntries() {
final ArrayList<NavigationEntry> entries = new ArrayList<>();
int index = this.currentIndex - 1;
while (index >= 0) {
entries.add(this.history.get(index));
index--;
}
return entries;
}
public NavigationEntry findEntry(final String absoluteURL) {
try {
final java.net.URL targetURL = DomainValidation.guessURL(absoluteURL);
for (final NavigationEntry entry : this.history) {
if (Urls.sameNoRefURL(targetURL, entry.getUrl())) {
return entry;
}
}
return null;
} catch (final java.net.MalformedURLException mfu) {
if (logger.isLoggable(Level.INFO)) {
logger.log(Level.INFO, "findEntry(): URL is malformed: " + absoluteURL, mfu);
}
return null;
}
}
public int getLength() {
return this.history.size();
}
}