org.glassfish.api.admin.progress.ProgressStatusBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-micro Show documentation
Show all versions of payara-micro Show documentation
Micro Distribution of the Payara Project
/*
* 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();
}
}