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

org.glassfish.api.admin.progress.ProgressStatusBase Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2012-2013 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package org.glassfish.api.admin.progress;

import java.io.Serializable;
import java.util.*;
import org.glassfish.api.admin.CommandProgress;
import org.glassfish.api.admin.ProgressStatus;

/** Basic abstract implementation of {@code ProgressStatus}.
 *
 * @author mmares
 */
//TODO: Move to utils if possible. It is now in API only because ProgressStatusImpl is here, too
public abstract class ProgressStatusBase implements ProgressStatus, Serializable {
    
    private static final long serialVersionUID = -2501719606059507140L;

    public static class ChildProgressStatus implements Serializable {
        
        private final int allocatedSteps;
        private final ProgressStatusBase progressStatus;
        
        public ChildProgressStatus(int allocatedSteps, ProgressStatusBase progressStatus) {
            if (allocatedSteps > 0) {
                this.allocatedSteps = allocatedSteps;
            } else {
                this.allocatedSteps = 0;
            }
            this.progressStatus = progressStatus;
        }

        public int getAllocatedSteps() {
            return allocatedSteps;
        }

        public ProgressStatusBase getProgressStatus() {
            return progressStatus;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final ChildProgressStatus other = (ChildProgressStatus) obj;
            if (this.allocatedSteps != other.allocatedSteps) {
                return false;
            }
            if (this.progressStatus != other.progressStatus && (this.progressStatus == null || !this.progressStatus.equals(other.progressStatus))) {
                return false;
            }
            return true;
        }

        @Override
        public int hashCode() {
            return this.progressStatus != null ? this.progressStatus.hashCode() : 0;
        }

        @Override
        public String toString() {
            return "ChildProgressStatus{" + "allocatedSteps=" + allocatedSteps + ", progressStatus=" + progressStatus + '}';
        }
        
    }
    
    protected String name;
    protected String id;
    protected int totalStepCount = -1;
    protected int currentStepCount = 0;
    protected ProgressStatusBase parent;
    protected boolean completed = false;
    protected Set children = new HashSet();

    /** Construct unnamed {@code ProgressStatus}
     * 
     * @param parent Parent {@code ProgressStatus}
     * @param id Is useful for event transfer
     */ 
    protected ProgressStatusBase(ProgressStatusBase parent, String id) {
        this(null, -1, parent, id);
    }
    
    /** Construct named {@code ProgressStatus}.
     * 
     * @param name of the {@code ProgressStatus} implementation is used 
     *        to identify source of progress messages.
     * @param parent Parent {@code ProgressStatus}
     * @param id Is useful for event transfer
     */
    protected ProgressStatusBase(String name, ProgressStatusBase parent, String id) {
        this(name, -1, parent, id);
    }
    
    /** Construct named {@code ProgressStatus} with defined expected count 
     * of steps.
     * 
     * @param name of the {@code ProgressStatus} implementation is used 
     *        to identify source of progress messages.
     * @param totalStepCount How many steps are expected in this 
     *        {@code ProgressStatus}
     * @param parent Parent {@code ProgressStatus}
     * @param id Is useful for event transfer
     */
    protected ProgressStatusBase(String name, int totalStepCount, 
            ProgressStatusBase parent, String id) {
        this.name = name;
        this.totalStepCount = totalStepCount;
        this.parent = parent;
        if (id == null || id.isEmpty()) {
            id = UUID.randomUUID().toString();
        }
        this.id = id;
    } 
    
    /** Fires {@link ProgressStatusEvent} to parent.
     */
    protected void fireEvent(ProgressStatusEvent event) {
        if (parent != null) {
            parent.fireEvent(event);
        }
    }
    
    @Override
    public synchronized void setTotalStepCount(int totalStepCount) {
        if (completed || this.totalStepCount == totalStepCount) {
            return;
        }
        this.totalStepCount = totalStepCount;
        if (totalStepCount >= 0 && this.currentStepCount > totalStepCount) {
            this.currentStepCount = totalStepCount;
        }
        fireEvent(new ProgressStatusEventSet(id, totalStepCount, null));
    }

    @Override
    public synchronized int getTotalStepCount() {
        return totalStepCount;
    }

    @Override
    public int getRemainingStepCount() {
        int childAlocSteps = 0;
        for (ChildProgressStatus childProgressStatus : children) {
            childAlocSteps += childProgressStatus.getAllocatedSteps();
        }
        return totalStepCount - currentStepCount - childAlocSteps;
    }

    @Override
    public synchronized void progress(int steps, String message, boolean spinner) {
        if (completed) {
            return;
        }
        int lastCurrentStepCount = this.currentStepCount;
        if (steps > 0) {
            if (totalStepCount < 0) {
                currentStepCount += steps;
            } else if (currentStepCount < totalStepCount) {
                currentStepCount += steps;
                if (currentStepCount > totalStepCount) {
                    currentStepCount = totalStepCount;
                }
            }
        }
        if (currentStepCount != lastCurrentStepCount || message != null || spinner != getSpinnerStatus()) {
            fireEvent(new ProgressStatusEventProgress(id, steps, message, spinner));
        }
    }
    
    @Override
    public synchronized void progress(int steps, String message) {
        progress(steps, message, false);
    }

    @Override
    public void progress(int steps) {
        progress(steps, null, false);
    }

    @Override
    public void progress(String message) {
        progress(0, message, false);
    }

    @Override
    public synchronized void setCurrentStepCount(int stepCount) {
        if (completed) {
            return;
        }
        boolean stepsChanged = false;
        if (stepCount >= 0 && stepCount != currentStepCount) {
            if (totalStepCount < 0 || stepCount < totalStepCount) {
                currentStepCount = stepCount;
                stepsChanged = true;
            } else if (currentStepCount != totalStepCount) {
                currentStepCount = totalStepCount;
                stepsChanged = true;
            }
        }
        if (stepsChanged) {
            fireEvent(new ProgressStatusEventSet(id, null, stepCount));
        }
    }

    @Override
    public void complete(String message) {
        if (completeSilently()) {
            fireEvent(new ProgressStatusEventComplete(id, message));
        }
    }
    
    /** Complete this {@code ProgressStatus} and all sub-ProgressStatuses 
     * but does not fire event to parent statuses.
     */
    protected synchronized boolean completeSilently() {
        if (completed) {
            return false;
        }
        if (totalStepCount >= 0) {
            currentStepCount = totalStepCount;
        }
        completed = true;
        for (ChildProgressStatus child : children) {
            child.getProgressStatus().completeSilently();
        }
        return true;
    }

    @Override
    public void complete() {
        complete(null);
    }

    @Override
    public boolean isComplete() {
        return completed;
    }
    
    protected abstract ProgressStatusBase doCreateChild(String name, int totalStepCount);
    
    protected void allocateStapsForChildProcess(int allocatedSteps) {
        if (allocatedSteps < 0) {
            allocatedSteps = 0;
        }
        if (totalStepCount >= 0) {
            for (ChildProgressStatus child : children) {
                allocatedSteps += child.getAllocatedSteps();
            }
            if ((allocatedSteps + currentStepCount) > totalStepCount) {
                currentStepCount = totalStepCount - allocatedSteps;
                if (currentStepCount < 0) {
                    currentStepCount = 0;
                    totalStepCount = allocatedSteps;
                }
            }
        }
    }
    
    public synchronized ProgressStatus createChild(String name, 
            int allocatedSteps, int totalStepCount) {
        if (allocatedSteps < 0) {
            allocatedSteps = 0;
        }
        allocateStapsForChildProcess(allocatedSteps);
        ProgressStatusBase result = doCreateChild(name, totalStepCount);
        children.add(new ChildProgressStatus(allocatedSteps, result));
        fireEvent(new ProgressStatusEventCreateChild(id, name, result.getId(), allocatedSteps, totalStepCount));
        return result;
    }

    @Override
    public ProgressStatus createChild(String name, int allocatedSteps) {
        return createChild(name, allocatedSteps, -1);
    }

    @Override
    public ProgressStatus createChild(int allocatedSteps) {
        return createChild(null, allocatedSteps);
    }
    
    public synchronized int getCurrentStepCount() {
        return this.currentStepCount;
    }
    
    protected synchronized float computeCompleteSteps() {
        if (isComplete()) {
            return totalStepCount;
        }
        float realStepCount = currentStepCount;
        for (ChildProgressStatus child : children) {
            float childPortion = child.progressStatus.computeCompletePortion();
            if (childPortion < 0) {
                return -1;
            }
            realStepCount += ((float) child.getAllocatedSteps()) * childPortion;
        }
        return realStepCount;
    }
    
    public synchronized float computeCompletePortion() {
        if (isComplete()) {
            return 1;
        }
//        if (totalStepCount < 0) {
//            return -1;
//        }
        float realSteps = computeCompleteSteps();
        if (realSteps < 0) {
            return -1;
        }
        if (realSteps == 0) {
            return 0;
        }
        if (totalStepCount < 0) {
            return -1;
        } else if (totalStepCount > 0) {
            return realSteps / ((float) totalStepCount);
        } else {
            return 1;
        }
    }
    
    public synchronized int computeSumSteps() {
        int result = 0;
        for (ChildProgressStatus child : children) {
            if (child.allocatedSteps > 0) {
                result += child.progressStatus.computeSumSteps();
            }
        }
        return getCurrentStepCount() + result;
    }
    
    @Override
    public String toString() {
        StringBuilder result = new StringBuilder();
        if (name == null) {
            result.append("NoName ");
        } else {
            result.append(name).append(' ');
        }
        float realSteps = computeCompleteSteps();
        if (realSteps < 0) {
            result.append(currentStepCount).append(" / ").append('?');
        } else {
            result.append(Math.round(realSteps)).append(" / ");
            result.append(totalStepCount < 0 ? "?" : String.valueOf(totalStepCount));
        }
        
        return result.toString();
    }
    
    public synchronized Collection getChildren() {
        Collection result = new ArrayList(children.size());
        for (ChildProgressStatus chld : children) {
            result.add(chld.getProgressStatus());
        }
        return result;
    }

    public Set getChildProgressStatuses() {
        return children;
    }
    
    @Override
    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }
    
    public ProgressStatusBase getParrent() {
        return parent;
    }
    
    /** Recursive search for child by id.
     */
    protected ProgressStatusBase findById(String id) {
        if (id == null || id.isEmpty()) {
            return null;
        }
        if (id.equals(getId())) {
            return this;
        }
        for (ChildProgressStatus child : getChildProgressStatuses()) {
            ProgressStatusBase result = child.getProgressStatus().findById(id);
            if (result != null) {
                return result;
            }
        }
        return null;
    }
    
    /** Returns spinner status or null if status was not possible to check.
     */
    private boolean getSpinnerStatus() {
        if (parent == null) {
            return false;
        }
        if (parent instanceof CommandProgress) {
            return ((CommandProgress) parent).isSpinnerActive();
        }
        return ((ProgressStatusBase) parent).getSpinnerStatus();
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy