001/*
002 *  Copyright 2016 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.workspaces.repository.maintenance;
017
018import java.util.HashMap;
019import java.util.Map;
020
021/**
022 * TaskProgress
023 */
024public class TaskProgress
025{
026    private final float _total;
027    private float _progress;
028    private State _state;
029
030    private Exception _exception;
031
032    /**
033     * Progress state
034     */
035    public enum State 
036    {
037        /** NEW */
038        NEW,
039        /** RUNNING */
040        RUNNING,
041        /** FINISHED */
042        FINISHED,
043        /** ERROR_STATE */
044        ERROR_STATE
045    }
046
047    /**
048     * Ctor
049     * @param total The total progress
050     */
051    public TaskProgress(float total)
052    {
053        this._total = total;
054        this._progress = 0f;
055        this._state = State.NEW;
056    }
057
058    /**
059     * Overriden Ctor
060     * @param total The total progress
061     * @param start The progress start
062     */
063    public TaskProgress(float total, float start)
064    {
065        this(total);
066        this._progress = start;
067    }
068
069    /**
070     * Unit progress
071     */
072    public void progress()
073    {
074        progress(1);
075    }
076
077    /**
078     * Quantitative progress
079     * @param quantity The quantity to progress
080     */
081    public synchronized void progress(float quantity)
082    {
083        _progress += quantity;
084    }
085
086    /**
087     * Progress by a percentage relative to the range [current progress; total]
088     * @param percentage must be in the [0; 100] range
089     */
090    public void progressRelativePercentage(int percentage)
091    {
092        if (percentage < 0 || percentage > 100)
093        {
094            throw new IllegalArgumentException("percentage must be in the [0; 100] range.");
095        }
096
097        synchronized (this)
098        {
099            if (percentage == 100)
100            {
101                _progress = _total;
102            }
103            else
104            {
105                _progress += (_total - _progress) * percentage / 100f;
106            }
107        }
108    }
109
110    /**
111     * Progress by a given percentage
112     * @param percentage must be in the [0; 100] range
113     */
114    public void progressTotalPercentage(int percentage)
115    {
116        if (percentage < 0 || percentage > 100)
117        {
118            throw new IllegalArgumentException("percentage must be in the [0; 100] range.");
119        }
120
121        synchronized (this)
122        {
123            if (percentage == 100)
124            {
125                _progress = _total;
126            }
127            else
128            {
129                _progress = _total * percentage / 100f;
130            }
131        }
132    }
133
134    /**
135     * getProgressPercentage
136     * @return int
137     */
138    public synchronized float getProgressPercentage()
139    {
140        return Math.min(1f, _progress / _total);
141    }
142
143    /**
144     * setRunning
145     */
146    public synchronized void setRunning()
147    {
148        _state = State.RUNNING;
149    }
150
151    /**
152     * setFinished
153     */
154    public synchronized void setFinished()
155    {
156        _state = State.FINISHED;
157    }
158
159    /**
160     * setInErrorState
161     */
162    public void setInErrorState()
163    {
164        setInErrorState(null);
165    }
166
167    /**
168     * setInErrorState
169     * @param e The exception responsible for the error state
170     */
171    public synchronized void setInErrorState(Exception e)
172    {
173        _exception = e;
174        _state = State.ERROR_STATE;
175    }
176
177    /**
178     * isNotStarted
179     * @return boolean
180     */
181    public boolean isNotStarted()
182    {
183        return State.NEW.equals(_state);
184    }
185
186    /**
187     * isRunning
188     * @return boolean
189     */
190    public boolean isRunning()
191    {
192        return State.RUNNING.equals(_state);
193    }
194
195    /**
196     * isFinished
197     * @return boolean
198     */
199    public boolean isFinished()
200    {
201        return State.FINISHED.equals(_state);
202    }
203
204    /**
205     * isInErrorState
206     * @return boolean
207     */
208    public boolean isInErrorState()
209    {
210        return State.ERROR_STATE.equals(_state);
211    }
212
213    /**
214     * getException
215     * @return Exception
216     */
217    public Exception getException()
218    {
219        return _exception;
220    }
221
222    /**
223     * getState
224     * @return State
225     */
226    public State getState()
227    {
228        return _state;
229    }
230
231
232    /**
233     * Returns information this progress object.
234     * @return a map containing information on the progress status
235     */
236    public Map<String, Object> getProgressInfo()
237    {
238        Map<String, Object> infos = new HashMap<>();
239        synchronized (this)
240        {
241            infos.put("progress", _progress);
242            infos.put("total", _total);
243            infos.put("percentage", getProgressPercentage());
244            infos.put("state", _state.name());
245            if (_exception != null)
246            {
247                infos.put("exception", _exception.getLocalizedMessage());
248            }
249        }
250        return infos;
251    }
252
253    @Override
254    public String toString()
255    {
256        StringBuilder sb = new StringBuilder("Progress : ");
257        synchronized (this)
258        {
259            sb.append(getProgressPercentage()).append(" ");
260            sb.append("[").append(_progress).append("/").append(_total).append("]");
261        }
262        return sb.toString();
263    }
264}