package org.smartly.application.desktopgap.impl.app.applications.window;
import org.smartly.IConstants;
import org.smartly.Smartly;
import org.smartly.application.desktopgap.DesktopGap;
import org.smartly.application.desktopgap.impl.app.IDesktopConstants;
import org.smartly.application.desktopgap.impl.app.utils.Utils;
import org.smartly.commons.cryptograph.GUID;
import org.smartly.commons.cryptograph.MD5;
import org.smartly.commons.util.*;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Manifest wrapper
*/
public class AppManifest {
private static final String MANIFEST = IDesktopConstants.FILE_MANIFEST;
private static final String PAGE_FRAME = IDesktopConstants.PAGE_FRAME;
private static final String TEMP_DIR = IDesktopConstants.TEMP_DIR;
private static final String INSTALLED_DIR = IDesktopConstants.INSTALLED_STORE_DIR;
private static final String DIR_APP = "./app";
private static final String DIR_LIBS = "./libs";
private static final String MF_LANG_BASE = IDesktopConstants.LANG_BASE;
private static final String MF_UID = IDesktopConstants.MF_UID;
private static final String MF_SYS_ID = "sys_id";
private static final String MF_NAME = "name";
private static final String MF_TITLE = "title";
private static final String MF_DESCRIPTION = "description";
private static final String MF_VERSION = "version";
private static final String MF_CATEGORY = "category";
private static final String MF_DEBUG = "debug";
private static final String MF_CATEGORY_UNDEFINED = IDesktopConstants.MF_CATEGORY_UNDEFINED;
private static final String MF_INDEX = "index";
private static final String MF_FRAME = IDesktopConstants.MF_FRAME;
private static final String MF_FRAME_TYPE = StringUtils.concatDot(MF_FRAME, "type"); // standard, tool
private static final String MF_FRAME_CONTEXTMENU = IDesktopConstants.MF_FRAME_CONTEXTMENU;
private static final String MF_FRAME_SHADOW = IDesktopConstants.MF_FRAME_SHADOW;
private static final String MF_FRAME_RESIZABLE = IDesktopConstants.MF_FRAME_RESIZABLE;
private static final String MF_FRAME_DRAGGABLE = IDesktopConstants.MF_FRAME_DRAGGABLE;
private static final String MF_FRAME_MAXIMIZED = IDesktopConstants.MF_FRAME_MAXIMIZED;
private static final String MF_FRAME_MIN_WIDTH = IDesktopConstants.MF_FRAME_MIN_WIDTH;
private static final String MF_FRAME_MIN_HEIGHT = IDesktopConstants.MF_FRAME_MIN_HEIGHT;
private static final String MF_FRAME_MAX_WIDTH = IDesktopConstants.MF_FRAME_MAX_WIDTH;
private static final String MF_FRAME_MAX_HEIGHT = IDesktopConstants.MF_FRAME_MAX_HEIGHT;
private static final String MF_FRAME_WIDTH = IDesktopConstants.MF_FRAME_WIDTH;
private static final String MF_FRAME_HEIGHT = IDesktopConstants.MF_FRAME_HEIGHT;
private static final String MF_FRAME_X = IDesktopConstants.MF_FRAME_X;
private static final String MF_FRAME_Y = IDesktopConstants.MF_FRAME_Y;
private static final String MF_BUTTONS = IDesktopConstants.MF_BUTTONS;
private static final String MF_BUTTONS_CLOSE = IDesktopConstants.MF_BUTTONS_CLOSE;
private static final String MF_BUTTONS_FULLSCREEN = IDesktopConstants.MF_BUTTONS_FULLSCREEN;
private static final String MF_BUTTONS_MAXIMIZE = IDesktopConstants.MF_BUTTONS_MAXIMIZE;
private static final String MF_BUTTONS_MINIMIZE = IDesktopConstants.MF_BUTTONS_MINIMIZE;
private static final String MF_FRAME_STANDARD = IDesktopConstants.FRAME_STANDARD;
private static final String MF_FRAME_TOOL = IDesktopConstants.FRAME_TOOL;
private final String _temp_dir;
private final JsonWrapper _manifest;
private final String _install_dir;
private final String _dir_app;
private final String _dir_libs;
private final String _appName;
private final String _lang;
private String _install_root; // system or store
private boolean _is_system;
private String _filePath;
private String _appId;
/**
* Generate manifest
*
* @param path App Path or Package Name
* @throws IOException
*/
public AppManifest(final String path) throws IOException {
_lang = DesktopGap.getLang();
_temp_dir = PathUtils.concat(Smartly.getAbsolutePath(TEMP_DIR), GUID.create(false, true));
_manifest = this.init(path);
if (!_manifest.isEmpty()) {
_appName = _manifest.optString(MF_NAME);
_install_dir = PathUtils.concat(_install_root, _appName);
_dir_app = PathUtils.merge(_install_dir, DIR_APP);
_dir_libs = PathUtils.merge(_install_dir, DIR_LIBS);
if (_is_system) {
_appId = _manifest.optString(MF_SYS_ID, null);
}
// add id
_manifest.putSilent(MF_UID, this.getAppId());
// add object_type for javascript usage
_manifest.putSilent(IDesktopConstants.OBJECT_TYPE, IDesktopConstants.OBJECT_TYPE_MANIFEST);
} else {
_appName = "";
_install_dir = "";
_dir_app = "";
_dir_libs = "";
}
}
public JsonWrapper getJson() {
return _manifest;
}
public boolean isSystem() {
return _is_system;
}
public boolean isValid() {
return null != _manifest && !_manifest.isEmpty() && !_manifest.hasParseError();
}
public String getErrorMessage() {
return _manifest.hasParseError() ? _manifest.getParseError().toString() : "";
}
public String getPathLibs() {
return _dir_libs;
}
public String getPathApp() {
return _dir_app;
}
public String getAbsolutePath(final String path) {
return PathUtils.concat(_install_dir, path);
}
public String getAbsoluteAppPath(final String path) {
if (PathUtils.isHttp(path)) {
return path;
}
return PathUtils.concat(_dir_app, path);
}
public String getRelativeAppPath(final String path) {
final String relativeRoot = StringUtils.concatArgsEx("/",
_is_system ? IDesktopConstants.SYSTEM_DIR : IDesktopConstants.STORE_DIR,
this.getAppName());
final String relativeAppPath = PathUtils.resolve(PathUtils.concat(relativeRoot, DIR_APP));
return PathUtils.concat(relativeAppPath, path);
}
public String getUid() {
return _manifest.optString(MF_UID);
}
public String getAppId() {
if (!StringUtils.hasText(_appId)) {
this.generateId();
}
return _appId;
}
public String getAppName() {
return _appName;
}
public String getInstallDir() {
return _install_dir;
}
public String getAppIndex() {
return PathUtils.concat(DIR_APP, this.getIndex());
}
public String getAbsolutePageFrame() {
return this.getAbsoluteAppPath(PAGE_FRAME);
}
public String getAbsoluteIndex() {
return this.getAbsoluteAppPath(this.getIndex());
}
public String getRelativeIndex() {
return this.getRelativeAppPath(this.getIndex());
}
public boolean isGreaterThan(final AppManifest other) {
return this.isGreaterThan(other.getVersion());
}
public boolean isGreaterThan(final String other_version) {
return CompareUtils.greater(this.getVersion(), other_version);
}
public boolean save() {
try {
FileUtils.copy(_manifest.toString().getBytes(), new File(_filePath));
} catch (Throwable t) {
return false;
}
return true;
}
// --------------------------------------------------------------------
// P r o p e r t i e s
// --------------------------------------------------------------------
public String getIndex() {
return _manifest.optString(MF_INDEX);
}
public void setIndex(final String value) {
_manifest.putSilent(MF_INDEX, value);
this.generateId();
this.save();
}
public String getName() {
return _manifest.optString(MF_NAME);
}
public void setName(final String value) {
_manifest.putSilent(MF_NAME, value);
this.generateId();
this.save();
}
public String getTitle() {
String result = _manifest.deepString(StringUtils.concatDot(MF_TITLE, _lang));
if (!StringUtils.hasText(result)) {
result = _manifest.deepString(StringUtils.concatDot(MF_TITLE, MF_LANG_BASE));
}
if (!StringUtils.hasText(result)) {
result = _manifest.optString(MF_TITLE);
}
return result;
}
public void setTitle(final String lang, final String value) {
final String key = StringUtils.concatDot(MF_TITLE, lang);
_manifest.putSilent(key, value);
this.generateId();
this.save();
}
public String getDescription() {
String result = _manifest.deepString(StringUtils.concatDot(MF_DESCRIPTION, _lang));
if (!StringUtils.hasText(result)) {
result = _manifest.deepString(StringUtils.concatDot(MF_DESCRIPTION, MF_LANG_BASE));
}
if (!StringUtils.hasText(result)) {
result = _manifest.optString(MF_DESCRIPTION);
}
return result;
}
public void setDescription(final String lang, final String value) {
final String key = StringUtils.concatDot(MF_DESCRIPTION, lang);
_manifest.putSilent(key, value);
this.generateId();
this.save();
}
public String getCategory() {
return _manifest.optString(MF_CATEGORY, MF_CATEGORY_UNDEFINED);
}
public void setCategory(final String value) {
_manifest.putSilent(MF_CATEGORY, value);
this.generateId();
this.save();
}
public boolean isDebug() {
return _manifest.optBoolean(MF_DEBUG);
}
public void setDebug(final boolean value) {
_manifest.putSilent(MF_DEBUG, value);
this.generateId();
this.save();
}
public String getVersion() {
return _manifest.optString(MF_VERSION);
}
public void setVersion(final String version) {
_manifest.putSilent(MF_VERSION, version);
this.generateId();
this.save();
}
public boolean hasContextMenu() {
return _manifest.deepBoolean(MF_FRAME_CONTEXTMENU);
}
public void setContextMenu(final boolean value) {
_manifest.putDeep(MF_FRAME_CONTEXTMENU, value);
this.save();
}
public boolean hasShadow() {
return _manifest.deepBoolean(MF_FRAME_SHADOW);
}
public void setShadow(final boolean value) {
_manifest.putDeep(MF_FRAME_SHADOW, value);
this.save();
}
public boolean isResizable() {
return _manifest.deepBoolean(MF_FRAME_RESIZABLE);
}
public void setResizable(final boolean value) {
_manifest.putDeep(MF_FRAME_RESIZABLE, value);
this.save();
}
public boolean isDraggable() {
return _manifest.deepBoolean(MF_FRAME_DRAGGABLE);
}
public void setDraggable(final boolean value) {
_manifest.putDeep(MF_FRAME_DRAGGABLE, value);
this.save();
}
public String getFrameType() {
return _manifest.deepString(MF_FRAME_TYPE, MF_FRAME_STANDARD);
}
public void setFrameType(final String value) {
_manifest.putSilent(MF_FRAME_TYPE, value);
this.save();
}
//-- registry --//
public boolean getMaximized() {
return _manifest.deepBoolean(MF_FRAME_MAXIMIZED);
}
public void setMaximized(final boolean value) {
_manifest.putDeep(MF_FRAME_MAXIMIZED, value);
this.save();
}
public double getWidth() {
return _manifest.deepDouble(MF_FRAME_WIDTH);
}
public void setWidth(final double value) {
_manifest.putDeep(MF_FRAME_WIDTH, value);
this.save();
}
public double getHeight() {
return _manifest.deepDouble(MF_FRAME_HEIGHT);
}
public void setHeight(final double value) {
_manifest.putDeep(MF_FRAME_HEIGHT, value);
this.save();
}
public double getMinWidth() {
return _manifest.deepDouble(MF_FRAME_MIN_WIDTH, 64);
}
public void setMinWidth(final double value) {
_manifest.putDeep(MF_FRAME_MIN_WIDTH, value);
this.save();
}
public double getMinHeight() {
return _manifest.deepDouble(MF_FRAME_MIN_HEIGHT, 64);
}
public void setMinHeight(final double value) {
_manifest.putDeep(MF_FRAME_MIN_HEIGHT, value);
this.save();
}
public double getMaxWidth() {
return _manifest.deepDouble(MF_FRAME_MAX_WIDTH, -1);
}
public void setMaxWidth(final double value) {
_manifest.putDeep(MF_FRAME_MAX_WIDTH, value);
this.save();
}
public double getMaxHeight() {
return _manifest.deepDouble(MF_FRAME_MAX_HEIGHT, -1);
}
public void setMaxHeight(final double value) {
_manifest.putDeep(MF_FRAME_MAX_HEIGHT, value);
this.save();
}
public double getX() {
return _manifest.deepDouble(MF_FRAME_X);
}
public void setX(final double value) {
_manifest.putDeep(MF_FRAME_X, value);
this.save();
}
public double getY() {
return _manifest.deepDouble(MF_FRAME_Y);
}
public void setY(final double value) {
_manifest.putDeep(MF_FRAME_Y, value);
this.save();
}
//-- buttons --//
public Map<String, Boolean> getButtonsMap() {
final Map<String, Boolean> buttons = new HashMap<String, Boolean>();
buttons.put(IDesktopConstants.BTN_CLOSE, getButtonClose());
buttons.put(IDesktopConstants.BTN_FULLSCREEN, getButtonFullscreen());
buttons.put(IDesktopConstants.BTN_MAXIMIZE, getButtonMaximize());
buttons.put(IDesktopConstants.BTN_MINIMIZE, getButtonMinimize());
return buttons;
}
public boolean getButtonClose() {
return _manifest.deepBoolean(MF_BUTTONS_CLOSE);
}
public void setButtonClose(final boolean value) {
_manifest.putSilent(MF_BUTTONS_CLOSE, value);
this.save();
}
public boolean getButtonFullscreen() {
return _manifest.deepBoolean(MF_BUTTONS_FULLSCREEN);
}
public void setButtonFullscreen(final boolean value) {
_manifest.putSilent(MF_BUTTONS_FULLSCREEN, value);
this.save();
}
public boolean getButtonMaximize() {
return _manifest.deepBoolean(MF_BUTTONS_MAXIMIZE);
}
public void setButtonMaximize(final boolean value) {
_manifest.putSilent(MF_BUTTONS_MAXIMIZE, value);
this.generateId();
this.save();
}
public boolean getButtonMinimize() {
return _manifest.deepBoolean(MF_BUTTONS_MINIMIZE);
}
public void setButtonsMinimize(final boolean value) {
_manifest.putSilent(MF_BUTTONS_MINIMIZE, value);
this.generateId();
this.save();
}
// ------------------------------------------------------------------------
// p r i v a t e
// ------------------------------------------------------------------------
private JsonWrapper init(final String path) throws IOException {
final String unixPath = PathUtils.toUnixPath(path);
_install_root = Smartly.getAbsolutePath(INSTALLED_DIR); // default
final String manifestJson;
if (Utils.isPackage(unixPath)) {
// PACKAGE
// unzip temp
ZipUtils.unzip(unixPath, _temp_dir);
_filePath = PathUtils.concat(_temp_dir, MANIFEST);
manifestJson = FileUtils.readFileToString(new File(_filePath));
// remove temp
FileUtils.delete(_temp_dir);
} else if (Utils.isManifest(unixPath)) {
// MANIFEST FILE
_filePath = unixPath;
manifestJson = FileUtils.readFileToString(new File(_filePath));
_install_root = PathUtils.getParent(PathUtils.getParent(_filePath)); // overwrite default
} else if (Utils.isAppFolder(unixPath)) {
// APP FOLDER
_filePath = PathUtils.concat(unixPath, MANIFEST);
manifestJson = FileUtils.readFileToString(new File(_filePath));
_install_root = PathUtils.getParent(unixPath); // overwrite default
} else if (unixPath.indexOf(IConstants.FOLDER_SEPARATOR) > 0) {
_filePath = PathUtils.concat(unixPath, MANIFEST);
manifestJson = FileUtils.readFileToString(new File(_filePath));
_install_root = PathUtils.getParent(unixPath); // overwrite default
} else {
// INVALID PATH
_filePath = "";
manifestJson = "{}";
}
_is_system = _install_root.endsWith(IDesktopConstants.SYSTEM_DIR);
return new JsonWrapper(manifestJson);
}
private void generateId() {
final String index = _manifest.optString(MF_INDEX);
final String name = _manifest.optString(MF_NAME);
final String title = _manifest.optString(MF_TITLE);
final String version = _manifest.optString(MF_VERSION);
_appId = MD5.encode(StringUtils.concatDot(index, name, title, version));
}
// --------------------------------------------------------------------
// S T A T I C
// --------------------------------------------------------------------
private static File getManifestFile(final String path) {
final String unixPath = PathUtils.toUnixPath(path);
try {
final String ext = PathUtils.getFilenameExtension(unixPath);
final File file;
if (StringUtils.hasText(ext)) {
file = new File(unixPath);
} else {
file = new File(PathUtils.concat(unixPath, MANIFEST));
}
if (PathUtils.getFilename(file.getName()).equalsIgnoreCase(MANIFEST)) {
if (file.exists()) {
return file;
}
}
} catch (Throwable ignored) {
}
return null;
}
public static AppManifest getManifest(final String path) {
try {
File file = new File(path);
File manifest = getManifestFile(file.getAbsolutePath());
while (null == manifest) {
file = file.getParentFile();
if (null == file) {
break;
}
manifest = getManifestFile(file.getAbsolutePath());
}
if (null != manifest) {
return new AppManifest(manifest.getAbsolutePath());
}
} catch (Throwable ignored) {
}
return null;
}
public static boolean existManifest(final String path) {
return null != getManifestFile(path);
}
}