All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.izforge.izpack.installer.panel.AbstractPanels Maven / Gradle / Ivy

The newest version!
/*
 * IzPack - Copyright 2001-2012 Julien Ponge, All Rights Reserved.
 *
 * http://izpack.org/
 * http://izpack.codehaus.org/
 *
 * Copyright 2012 Tim Anderson
 *
 * 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.izforge.izpack.installer.panel;


import com.izforge.izpack.api.adaptator.IXMLElement;
import com.izforge.izpack.api.adaptator.IXMLWriter;
import com.izforge.izpack.api.adaptator.impl.XMLWriter;
import com.izforge.izpack.api.data.InstallData;
import com.izforge.izpack.api.data.Panel;
import com.izforge.izpack.api.data.Variables;
import com.izforge.izpack.api.exception.IzPackException;
import com.izforge.izpack.installer.data.UninstallData;
import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Abstract implementation of the {@link PanelViews} interface.
 *
 * @author Tim Anderson
 */
public abstract class AbstractPanels, V> implements PanelViews
{

    /**
     * The panels.
     */
    private final List panels;

    /**
     * The panel views.
     */
    private final List panelViews;

    /**
     * The installation data.
     */
    private final InstallData installData;

    /**
     * The variables.
     */
    private final Variables variables;

    /**
     * The current panel index.
     */
    private int index = -1;

    /**
     * Determines if the next panel may be navigated to, if any.
     */
    private boolean nextEnabled;

    /**
     * Determines if the previous panel may be navigated to, if any.
     */
    private boolean previousEnabled;

    /**
     * The logger.
     */
    private static final Logger logger = Logger.getLogger(AbstractPanels.class.getName());

    /**
     * Constructs an {@code AbstractPanels}.
     *
     * @param panels    the panels
     * @param installData
     */
    public AbstractPanels(List panels, InstallData installData)
    {
        this.panels = new ArrayList();
        this.panelViews = panels;
        this.installData = installData;
        this.variables = installData.getVariables();
        nextEnabled = !panels.isEmpty();
        int index = 0;
        for (T panelView : panels)
        {
            panelView.setIndex(index++);
            this.panels.add(panelView.getPanel());
        }
    }

    /**
     * Returns the panels.
     *
     * @return the panels
     */
    @Override
    public List getPanels()
    {
        return panels;
    }

    /**
     * Returns the current panel.
     *
     * @return the current panel, or {@code null} if there is no current panel
     */
    @Override
    public Panel getPanel()
    {
        return (index >= 0 && index < panels.size()) ? panels.get(index) : null;
    }

    /**
     * Returns the panel views.
     *
     * @return the panel views
     */
    @Override
    public List getPanelViews()
    {
        return panelViews;
    }

    /**
     * Returns the current view.
     *
     * @return the current view, or {@code null} if there is none
     */
    @Override
    public V getView()
    {
        T panelView = getPanelView();
        return panelView != null ? panelView.getView() : null;
    }

    /**
     * Returns the current panel view.
     *
     * @return the current panel view, or {@code null} if there is none
     */
    @Override
    public T getPanelView()
    {
        return getPanelView(index);
    }

    /**
     * Determines if the current panel is valid.
     *
     * @return {@code true} if the current panel is valid
     */
    @Override
    public boolean isValid()
    {
        T panel = getPanelView();
        return panel == null || executeValidationActions(panel, true);
    }

    /**
     * Returns the current panel index.
     *
     * @return the current panel index, or {@code -1} if there is no current panel
     */
    @Override
    public int getIndex()
    {
        return index;
    }

    /**
     * Determines if there is another panel after the current panel.
     *
     * @return {@code true} if there is another panel
     */
    @Override
    public boolean hasNext()
    {
        return getNext(index, false) != -1;
    }

    /**
     * Navigates to the next panel.
     * 
* Navigation can only occur if the current panel is valid. * * @return {@code true} if the next panel was navigated to */ @Override public boolean next() { return next(true); } /** * Navigates to the next panel. * * @param validate if {@code true}, only move to the next panel if validation succeeds * @return {@code true} if the next panel was navigated to */ @Override public boolean next(boolean validate) { boolean result = false; // Evaluate and set variables for current panel before verifying panel conditions if (!validate || isValid()) { int newIndex = getNext(index, false); if (newIndex != -1) { result = switchPanel(newIndex, validate); } } return result; } /** * Determines if there is panel prior to the current panel. * * @return {@code true} if there is a panel prior to the current panel */ @Override public boolean hasPrevious() { return getPrevious(index, false) != -1; } /** * Navigates to the previous panel. * * @return {@code true} if the previous panel was navigated to */ @Override public boolean previous() { return previous(index); } /** * Navigates to the panel before the specified index. *
* The target panel must be before the current panel. * * @return {@code true} if the previous panel was navigated to */ @Override public boolean previous(int index) { boolean result = false; if (hasPrevious()) { int newIndex = getPrevious(index, true); if (newIndex != -1) { result = switchPanel(newIndex, false); } } return result; } /** * Determines if there is another panel after the specified index. * * @param index the panel index * @param visibleOnly if {@code true}, only examine visible panels * @return {@code true} if there is another panel */ @Override public int getNext(int index, boolean visibleOnly) { int result = -1; List panels = getPanelViews(); for (int i = index + 1; i < panels.size(); ++i) { if (canShow(panels.get(i), visibleOnly)) { result = i; break; } } return result; } /** * Determines if there is another panel after the current index. * * @param visibleOnly if {@code true}, only examine visible panels * @return {@code true} if there is another panel */ @Override public int getNext(boolean visibleOnly) { return getNext(index, visibleOnly); } /** * Determines if there is another panel prior to the specified index. * * @param index the panel index * @param visibleOnly if {@code true}, only examine visible panels * @return the previous panel index, or {@code -1} if there are no more panels */ @Override public int getPrevious(int index, boolean visibleOnly) { int result = -1; for (int i = index - 1; i >= 0; --i) { if (canShow(getPanelView(i), visibleOnly)) { result = i; break; } } return result; } /** * Determines if there is another panel prior to the specified index. * * @param visibleOnly if {@code true}, only examine visible panels * @return the previous panel index, or {@code -1} if there are no more panels */ @Override public int getPrevious(boolean visibleOnly) { return getPrevious(index, visibleOnly); } /** * Returns the index of a visible panel, relative to other visible panels. * * @param panel the panel * @return the panel's visible index, or {@code -1} if the panel is not visible */ @Override public int getVisibleIndex(T panel) { int result = -1; if (panel.isVisible()) { for (int i = 0; i <= panel.getIndex() && i < panelViews.size(); ++i) { if (panelViews.get(i).isVisible()) { result++; } } } return result; } /** * Returns the number of visible panels. * * @return the number of visible panels */ @Override public int getVisible() { int result = 0; for (T panelView : panelViews) { if (panelView.isVisible()) { ++result; } } return result; } @Override public void writeInstallationRecord(File file, UninstallData uninstallData) throws Exception { FileOutputStream out = null; try { out = new FileOutputStream(file); IXMLWriter writer = new XMLWriter(out); IXMLElement panelsRoot = installData.getInstallationRecord(); for (T panelView : panelViews) { Panel panel = panelView.getPanel(); if (panel.isVisited()) { IXMLElement panelRoot = panelView.createPanelRootRecord(); //AbstractPanelView panelView.createInstallationRecord(panelRoot); panelsRoot.addChild(panelRoot); } } writer.write(panelsRoot); } finally { IOUtils.closeQuietly(out); //Only remove the automatic installation for if its placed in installation path //We would like to contain any removal of data within the install path if(file.getAbsolutePath().startsWith(installData.getInstallPath())) { uninstallData.addFile(file.getAbsolutePath(), true); } } } /** * TODO: validate parameter not used - refactor this * Switches panels. * * @param newIndex the index of the new panel * @return {@code true} if the switch was successful */ public boolean switchPanel(int newIndex, boolean validate) { boolean result; T panel = getPanelView(); //Save data on every panel switch if(panel != null) { panel.saveData(); } if ((newIndex > index) && !hasNext()) // NOTE: actions may change isNextEnabled() status { return false; } try { // refresh variables prior to switching panels variables.refresh(); T oldPanelView = getPanelView(index); T newPanelView = getPanelView(newIndex); int oldIndex = index; index = newIndex; Panel newPanel = newPanelView.getPanel(); newPanel.setVisited(true); if (switchPanel(newPanelView, oldPanelView)) { if (oldIndex > newIndex) { // Switches back in a sorted list of panels // -> set unvisited all panels in order after this one to always keep history information up to date // -> important for summary panel and generation of auto-install.xml for (int i = panelViews.size() - 1; i > index; i--) { T futurePanelView = panelViews.get(i); Panel futurePanel = futurePanelView.getPanel(); futurePanel.setVisited(false); Set blockedNames = futurePanel.getAffectedVariableNames(); variables.unregisterBlockedVariableNames(futurePanel.getAffectedVariableNames(), futurePanel); if( logger.isLoggable(Level.FINE)) { logger.fine("Unblocked variables on panel '" + futurePanel.getPanelId() +"': " + createListAsString(blockedNames)); } } } else { Set blockedNames = newPanel.getAffectedVariableNames(); variables.registerBlockedVariableNames(blockedNames, newPanel); if( logger.isLoggable(Level.FINE)) { logger.fine("Blocked variables on panel '" + newPanel.getPanelId() +"': " + createListAsString(blockedNames)); } } logger.fine("Switched panel index: " + oldIndex + " -> " + index); result = true; } else { index = oldIndex; result = false; newPanel.setVisited(false); } variables.refresh(); } catch (IzPackException e) { result = false; getPanelView().getHandler().emitError(null, e.getMessage()); } return result; } private String createListAsString(Set list) { StringBuffer msg = new StringBuffer("{"); if (list != null) { Iterator it = list.iterator(); while (it.hasNext()) { if( logger.isLoggable(Level.FINE)) { msg.append(it.next()); if (it.hasNext()) { msg.append(", "); } } } } msg.append("}"); return msg.toString(); } /** * Switches panels. * * @param newPanel the panel to switch to * @param oldPanel the panel to switch from, or {@code null} if there was no prior panel * @return {@code true} if the switch was successful */ protected abstract boolean switchPanel(T newPanel, T oldPanel); /** * Executes any pre and post-validation actions for a panel. * * @param panel the panel * @param validate if {@code true}, validate the panel after executing the pre-validation actions * @return {@code true} if the panel is valid */ protected boolean executeValidationActions(T panel, boolean validate) { boolean result; if (validate) { result = panel.isValid(); } else { // execute the pre- and post-validation actions, but don't perform validation itself try { variables.refresh(); panel.executePreValidationActions(); panel.executePostValidationActions(); panel.saveData(); result = true; } catch (IzPackException e) { result = false; getPanelView().getHandler().emitError(null, e.getMessage()); } } return result; } /** * Returns the panel view at the specified index. * * @param index the panel index * @return the corresponding panel, or {@code null} if there is no panel at the index */ private T getPanelView(int index) { List panels = getPanelViews(); return index >= 0 && index < panels.size() ? panels.get(index) : null; } /** * Determines if a panel can be shown. * * @param panel the panel * @param visibleOnly if {@code true}, only examine visible panels * @return {@code true} if the nominated panel can be shown */ private boolean canShow(T panel, boolean visibleOnly) { return ((!visibleOnly || panel.isVisible()) && panel.canShow()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy