/**
* This file is part of HIDB2.
*
* HIDB2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HIDB2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with HIDB2. If not, see <http://www.gnu.org/licenses/>.
*/
package hidb2.kern;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
/**
* An Image attribut, is a path to an Image.
*
* The path is either absolute or relative to a DataPath of the IDB.<br>
* The path is stored in an URL format.<br>
* The path is absolute, when it starts with a protocole name (file:, http:, ftp: USW)
*
* This class is associated wth specific editors (Browser & Co) and renderers.
* The icon cach is managed by those classes.
*
* This class has probably a special storage method and cach for icons. (hum.. later...)
*
* TODO: Manage Orientation
*/
public class AttrImage extends AttrFile
{
/** Read from the checker. Default is 128 pixels */
protected int _thumbSize = 128;
protected int _width;
protected int _height;
private Image _sqThumb;
/**
* Persistent attribut, that contains te thumbnail of the image.
* ==> Pas sur (20101006) - This attribut is evaluated when getIcon() is called.
*/
protected ImageData _thumb;
public AttrImage()
{
setStatus(StatusCycle.CREATED);
}
/**
* Relative management of path.
*/
public void setValue(Object o)
{
super.setValue(o);
refresh();
}
/**
* Return a squared Image of the thumbnail
*/
public Image getSqrImage(Device device, int size)
{
if (_sqThumb == null)
{
ImageData iconData = getIcon();
int width = iconData.width;
int height = iconData.height;
if ((width == size) && (height == size))
{
_sqThumb = new Image(device, iconData);
}
else
{
_sqThumb = new Image(device, size, size);
GC gc = new GC(_sqThumb);
if ((width > size) || (height > size))
{
// Downscaling is needed
int nWidth = 0;
int nHeight = 0;
if (width > height)
{
nWidth = size;
nHeight = (size * height) / width;
}
else
{
nHeight = size;
nWidth = (size * width) / height;
}
iconData = iconData.scaledTo(nWidth, nHeight);
}
int x0 = (size - width) / 2;
int y0 = (size - height) / 2;
gc.drawImage(new Image(device, iconData), x0, y0);
gc.dispose();
}
}
return _sqThumb;
}
/**
* Return the ImageData of this AttrImage.
*/
public ImageData getIcon()
{
if (_thumb == null)
{
String absPath = getAbsolutePath();
_thumb = (absPath == null) ? null : new ImageData(absPath);
}
return _thumb;
}
/**
* @return
*/
public DataPath getDataPath()
{
return _dataPath;
}
/**
* @param path
*/
public void setDataPath(DataPath path)
{
_dataPath = path;
// Reset the potentially already created thumbnail
_thumb = null;
_sqThumb = null;
}
/**
* Refresh the values relatives to the images :<br>
* - Date, Icon, sizes
*
*/
public void refresh()
{
if (_path != null)
{
int lastFileSeparator = _path.lastIndexOf(File.separator);
String dirname;
String filename = _path.substring(lastFileSeparator + 1);
if (_dataPath != null)
{
dirname = _dataPath.getPath() + ((lastFileSeparator > 0) ? _path.substring(0, lastFileSeparator) : "");
}
else
{
dirname = "";
}
// Force to read new Thumbnail
ImageData fullImg = new ImageData(dirname + File.separator + filename);
_width = fullImg.width;
_height = fullImg.height;
int thumbWidth = 0;
int thumbHeight = 0;
if (_width > _height)
{
thumbWidth = _thumbSize;
thumbHeight = (_thumbSize * _height) / _width;
}
else
{
thumbHeight = _thumbSize;
thumbWidth = (_thumbSize * _width) / _height;
}
// PaletteData pdt = fullImg.palette;
_thumb = fullImg.scaledTo(thumbWidth, thumbHeight);
// Get new date
File f = new File(dirname + File.separator + filename);
_lmd = f.lastModified();
_lmDate = null;
_fileSize = f.length();
}
}
@Override
public void setChecker(AttrChecker checker)
{
_thumbSize = ((AttrImageChecker) checker).getIconSize();
}
// --------------------------------------------------------------------------
// static Storage methods
// --------------------------------------------------------------------------
/**
* Return an ordered table of SQL commands that create the tables, indexes
* and constraints associated to the type.
* @return
*/
public static String[] getTableDecl()
{
return new String[]
{
"CREATE TABLE T_IMAGEREF (ID INT IDENTITY, DATAPATHID INT, RELPATH VARCHAR(1024), "
+ "FILESIZE INT(9), LASTMODIFTIME TIMESTAMP, "
+ "WIDTH INT(4), HEIGHT INT(4), COLORMODEL INT(1), ORIENTATION INT(1), THUMB_LARGE BINARY(1000000))",
"CREATE INDEX IDXIMGRELPATH ON T_IMAGEREF(RELPATH)",
// Index relative file names
"CALL FTL_CREATE_INDEX('PUBLIC', 'T_IMAGEREF', 'RELPATH')"
};
}
/**
* Return an ordered table of SQL commands that drop the tables, indexes
* and constraints associated to the type.
* @return
*/
public static String[] getTableDelete()
{
return new String[]
{
"CALL FTL_DROP_INDEX('PUBLIC', 'T_IMAGEREF')",
"DROP INDEX IF EXISTS IDXIMGRELPATH",
"DROP TABLE IF EXISTS T_IMAGEREF"
};
}
/**
* Return the statement kit associated to the AttrImage.
* @return a new instance of created statements.
*/
public static StatKit getStatements(DataStore das)
{
StatKit sk = new StatKit();
try
{
sk.fullSelect = das.getCnx().prepareStatement("SELECT * FROM T_IMAGEREF WHERE ID=?");
// Update statement
sk.update = das.getCnx().prepareStatement(
"UPDATE T_IMAGEREF SET DATAPATHID=?, RELPATH=?, FILESIZE=?, LASTMODIFTIME=?, "
+ "WIDTH=?, HEIGHT=?, COLORMODEL=?, ORIENTATION=?, THUMB_LARGE=? WHERE ID=?");
sk.insert = das.getCnx().prepareStatement(
"INSERT INTO T_IMAGEREF (DATAPATHID, RELPATH, FILESIZE, LASTMODIFTIME, "
+ "WIDTH, HEIGHT, COLORMODEL, ORIENTATION, THUMB_LARGE) VALUES (?,?,?,?,?,?,?,?,?)",
Statement.RETURN_GENERATED_KEYS);
sk.delete = das.getCnx().prepareStatement("DELETE FROM T_IMAGEREF WHERE ID=?");
sk.datapathReference = das.getCnx().prepareStatement("SELECT COUNT(ID) FROM T_IMAGEREF WHERE DATAPATHID=?");
sk.datapathReplace = das.getCnx().prepareStatement("UPDATE T_IMAGEREF SET DATAPATHID=? WHERE DATAPATHID=?");
}
catch (SQLException e)
{
e.printStackTrace();
}
return sk;
}
// Methods dedicated to extented types
public int read(DataStore das)
{
int res = C_OK;
try
{
// Optimze - Set at DataStore level
PreparedStatement ps = das.getFullSelect(AttrType.T_Image);
ps.setLong(1, getID());
ResultSet rs = ps.executeQuery();
if (rs.next())
{
// (1) ID INT NOT NULL PRIMARY KEY
// (2) DATAPATHID INT
long dataPathid = rs.getLong(2);
_dataPath = das.findDataPath(dataPathid);
// (3) RELPATH VARCHAR(1024)
_path = rs.getString(3);
// (4) FILESIZE INT(9)
_fileSize = rs.getLong(4);
// (5) LASTMODIFTIME TIMESTAMP
_lmd = rs.getTimestamp(5).getTime();
// (6) WIDTH INT(4)
_width = rs.getInt(6);
// (8) HEIGHT(4)
_height = rs.getInt(7);
// (8) COLORMODEL INT(1)
// (9) ORIENTATION INT(1)
// (10) THUMB_LARGE
InputStream thumbIs = rs.getBinaryStream(10);
_thumb = new ImageData(thumbIs);
setStatus(StatusCycle.UNCHANGED);
}
else
{
log.warning("Image(" + getID() + ") not found");
res = C_FAIL;
}
}
catch (SQLException sqex)
{
log.warning("Image(" + getID() + ") error");
res = C_ERROR;
}
return res;
}
public int write(DataStore das, ValuedInstance vi)
{
int res = C_OK;
switch (getStatus())
{
case CREATED:
res = create(das, vi);
break;
case MODIFIED:
res = update(das);
break;
case DELETED:
res = delete(das);
break;
}
setStatus(StatusCycle.UNCHANGED);
return res;
}
public int create(DataStore das, ValuedInstance vi)
{
int res = C_OK;
try
{
PreparedStatement ps = das.getInsertSelect(AttrType.T_Image);
// (3) DATAPATHID INT
ps.setLong(1, _dataPath.getID());
// (4) RELPATH VARCHAR(1024)
ps.setString(2, _path);
// (5) FILESIZE INT(9)
ps.setLong(3, _fileSize);
// (6) LASTMODIFTIME TIMESTAMP
ps.setTimestamp(4, new Timestamp(_lmd));
// (7) WIDTH INT(4)
ps.setInt(5, _width);
// (8) HEIGHT(4)
ps.setInt(6, _height);
// (7) COLORMODEL INT(1)
ps.setInt(7, 0);
// (8) ORIENTATION INT(1)
ps.setInt(8, 0);
// (9) THUMB_LARGE
ImageLoader imldr = new ImageLoader();
imldr.data = new ImageData[]
{
_thumb
};
ByteArrayOutputStream bos = new ByteArrayOutputStream(64000);
imldr.save(bos, SWT.IMAGE_JPEG);
InputStream thumbIs = new ByteArrayInputStream(bos.toByteArray());
ps.setBinaryStream(9, thumbIs);
int nbrows = ps.executeUpdate();
if (nbrows != 1)
{
log.warning("Image(" + getID() + ") not inserted");
res = C_FAIL;
}
ResultSet rsid = ps.getGeneratedKeys();
if (rsid.next())
{
setID(rsid.getLong(1));
}
rsid.close();
}
catch (SQLException sqex)
{
log.warning("Image(" + getID() + ") error");
res = C_ERROR;
}
return res;
}
public int delete(DataStore das)
{
int res = C_OK;
try
{
PreparedStatement ps = das.getDelete(AttrType.T_Image);
// (1) ID
ps.setLong(1, getID());
int nbrows = ps.executeUpdate();
if (nbrows != 1)
{
log.warning("Image deletion failed (" + getID() + ") ROWS modified:" + nbrows);
res = C_FAIL;
}
}
catch (SQLException sqex)
{
log.warning("Image(" + getID() + ") error");
res = C_ERROR;
}
return res;
}
public int update(DataStore das)
{
int res = C_OK;
try
{
PreparedStatement ps = das.getUpdate(AttrType.T_Image);
// (1) DATAPATHID INT
ps.setLong(1, _dataPath.getID());
// (2) RELPATH VARCHAR(1024)
ps.setString(2, _path);
// (3) FILESIZE INT(9)
ps.setLong(3, _fileSize);
// (4) LASTMODIFTIME TIMESTAMP
ps.setTimestamp(4, new Timestamp(_lmd));
// (5) WIDTH INT(4)
ps.setInt(5, _width);
// (6) HEIGHT(4)
ps.setInt(6, _height);
// (7) COLORMODEL INT(1)
ps.setInt(7, 0);
// (8) ORIENTATION INT(1)
ps.setInt(8, 0);
// (9) THUMB_LARGE
ImageLoader imldr = new ImageLoader();
imldr.data = new ImageData[]
{
_thumb
};
ByteArrayOutputStream bos = new ByteArrayOutputStream(64000);
imldr.save(bos, SWT.IMAGE_JPEG);
InputStream thumbIs = new ByteArrayInputStream(bos.toByteArray());
ps.setBinaryStream(9, thumbIs);
// (10) ID
ps.setLong(10, getID());
int nbrows = ps.executeUpdate();
if (nbrows != 1)
{
log.warning("Image(" + getID() + ") not inserted");
res = C_FAIL;
}
}
catch (SQLException sqex)
{
log.warning("Image(" + getID() + ") error");
res = C_ERROR;
}
return res;
}
}