/**
* Copyright 2012-2013 Maciej Jaworski, Mariusz Kapcia, Paweł Kędzia, Mateusz Kubuszok
*
* <p>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</p>
*
* <p>http://www.apache.org/licenses/LICENSE-2.0</p>
*
* <p>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.</p>
*/
package com.autoupdater.client.models;
import static com.autoupdater.client.models.EUpdateStatus.*;
import static com.autoupdater.client.models.EUpdateStrategy.COPY;
import static com.autoupdater.client.models.Models.secureRelativePath;
import static com.autoupdater.client.models.VersionNumber.UNVERSIONED;
import static com.autoupdater.client.utils.comparables.Comparables.compare;
import static com.google.common.base.Objects.equal;
import static java.lang.Math.pow;
import static java.lang.String.valueOf;
import java.io.File;
import java.util.Comparator;
import java.util.Random;
import com.autoupdater.client.utils.comparables.Comparables;
import com.autoupdater.client.utils.enums.Enums;
import com.autoupdater.client.utils.services.ObservableService;
/**
* Class representing Update available for installation.
*/
public class Update extends ObservableService<EUpdateStatus> implements IModel<Update>,
IModelWithVersionNumber {
private Package _package;
private String packageName;
private String packageID;
private boolean developmentVersion;
private String id;
private String changes;
private VersionNumber versionNumber;
private EUpdateStrategy updateStrategy;
private String originalName;
private String relativePath;
private String command;
private File file;
private EUpdateStatus status;
private String statusMessage;
private String uniqueIdentifier;
Update() {
packageID = "";
packageName = "";
id = "";
changes = "";
versionNumber = UNVERSIONED;
updateStrategy = COPY;
originalName = "";
relativePath = "";
command = "";
status = NOT_SELECTED;
}
/**
* Returns Program's Package.
*
* @return Program's Package
*/
public Package getPackage() {
return _package;
}
/**
* Sets Update's Package.
*
* @param _package
* Program's Package
*/
public void setPackage(Package _package) {
this._package = _package;
}
/**
* Returns Update's Package's name.
*
* @return Update's Package's name
*/
public String getPackageName() {
return packageName;
}
/**
* Sets Update's Package's name.
*
* @param packageName
* Update's Package's name
*/
void setPackageName(String packageName) {
this.packageName = packageName != null ? packageName : "";
}
/**
* Returns Update's Package's ID.
*
* @return Program's Package's ID
*/
public String getPackageID() {
return packageID;
}
/**
* Sets Update's Package's ID.
*
* @param packageID
* Program's Package's ID
*/
void setPackageID(String packageID) {
this.packageID = packageID != null ? packageID : "";
}
/**
* Whether Update is for development version.
*
* @return whether Update is for development version
*/
public boolean isDevelopmentVersion() {
return developmentVersion;
}
/**
* Sets whether Update is for development version
*
* @param developmentVersion
* whether Update is for development version
*/
void setDevelopmentVersion(boolean developmentVersion) {
this.developmentVersion = developmentVersion;
}
/**
* Sets whether Update is for development version
*
* @param developmentVersion
* whether Update is for development version
*/
void setDevelopmentVersion(String developmentVersion) {
this.developmentVersion = "true".equalsIgnoreCase(developmentVersion);
}
/**
* Returns Update's ID.
*
* @return Update's ID
*/
public String getID() {
return id;
}
/**
* Sets Update's ID.
*
* @param id
* Update's ID
*/
void setID(String id) {
this.id = id != null ? id : "";
}
/**
* Returns changes done in this Update.
*
* @return description
*/
public String getChanges() {
return changes;
}
/**
* Sets changes done in this Update
*
* @param changes
* description
*/
void setChanges(String changes) {
this.changes = changes != null ? changes : "";
}
@Override
public VersionNumber getVersionNumber() {
return versionNumber;
}
/**
* Sets Update's version number.
*
* @param versionNumber
* Update's version number
*/
void setVersionNumber(String versionNumber) {
this.versionNumber = new VersionNumber(versionNumber);
}
/**
* Sets Update's version number.
*
* @param versionNumber
* Update's version number
*/
void setVersionNumber(VersionNumber versionNumber) {
this.versionNumber = versionNumber != null ? versionNumber : UNVERSIONED;
}
/**
* Whether this Update was installed.
*
* @return true if Update was installed, false otherwise
*/
public boolean isInstalled() {
return status == INSTALLED && _package != null && _package.compareVersions(this) >= 0;
}
/**
* Whether or not is this Update newer that its Package.
*
* @return true it Update is newer that its Package
*/
public boolean isNewerThatPackage() {
return _package != null && _package.compareVersions(this) < 0;
}
/**
* Returns Update strategy.
*
* @return Update strategy
*/
public EUpdateStrategy getUpdateStrategy() {
return updateStrategy;
}
/**
* Sets Update strategy.
*
* @param updateStrategy
* Update strategy
*/
void setUpdateStrategy(String updateStrategy) {
setUpdateStrategy(Enums.parseMessage(EUpdateStrategy.class,
updateStrategy != null ? updateStrategy.toLowerCase() : ""));
}
/**
* Sets Update strategy.
*
* @param updateStrategy
* Update strategy
*/
void setUpdateStrategy(EUpdateStrategy updateStrategy) {
this.updateStrategy = updateStrategy != null ? updateStrategy : EUpdateStrategy.COPY;
}
/**
* Returns original Update filename.
*
* @return original Update filename
*/
public String getOriginalName() {
return originalName;
}
/**
* Sets original Update filename.
*
* @param originalName
* original Update filename
*/
void setOriginalName(String originalName) {
this.originalName = originalName != null ? originalName : "";
}
/**
* Returns relative path for strategy.
*
* @return relative path for strategy
*/
public String getRelativePath() {
return relativePath;
}
/**
* Sets relative path for strategy.
*
* @param relativePath
* relative path for strategy
*/
void setRelativePath(String relativePath) {
this.relativePath = secureRelativePath(relativePath);
}
/**
* Returns command to execute after/as update (depending on strategy).
*
* @return command to execute after/as update
*/
public String getCommand() {
return command;
}
/**
* Sets command to execute after/as update.
*
* @param command
* command to execute after/as update
*/
void setCommand(String command) {
this.command = command != null ? command : "";
}
/**
* Returns Update's File.
*
* @return Update's File
*/
public File getFile() {
return file;
}
/**
* Sets Update's File.
*
* @param file
* Update's File
*/
public void setFile(File file) {
this.file = file;
}
/**
* Returns Update's status.
*
* @return Update's status
*/
public EUpdateStatus getStatus() {
return status;
}
/**
* Sets Update's status.
*
* <p>
* Notifies Update's observers about change.
* </p>
*
* @param status
* Update's status
*/
public void setStatus(String status) {
setStatus(Enums.parseMessage(EUpdateStatus.class, status));
}
/**
* Sets Update's status.
*
* <p>
* Notifies Update's observers about change.
* </p>
*
* @param status
* Update's status
*/
public void setStatus(EUpdateStatus status) {
this.status = status;
if (status == INSTALLED && _package != null && _package.compareVersions(this) < 0)
_package.setVersionNumber(versionNumber);
hasChanged();
notifyObservers(status);
}
/**
* Returns last message related to status change.
*
* @return last message related to status change
*/
public String getStatusMessage() {
return statusMessage != null ? statusMessage : "";
}
/**
* Sets last message related to status change.
*
* @param statusMessage
* last message related to status change
*/
public void setStatusMessage(String statusMessage) {
this.statusMessage = statusMessage;
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Update))
return false;
else if (obj == this)
return true;
Update update = (Update) obj;
return equal(packageName, update.packageName) && equal(versionNumber, update.versionNumber);
}
@Override
public boolean equalVersions(IModelWithVersionNumber model) {
return versionNumber.equals(model.getVersionNumber());
}
@Override
public int hashCode() {
return (int) pow(packageName.hashCode(), 10) + versionNumber.hashCode();
}
@Override
public int compareTo(Update o) {
if (o == null)
return 1;
else if (o == this)
return 0;
else if (!equal(packageName, o.packageName))
return compare(packageName, o.packageName);
return compare(versionNumber, o.versionNumber);
}
@Override
public int compareVersions(IModelWithVersionNumber model) {
return versionNumber.compareTo(model.getVersionNumber());
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("[Update]").append('\n');
builder.append("ID:\t\t\t").append(id).append('\n');
builder.append("Package:\t").append(packageName).append(" (").append(packageID).append(')')
.append('\n');
builder.append("Version:\t").append(versionNumber).append(' ')
.append(developmentVersion ? "development" : "release").append('\n');
builder.append("Changes:\t").append(changes).append('\n');
builder.append("Strategy:\t").append(updateStrategy).append('\n');
builder.append("Filename:\t")
.append(file != null ? file.getAbsolutePath() : "not downloaded").append('\n');
builder.append("Originally:\t").append(originalName).append('\n');
builder.append("Target:\t\t").append(relativePath.isEmpty() ? "default" : relativePath)
.append('\n');
builder.append("Command:\t").append(command).append('\n');
builder.append("Status:\t\t").append(status).append('\n');
builder.append("Message:\t").append(statusMessage != null ? statusMessage : "none")
.append('\n');
return builder.toString();
}
/**
* Returns Unique identifier used to identify update process during
* installation.
*
* @return identifier
*/
public String getUniqueIdentifer() {
return uniqueIdentifier != null ? uniqueIdentifier
: (uniqueIdentifier = valueOf(new Random().nextLong()));
}
@Override
public Comparator<Update> getInstallationsServerPropertiesComparator() {
throw new UnsupportedOperationException("Not implemented - not need to use this!");
}
@Override
public Comparator<Update> getLocalInstallationsComparator() {
return new LocalInstallationsComparator();
}
@Override
public Comparator<Update> getLocal2ServerComparator() {
return new Local2ServerComparator();
}
static class LocalInstallationsComparator implements Comparator<Update> {
@Override
public int compare(Update o1, Update o2) {
if (o1 == null)
return o2 == null ? 0 : -1;
if (!equal(o1.packageName, o2.packageName))
return Comparables.compare(o1.packageName, o2.packageName);
return Comparables.compare(o1.versionNumber, o2.versionNumber);
}
}
static class Local2ServerComparator implements Comparator<Update> {
@Override
public int compare(Update o1, Update o2) {
if (o1 == null)
return o2 == null ? 0 : -1;
if (!equal(o1.packageName, o2.packageName))
return Comparables.compare(o1.packageName, o2.packageName);
if (!equal(o1.developmentVersion, o2.developmentVersion))
return o1.developmentVersion ? 1 : -1;
if (!Models.equal(o1._package, o2._package, Models.EComparisionType.LOCAL_TO_SERVER))
return Models.compare(o1._package, o2._package,
Models.EComparisionType.LOCAL_TO_SERVER);
return Models.compare(o1._package.getProgram(), o2._package.getProgram(),
Models.EComparisionType.LOCAL_TO_SERVER);
}
}
}