/*
* Copyright (2007-2012) Schibsted ASA
* This file is part of Possom.
*
* Possom is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Possom 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Possom. If not, see <http://www.gnu.org/licenses/>.
*/
package no.sesat.search.view.navigation;
import no.sesat.search.datamodel.DataModel;
import no.sesat.search.datamodel.generic.StringDataObject;
import org.apache.log4j.Logger;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
/**
* Class responsible for assembling the current navigation state.
*
*
*
* @version $Id$
*/
public final class NavigationManager {
private static final Logger LOG = Logger.getLogger(NavigationManager.class);
private final DataModel dataModel;
private final Map<String, String> parameters;
/**
* Creates a new NavigationManager.
*
* @param dataModel The datamodel.
*/
public NavigationManager(final DataModel dataModel) {
this.dataModel = dataModel;
parameters = new HashMap<String, String>();
for (final NavigationConfig.Navigation n : dataModel.getNavigation().getConfiguration().getNavigationList()) {
parameters.putAll(new Generator(n).getParameters());
}
}
/**
* Returns the navigation state that should be persisted for a particular navigator. The state differs between
* different navigators because there are things like the reset and is-out functionality.
*
* @see no.sesat.search.view.navigation.NavigationConfig.Navigation#resetNavSet
* @see no.sesat.search.view.navigation.NavigationConfig.Nav#isOut
*
* @return the navigation state for the given navigator.
*/
public NavigationState getNavigationState() {
return new NavigationState() {
/**
* Returns the set of parameters that should be kept when navigating the given navigator.
*
* @param nav the navigation.
*
* @return the set of parameters.
*
*/
public Set<String> getParameterNames(final NavigationConfig.Nav nav, final boolean reset) {
/*
* @todo come up with a data structure that does not require us to create new sets.
*/
if (nav.getId() != null && !nav.isOut()) {
final Set<String> pNames = new HashSet<String>(parameters.keySet());
if (! nav.getNavigation().getResetNavSet().isEmpty()) {
pNames.removeAll(nav.getNavigation().getResetNavSet());
}
if (reset) {
reset(pNames, nav);
} else {
for (NavigationConfig.Nav child : nav.getChildNavs()) {
reset(pNames, child);
}
}
return pNames;
} else {
return new HashSet<String>(2);
}
}
/**
* Returns the value for the given navigation parameter.
*
* @param nav the navigator.
* @param parameterName the parameter.
*
* @return the value of the parameter. UTF-8 URL ENCODED.
*/
public String getParameterValue(final NavigationConfig.Nav nav, final String parameterName) {
final String value = parameters.get(parameterName);
if (null == value && null != dataModel.getParameters().getValue(parameterName)) {
return dataModel.getParameters().getValue(parameterName).getUtf8UrlEncoded();
}
return value;
}
private void reset(final Set<String> pNames, final NavigationConfig.Nav nav) {
pNames.remove(nav.getId());
for (NavigationConfig.Nav child: nav.getChildNavs()) {
reset(pNames, child);
}
}
};
}
private class Generator {
private final NavigationConfig.Navigation navigation;
private final Map<String, String> parameters = new HashMap<String, String>();
public Generator(final NavigationConfig.Navigation navigation) {
this.navigation = navigation;
addNavigationFragments();
}
public Map<String, String> getParameters() {
return parameters;
}
private void addNavigationFragments() {
final Set<String> fieldFilterSet = new HashSet<String>();
for (final NavigationConfig.Nav nav : navigation.getNavList()) {
addNavigationFragment(fieldFilterSet, nav);
}
}
private void addNavigationFragment(
final Set<String> fieldFilterSet,
final NavigationConfig.Nav nav) {
StringDataObject fieldValue = dataModel.getParameters().getValue(nav.getField());
if (!fieldFilterSet.contains(nav.getField())) {
addPreviousField(fieldValue, nav.getField());
fieldFilterSet.add(nav.getField());
for (NavigationConfig.Nav childNav : nav.getChildNavs()) {
addNavigationFragment(fieldFilterSet, childNav);
}
}
}
private void addPreviousField(StringDataObject fieldValue, final String fieldName) {
if (fieldValue != null) {
parameters.put(enc(fieldName), enc(fieldValue.getString()));
}
}
private String enc(final String str) {
try {
return URLEncoder.encode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
LOG.error(e);
return str;
}
}
}
}