/*******************************************************************************
* Copyright 2009, 2010 Innovation Gate GmbH. All Rights Reserved.
*
* This file is part of the OpenWGA server platform.
*
* OpenWGA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, a special exception is granted by the copyright holders
* of OpenWGA called "OpenWGA plugin exception". You should have received
* a copy of this exception along with OpenWGA in file COPYING.
* If not, see <http://www.openwga.com/gpl-plugin-exception>.
*
* OpenWGA 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenWGA in file COPYING.
* If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package de.innovationgate.webgate.api.jdbc;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Blob;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.sf.cglib.beans.BeanMap;
import org.apache.commons.codec.binary.Hex;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.DOMWriter;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.ValidationException;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.exception.ConstraintViolationException;
import org.omg.stub.java.rmi._Remote_Stub;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.Dom4JDriver;
import de.innovationgate.webgate.api.WGAPIException;
import de.innovationgate.webgate.api.WGBackendException;
import de.innovationgate.webgate.api.WGContent;
import de.innovationgate.webgate.api.WGDatabase;
import de.innovationgate.webgate.api.WGDocument;
import de.innovationgate.webgate.api.WGDocumentCore;
import de.innovationgate.webgate.api.WGExpressionException;
import de.innovationgate.webgate.api.WGExtensionDataContainer;
import de.innovationgate.webgate.api.WGFactory;
import de.innovationgate.webgate.api.WGFileMetaData;
import de.innovationgate.webgate.api.WGIllegalArgumentException;
import de.innovationgate.webgate.api.WGIllegalDataException;
import de.innovationgate.webgate.api.WGIllegalStateException;
import de.innovationgate.webgate.api.WGInvalidDatabaseException;
import de.innovationgate.webgate.api.WGNotSupportedException;
import de.innovationgate.webgate.api.WGPortletRegistry;
import de.innovationgate.webgate.api.WGRelationData;
import de.innovationgate.webgate.api.WGStructEntry;
import de.innovationgate.webgate.api.WGSystemException;
import de.innovationgate.webgate.api.WGUpdateLog;
import de.innovationgate.webgate.api.WGUserProfile;
/**
* To change this generated comment edit the template variable "typecomment":
* Window>Preferences>Java>Templates. To enable and disable the creation of type
* comments go to Window>Preferences>Java>Code Generation.
*/
public class WGDocumentImpl implements WGDocumentCore {
static class FileExtDataHandler implements WGExtensionDataContainer {
private Entity _fileEntity;
private WGDatabaseImpl _dbCore;
private FileExtDataHandler(WGDatabaseImpl dbCore, Entity fileEntity) {
_dbCore = dbCore;
_fileEntity = fileEntity;
}
public Object getExtensionData(String strName) throws WGAPIException {
strName = strName.toLowerCase().trim();
ExtensionData att = _fileEntity.getExtensionData().get(strName);
if (att != null) {
return readItemValue(att);
}
else {
return null;
}
}
public List getExtensionDataNames() throws WGAPIException {
return new ArrayList(_fileEntity.getExtensionData().keySet());
}
public void removeExtensionData(String name) throws WGAPIException {
name = name.toLowerCase().trim();
ExtensionData item = (ExtensionData) _fileEntity.getExtensionData().get(name);
if (item != null) {
Hibernate.initialize(_fileEntity.getExtensionData());
Item oldItem = (Item) _fileEntity.getExtensionData().remove(name);
}
}
public void writeExtensionData(String strName, Object value) throws WGAPIException {
strName = strName.toLowerCase().trim();
// Convert numbers to doubles
if (value instanceof Number && !(value instanceof Double)) {
value = new Double(((Number) value).doubleValue());
}
Map atts = _fileEntity.getExtensionData();
ExtensionData att = (ExtensionData) atts.get(strName);
if (att == null) {
ExtensionData newAtt = new ExtensionData();
newAtt.setEntity((Entity) _fileEntity);
newAtt.setName(strName);
ExtensionData oldItem = (ExtensionData) atts.put(newAtt.getName(), newAtt);
att = newAtt;
}
writeItemValue(_dbCore, att, value);
}
}
public static final int ATTACHMENT_FILEPART_SIZE = 1024*64-1;
/**
* Column to store struct entry workflow names is "WORKFLOW", not "OVERRIDE_WORKFLOW" (which must be kept bc. of other WGACS implemenetations)
*/
public static final String ENTITYPROP_STRUCTENTRY_WORKFLOW = "WORKFLOW";
public static final int ITEMTYPE_STRING = 1;
public static final int ITEMTYPE_NUMBER = 2;
public static final int ITEMTYPE_DATE = 3;
public static final int ITEMTYPE_SERIALIZED_CASTOR = 4;
public static final int ITEMTYPE_SERIALIZED_XSTREAM = 5;
public static final int ITEMTYPE_BOOLEAN = 6;
private WGDocument _document;
protected WGDatabaseImpl _parent;
private int _type;
protected MainEntity _entity;
protected BeanMap _beanMap = null;
private BeanMap getBeanMap() {
if (_beanMap == null) {
BeanMap.Generator gen = new BeanMap.Generator();
gen.setBean(_entity);
gen.setUseCache(true);
_beanMap = gen.create();
}
return _beanMap;
}
protected Content _content;
protected UserProfile _profile;
/**
* map of Content- or ContainerFileMetas attached on this entity - mapped by fileName
* during this session
*/
private Map _attachedFiles = new HashMap();
/**
* map of Content- or ContainerFileMeta objects removed on this entity during this session - mapped by fileName
* for all these metas - file data is deleted via HQL on save()
*/
private Map _removedFiles = new HashMap();
private WGPortletRegistry _portletRegistry;
protected WGDocumentImpl(WGDatabaseImpl parent, MainEntity entity, int type) {
this._parent = parent;
this._type = type;
this._entity = entity;
if (type == WGDocument.TYPE_CONTENT) {
_content = (Content) entity;
}
else if (type == WGDocument.TYPE_USERPROFILE) {
_profile = (UserProfile) entity;
_portletRegistry = createPortletRegistry();
}
}
/**
* @throws WGIllegalStateException - if method is unsupported on the current document
* @throws WGIllegalArgumentException - if a file of the same name already exists
* @throws WGAPIException
* @see de.innovationgate.webgate.api.WGDocumentCore#attachFile(File)
*/
public boolean attachFile(File file) throws WGAPIException {
if ((_entity instanceof Content || _entity instanceof FileContainer) == false) {
// B0000471E
throw new WGIllegalStateException("Method attachFile() is not supported on '" + _entity.getClass().getName() + "'.");
}
if (_parent.useOptimizedFileHandling()) {
attachFileOptimizedImpl(file);
} else {
attachFileDefaultImpl(file);
}
return true;
}
private void attachFileDefaultImpl(File file)
throws WGIllegalArgumentException, WGBackendException {
try {
// See if a file of that name is already attached
String convertedFileName = _parent.convertFileNameForAttaching(file.getName());
if (_content != null) {
if (_content.getFiles().containsKey(convertedFileName)) {
// B0000471E
throw new WGIllegalArgumentException("A file with the same name '" + convertedFileName + "' is already attached on this document, please remove it first.");
}
}
else {
FileContainer cont = (FileContainer) _entity;
if (cont.getFiles().containsKey(convertedFileName)) {
// B0000471E
throw new WGIllegalArgumentException("A file with the same name '" + convertedFileName + "' is already present in this file container, please remove it first.");
}
}
// Load the data
InputStream in = new BufferedInputStream(new FileInputStream(file));
Blob blob = Hibernate.createBlob(in);
// Create entity and attach to parent entity
// TB
if (_content != null) {
ContentFile fileAtt = new ContentFile();
fileAtt.setParentcontent(_content);
fileAtt.setName(convertedFileName);
fileAtt.setData(blob);
ContentFile oldFile = (ContentFile) _content.getFiles().put(convertedFileName, fileAtt);
if (oldFile != null && oldFile != fileAtt) {
_parent.getSession().evict(oldFile);
}
}
else {
FileContainer cont = (FileContainer) _entity;
ContainerFile fileAtt = new ContainerFile();
fileAtt.setParentcontainer(cont);
fileAtt.setName(convertedFileName);
fileAtt.setData(blob);
ContainerFile oldFile = (ContainerFile) cont.getFiles().put(convertedFileName, fileAtt);
if (oldFile != null && oldFile != fileAtt) {
_parent.getSession().evict(oldFile);
}
}
}
catch (FileNotFoundException e) {
throw new WGIllegalArgumentException("Error attaching file - not found.", e);
}
catch (IOException e) {
throw new WGBackendException("Error attaching file.", e);
}
}
private void attachFileOptimizedImpl(File file)
throws WGIllegalArgumentException, WGBackendException {
// See if a file of that name is already attached
String convertedFileName = _parent.convertFileNameForAttaching(file
.getName());
if (_content != null) {
if (_content.getFiles().containsKey(convertedFileName)) {
// B0000471E
throw new WGIllegalArgumentException(
"A file with the same name '"
+ convertedFileName
+ "' is already attached on this document, please remove it first.");
}
} else {
FileContainer cont = (FileContainer) _entity;
if (cont.getFiles().containsKey(convertedFileName)) {
// B0000471E
throw new WGIllegalArgumentException(
"A file with the same name '"
+ convertedFileName
+ "' is already present in this file container, please remove it first.");
}
}
// Create meta entity and attach to parent entity
if (_content != null) {
ContentFileMeta fileMeta = new ContentFileMeta();
fileMeta.setParentcontent(_content);
fileMeta.setName(convertedFileName);
fileMeta.setSize(file.length());
Date now = new Date();
fileMeta.setCreated(now);
fileMeta.setLastmodified(now);
fileMeta.setSourceFile(file);
_content.getFiles().put(convertedFileName, fileMeta);
_attachedFiles.put(convertedFileName, fileMeta);
_removedFiles.remove(convertedFileName);
}
else {
FileContainer cont = (FileContainer) _entity;
ContainerFileMeta fileMeta = new ContainerFileMeta();
fileMeta.setParentcontainer(cont);
fileMeta.setName(convertedFileName);
fileMeta.setSize(file.length());
fileMeta.setCreated(new Date());
fileMeta.setSourceFile(file);
cont.getFiles().put(convertedFileName, fileMeta);
_attachedFiles.put(convertedFileName, fileMeta);
_removedFiles.remove(convertedFileName);
}
}
/**
* @throws HibernateException
* @throws WGSystemException
* @see de.innovationgate.webgate.api.WGDocumentCore#dispose()
*/
public void dispose() throws WGSystemException, HibernateException {
// Prevents that changes to the entity are again picked up if this document is re-read
if (isSaved()) {
getParent().getSession().evict(_entity);
}
}
/**
* @see de.innovationgate.webgate.api.WGDocumentCore#evaluateExpression(String)
*/
public Object evaluateExpression(String expression) throws WGExpressionException {
return null;
}
/**
* @throws WGSystemException
* @see de.innovationgate.webgate.api.WGDocumentCore#getCreated()
*/
public Date getCreated() {
return (Date) getBeanMap().get(WGDocument.META_CREATED.toLowerCase());
}
/**
* @see de.innovationgate.webgate.api.WGDocumentCore#getFastAccessKey()
*/
public Object getFastAccessKey() {
if (_parent._ddlVersion >= WGDatabase.CSVERSION_WGA5) {
return new WGDatabaseImpl.V5FastAccessKey(_type, _entity.getId());
}
else {
if (_content != null) {
if (_content.getId() != null) {
return _content.getId();
}
else {
return _content.getCuid();
}
}
else {
return null;
}
}
}
/**
* @throws WGAPIException
* @see de.innovationgate.webgate.api.WGDocumentCore#getFileData(String)
*/
public InputStream getFileData(String strFile) throws WGAPIException {
if (_parent.useOptimizedFileHandling()) {
return getFileDataOptimizedImpl(strFile);
} else {
return getFileDataDefaultImpl(strFile);
}
}
private InputStream getFileDataDefaultImpl(String strFile)
throws WGBackendException {
try {
Iterator it = fetchFileEntity(strFile);
if (it.hasNext()) {
Object fileEntity = it.next();
_parent.getSession().refresh(fileEntity);
if (fileEntity instanceof ContentFile) {
return ((ContentFile) fileEntity).getData().getBinaryStream();
}
else if (fileEntity instanceof ContainerFile) {
return ((ContainerFile) fileEntity).getData().getBinaryStream();
}
else {
throw new WGBackendException("Unknown file entity type " + fileEntity.getClass().getName());
}
}
else {
return null;
}
/*strFile = _parent.convertFileNameForAttaching(strFile);
if (_content != null) {
ContentFile fileAtt = (ContentFile) _content.getFiles().get(strFile);
if (fileAtt == null) {
return null;
}
return fileAtt.getData().getBinaryStream();
}
else if (_entity instanceof FileContainer) {
FileContainer cont = (FileContainer) _entity;
ContainerFile fileAtt = (ContainerFile) cont.getFiles().get(strFile);
if (fileAtt == null) {
return null;
}
return fileAtt.getData().getBinaryStream();
}
else {
return null;
}*/
}
catch (SQLException e) {
throw new WGBackendException("Error retrieving file data", e);
}
}
private InputStream getFileDataOptimizedImpl(String strFile)
throws WGBackendException {
Iterator it = fetchFileMetaEntity(strFile);
if (it.hasNext()) {
Object fileEntity = it.next();
if (fileEntity instanceof ContentFileMeta) {
ContentFileMeta meta = ((ContentFileMeta)fileEntity);
String hqlQuery = "select cfp from ContentFilePart as cfp where cfp.meta=:metaEntity order by cfp.partnr asc";
Query query = _parent.getSession().createQuery(hqlQuery);
query.setParameter("metaEntity", meta);
return createOptimizedInputStream(query);
} else if (fileEntity instanceof ContainerFileMeta) {
ContainerFileMeta meta = ((ContainerFileMeta)fileEntity);
String hqlQuery = "select cfp from ContainerFilePart as cfp where cfp.meta=:metaEntity order by cfp.partnr asc";
Query query = _parent.getSession().createQuery(hqlQuery);
query.setParameter("metaEntity", meta);
return createOptimizedInputStream(query);
} else {
throw new WGBackendException("Unknown file entity type "
+ fileEntity.getClass().getName());
}
} else {
return null;
}
}
protected InputStream createOptimizedInputStream(Query query) {
return new HibernateQueryInputStream(query, 0, _parent.isOptimizedFileHandlingDisableQueryPaging());
}
/**
* @throws WGAPIException
* @throws WGSystemException
* @see de.innovationgate.webgate.api.WGDocumentCore#getFileNames()
*/
public List getFileNames() throws WGAPIException {
if (_parent.useOptimizedFileHandling()) {
return getFileNamesOptimizedImpl();
} else {
return getFileNamesDefaultImpl();
}
}
private List getFileNamesDefaultImpl() throws WGBackendException {
// We cannot query if the entity is transient
if (getCreated() == null) {
return new ArrayList();
}
String hqlQuery;
if (_content != null) {
hqlQuery = "select cf.name from ContentFile cf where cf.parentcontent=:entity";
}
else if (_entity instanceof FileContainer) {
hqlQuery = "select cf.name from ContainerFile cf where cf.parentcontainer=:entity";
}
else {
throw new WGBackendException("Unknown entity type " + _entity.getClass().getName());
}
Query query = _parent.getSession().createQuery(hqlQuery);
query.setParameter("entity", _entity);
return query.list();
}
private List getFileNamesOptimizedImpl() throws WGBackendException {
if (_content != null) {
return new ArrayList(_content.getFiles().keySet());
}
else if (_entity instanceof FileContainer) {
return new ArrayList(((FileContainer)_entity).getFiles().keySet());
}
else {
throw new WGBackendException("Unknown entity type " + _entity.getClass().getName());
}
}
/**
* @throws WGAPIException
* @see de.innovationgate.webgate.api.WGDocumentCore#getFileSize(String)
*/
public int getFileSize(String strFile) throws WGAPIException {
if (_parent.useOptimizedFileHandling()) {
return getFileSizeOptimizedImpl(strFile);
} else {
return getFileSizeDefaultImpl(strFile);
}
}
private int getFileSizeOptimizedImpl(String strFile)
throws WGBackendException {
String convertedFileName = _parent.convertFileNameForAttaching(strFile);
if (_content != null) {
ContentFileMeta meta = (ContentFileMeta) _content.getFiles().get(convertedFileName);
if (meta != null) {
return (int) meta.getSize();
} else {
return -1;
}
}
else if (_entity instanceof FileContainer) {
ContainerFileMeta meta = (ContainerFileMeta) ((FileContainer)_entity).getFiles().get(convertedFileName);
if (meta != null) {
return (int) meta.getSize();
} else {
return -1;
}
} else {
throw new WGBackendException("Unknown entity type " + _entity.getClass().getName());
}
}
private int getFileSizeDefaultImpl(String strFile)
throws WGBackendException {
try {
Iterator it = fetchFileEntity(strFile);
if (it.hasNext()) {
Object fileEntity = it.next();
if (fileEntity instanceof ContentFile) {
return (int) ((ContentFile) fileEntity).getData().length();
}
else if (fileEntity instanceof ContainerFile) {
return (int) ((ContainerFile) fileEntity).getData().length();
}
else {
throw new WGBackendException("Unknown file entity type " + fileEntity.getClass().getName());
}
}
else {
return -1;
}
/* if (_content != null) {
ContentFile fileAtt = (ContentFile) _content.getFiles().get(strFile);
if (fileAtt == null) {
return -1;
}
return (int) fileAtt.getData().length();
}
else if (_entity instanceof FileContainer) {
FileContainer cont = (FileContainer) _entity;
ContainerFile fileAtt = (ContainerFile) cont.getFiles().get(strFile);
if (fileAtt == null) {
return -1;
}
return (int) fileAtt.getData().length();
}
else {
return -1;
}*/
}
catch (HibernateException e) {
throw new WGBackendException("Error retrieving blob size", e);
}
catch (SQLException e) {
throw new WGBackendException("Error retrieving blob size", e);
}
}
private Iterator fetchFileEntity(String strFile) throws WGBackendException, HibernateException {
// We cannot query if the entity is transient
if (getCreated() == null) {
return (new ArrayList()).iterator();
}
strFile = _parent.convertFileNameForAttaching(strFile);
String hqlQuery;
if (_content != null) {
hqlQuery = "select cf from ContentFile cf where cf.parentcontent=:entity and cf.name=:name";
}
else if (_entity instanceof FileContainer) {
hqlQuery = "select cf from ContainerFile cf where cf.parentcontainer=:entity and cf.name=:name";
}
else {
throw new WGBackendException("Unknown entity type " + _entity.getClass().getName());
}
Query query = _parent.getSession().createQuery(hqlQuery);
query.setParameter("entity", _entity);
query.setParameter("name", strFile);
Iterator it = query.iterate();
return it;
}
private Iterator fetchFileMetaEntity(String strFile) throws WGBackendException, HibernateException {
// We cannot query if the entity is transient
if (getCreated() == null) {
return (new ArrayList()).iterator();
}
strFile = _parent.convertFileNameForAttaching(strFile);
String hqlQuery;
if (_content != null) {
hqlQuery = "select cfm from ContentFileMeta cfm where cfm.parentcontent=:entity and cfm.name=:name";
}
else if (_entity instanceof FileContainer) {
hqlQuery = "select cf from ContainerFileMeta cf where cf.parentcontainer=:entity and cf.name=:name";
}
else {
throw new WGBackendException("Unknown entity type " + _entity.getClass().getName());
}
Query query = _parent.getSession().createQuery(hqlQuery);
query.setParameter("entity", _entity);
query.setParameter("name", strFile);
Iterator it = query.iterate();
return it;
}
/**
* @see de.innovationgate.webgate.api.WGDocumentCore#getItemNames()
*/
public List getItemNames() {
if (_content != null) {
return new ArrayList(_content.getItems().keySet());
}
else if (_profile != null) {
return new ArrayList(_profile.getItems().keySet());
}
else {
return new ArrayList();
}
}
/**
* @throws WGSystemException
* @throws WGBackendException
* @see de.innovationgate.webgate.api.WGDocumentCore#getItemValue(String)
*/
public Object getItemValue(String strName) throws WGSystemException, WGBackendException {
try {
strName = strName.toLowerCase();
Item item = null;
if (_content != null) {
item = (Item) _content.getItems().get(strName);
}
else if (_profile != null) {
item = (Item) _profile.getItems().get(strName);
}
if (item == null) {
return new ArrayList();
}
return readItemValue(item);
}
catch (HibernateException e) {
throw new WGBackendException("Exception retrieving item " + strName, e);
}
}
protected static Object readItemValue(Item item) throws WGIllegalDataException, WGSystemException {
switch (item.getType()) {
case ITEMTYPE_SERIALIZED_XSTREAM:
try {
XStream xstream = new XStream(new Dom4JDriver());
return xstream.fromXML(item.getText());
}
catch (Exception e) {
throw new WGIllegalDataException("Error deserializing itemvalue of type 'ITEMTYPE_SERIALIZED_XSTREAM'.", e);
}
case ITEMTYPE_SERIALIZED_CASTOR:
Unmarshaller unmarshaller = new Unmarshaller();
try {
// Workaround for castor bug. Primitive wrappers for
// boolean, character, long do not contain xsi:type
Document doc = DocumentHelper.parseText(item.getText());
Element root = doc.getRootElement();
if (root.getName().equals("boolean")) {
root.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.addAttribute("xsi:type", "java:java.lang.Boolean");
}
else if (root.getName().equals("character")) {
root.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.addAttribute("xsi:type", "java:java.lang.Boolean");
}
else if (root.getName().equals("long")) {
root.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.addAttribute("xsi:type", "java:java.lang.Long");
}
else if (root.getName().equals("array-list")) {
root.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.addAttribute("xsi:type", "java:java.util.ArrayList");
}
DOMWriter domWriter = new DOMWriter();
return unmarshaller.unmarshal(domWriter.write(doc));
// return unmarshaller.unmarshal(new
// StringReader(item.getText()));
}
catch (MarshalException e) {
throw new WGIllegalDataException("Error unmarshaling serialized object", e);
}
catch (ValidationException e) {
throw new WGIllegalDataException("Error unmarshaling serialized object", e);
}
catch (DocumentException e) {
throw new WGIllegalDataException("Error unmarshaling serialized object", e);
}
case ITEMTYPE_STRING:
return item.getText();
case ITEMTYPE_NUMBER:
return item.getNumber();
case ITEMTYPE_DATE:
return new Date(item.getDate().getTime());
case ITEMTYPE_BOOLEAN:
return new Boolean(item.getNumber().doubleValue() == 1);
default:
throw new WGSystemException("Unsupported itemtype '" + item.getType() + "'.");
}
}
/**
* @throws WGSystemException
* @see de.innovationgate.webgate.api.WGDocumentCore#getLastModified()
*/
public Date getLastModified() throws WGSystemException {
return (Date) getBeanMap().get(WGDocument.META_LASTMODIFIED.toLowerCase());
}
/**
* @throws WGBackendException
* @see de.innovationgate.webgate.api.WGDocumentCore#getMetaData(String)
*/
public Object getMetaData(String name) throws WGBackendException {
try {
// Special metas
if (name.equals(WGDocument.META_PASTAUTHORS)) {
return getPastAuthors();
}
else if (name.equals(WGDocument.META_PASTEDITDATES)) {
return getPastEditDates();
}
else if (name.equals(WGDocument.META_REVISION)) {
return new Integer(getRevision());
}
else if (_entity instanceof StructEntry && name.equals(WGStructEntry.META_WORKFLOW_NAME)) {
return getStructWorkflowName();
}
else if (name.equals(WGUserProfile.META_PORTLETREGISTRY)) {
return _portletRegistry;
}
Object value = getBeanMap().get(name.toLowerCase());;
// Return keys to entities
if (value instanceof MainEntity) {
if (name.equals(WGStructEntry.META_AREA)) {
value = ((Area) value).getName();
}
else if (name.equals(WGStructEntry.META_CONTENTTYPE)) {
value = ((ContentType) value).getName();
}
else if (name.equals(WGContent.META_STRUCTENTRY)) {
value = ((StructEntry) value).getKey();
}
else if (name.equals(WGContent.META_LANGUAGE)) {
value = ((Language) value).getName();
}
}
// Convert SQL-special date derivates to a standard date
else if (value instanceof Date) {
value = new Date(((Date) value).getTime());
}
return value;
}
catch (HibernateException e) {
throw new WGBackendException("Exception retrieving metadata field " + name, e);
}
}
/**
* The struct's workflow name is stored in the column ORIGINALKEY, which was used before
* WGA 3.3.1 to store the struct key of the original struct, from which this struct was cloned.
* Some functionality is needed to determine if the column contains an obsolete original
* key or a workflow name.
*/
private Object getStructWorkflowName() {
StructEntry struct = (StructEntry) _entity;
String wfName = struct.getWorkflow();
// If no workflow stored: Either the column is empty, or the original key equals
// the struct key (since cloned entries always have the same key as their originals,
// which is why this columns original meaning is obsolete)
if (wfName == null || wfName.equals(struct.getKey())) {
return null;
}
else {
return wfName;
}
}
/**
* @return
*/
private int getRevision() {
return getLogEntries().size();
}
/**
* @return
*/
private Object getPastEditDates() {
Iterator logEntries = getLogEntries().iterator();
LogEntry logEntry;
List pastEditDates = new ArrayList();
while (logEntries.hasNext()) {
logEntry = (LogEntry) logEntries.next();
pastEditDates.add(logEntry.getLogtime());
}
return pastEditDates;
}
/**
* @return
*/
private List getPastAuthors() {
Iterator logEntries = getLogEntries().iterator();
LogEntry logEntry;
List pastAuthors = new ArrayList();
while (logEntries.hasNext()) {
logEntry = (LogEntry) logEntries.next();
pastAuthors.add(logEntry.getLoguser());
}
return pastAuthors;
}
/**
*
*/
private List getLogEntries() {
try {
Session session = _parent.getSession();
String queryString = "from LogEntry where target=:target ";
if (_parent._ddlVersion >= WGDatabase.CSVERSION_WGA5) {
queryString += "order by id asc";
}
else {
queryString += "order by logtime asc";
}
Query query = session.createQuery(queryString);
query.setParameter("target", _document.getDocumentKey());
return query.list();
}
catch (HibernateException e) {
WGFactory.getLogger().error("Error retrieving log entries for document '" + _document.getDocumentKey() + "'", e);
return new ArrayList();
}
}
/**
* @see de.innovationgate.webgate.api.WGDocumentCore#getType()
*/
public int getType() {
return this._type;
}
/**
* @see de.innovationgate.webgate.api.WGDocumentCore#hasItem(String)
*/
public boolean hasItem(String strName) {
strName = strName.toLowerCase().trim();
if (_content != null) {
return _content.getItems().containsKey(strName);
}
else if (_profile != null) {
return _profile.getItems().containsKey(strName);
}
else {
return false;
}
}
/**
* @see de.innovationgate.webgate.api.WGDocumentCore#isDataCacheable()
*/
public boolean isDataCacheable() {
return true;
}
/**
* @throws WGSystemException
* @see de.innovationgate.webgate.api.WGDocumentCore#isDeleted()
*/
public boolean isDeleted() throws WGSystemException {
// A just created document cannot be regarded as deleted
if (!isSaved()) {
return false;
}
// See if the entity is still part of the session
if (_parent.getSession().contains(_entity)) {
return false;
}
// Still may be just a stale entity. Try to refresh it, then check again
try {
_parent.getSession().refresh(_entity);
if (_parent.getSession().contains(_entity)) {
return false;
}
}
catch (HibernateException e) {
}
return true;
}
/**
* @throws WGSystemException
* @see de.innovationgate.webgate.api.WGDocumentCore#isTemporary()
*/
public boolean isTemporary() throws WGSystemException {
return !isSaved();
}
/**
* @throws WGBackendException
* @see de.innovationgate.webgate.api.WGDocumentCore#remove()
*/
public boolean remove() throws WGAPIException {
try {
// for optimized file handling first remove all files - otherwise we might exhaust our heap
if (_parent.useOptimizedFileHandling() && (_entity instanceof Content || _entity instanceof FileContainer)) {
Iterator fileNames = getFileNames().iterator();
while (fileNames.hasNext()) {
String filename = (String) fileNames.next();
Iterator it = fetchFileMetaEntity(filename);
deleteFileData(it);
}
}
Session session = _parent.getSession();
if (getType() != WGDocument.TYPE_USERPROFILE) {
_parent.createLogEntry(session, WGUpdateLog.TYPE_DELETE, _document.getDocumentKey(), _entity.getId());
}
// Dereferencings of special object types
// Manual initializings are workaround for hibernate bug B00005D36
if (_entity instanceof Content) {
Content content = (Content) _entity;
Hibernate.initialize(content.getStructentry().getContent());
content.getStructentry().getContent().remove(content);
}
else if (_entity instanceof StructEntry) {
StructEntry entry = (StructEntry) _entity;
if (entry.getParententry() != null) {
Hibernate.initialize(entry.getParententry().getChildentries());
entry.getParententry().getChildentries().remove(entry.getKey());
}
else {
Hibernate.initialize(entry.getArea().getRootentries());
entry.getArea().getRootentries().remove(entry.getKey());
}
}
session.delete(_entity);
_parent.commitHibernateTransaction();
session.evict(_entity);
}
catch (ConstraintViolationException e) {
throw new WGBackendException("Deletion of document failed because of database constraint violation", e);
}
catch (HibernateException e) {
_parent.rollbackHibernateTransaction();
throw new WGBackendException("Error deleting entity", e);
}
return true;
}
/**
* @throws WGAPIException
* @see de.innovationgate.webgate.api.WGDocumentCore#removeFile(String)
*/
public boolean removeFile(String name) throws WGAPIException {
name = _parent.convertFileNameForAttaching(name);
if ((_entity instanceof Content || _entity instanceof FileContainer) == false) {
return false;
}
if (_parent.useOptimizedFileHandling()) {
removeFileOptimizedImpl(name);
} else {
removeFileDefaultImpl(name);
}
return true;
}
private void removeFileOptimizedImpl(String name) {
if (_content != null) {
ContentFileMeta fileMeta = (ContentFileMeta) _content.getFiles().get(name);
if (fileMeta != null) {
_removedFiles.put(name, fileMeta);
_attachedFiles.remove(name);
Hibernate.initialize(_content.getFiles());
_content.getFiles().remove(name);
}
}
else {
FileContainer cont = (FileContainer) _entity;
ContainerFileMeta fileMeta = (ContainerFileMeta) cont.getFiles().get(name);
if (fileMeta != null) {
_removedFiles.put(name, fileMeta);
_attachedFiles.remove(name);
Hibernate.initialize(cont.getFiles());
cont.getFiles().remove(name);
}
}
}
private void removeFileDefaultImpl(String name) {
if (_content != null) {
ContentFile fileAtt = (ContentFile) _content.getFiles().get(name);
if (fileAtt != null) {
Hibernate.initialize(_content.getFiles());
_content.getFiles().remove(name);
}
}
else {
FileContainer cont = (FileContainer) _entity;
ContainerFile fileAtt = (ContainerFile) cont.getFiles().get(name);
if (fileAtt != null) {
Hibernate.initialize(cont.getFiles());
cont.getFiles().remove(name);
}
}
}
/**
* @throws WGIllegalArgumentException
* @see de.innovationgate.webgate.api.WGDocumentCore#removeItem(String)
*/
public boolean removeItem(String name) throws WGIllegalArgumentException {
name = name.toLowerCase();
if ((_entity instanceof Content || _entity instanceof UserProfile) == false) {
String className = null;
if (_entity != null) {
className = _entity.getClass().getName();
}
throw new WGIllegalArgumentException("Cannot remove item on document of type '" + className + "' - doctype has no items.");
}
if (_content != null) {
Hibernate.initialize(_content.getItems());
ContentItem item = (ContentItem) _content.getItems().get(name);
if (item != null) {
Item oldItem = (Item) _content.getItems().remove(name);
}
}
else {
Hibernate.initialize(_profile.getItems());
UserProfileItem item = (UserProfileItem) _profile.getItems().get(name);
if (item != null) {
Item oldItem = (Item) _profile.getItems().remove(name);
}
}
return true;
}
/**
* @see de.innovationgate.webgate.api.WGDocumentCore#resultIsFalse(Object)
*/
public boolean resultIsFalse(Object result) {
return false;
}
/**
* @see de.innovationgate.webgate.api.WGDocumentCore#resultIsTrue(Object)
*/
public boolean resultIsTrue(Object result) {
return false;
}
/**
* @throws WGAPIException
* @see de.innovationgate.webgate.api.WGDocumentCore#save()
*/
public boolean save(java.util.Date lastModified) throws WGAPIException {
if (lastModified == null) {
lastModified = new Date();
}
try {
Session session = _parent.getSession();
// Save object
if (getCreated() == null) {
setCreated(lastModified);
setLastModified(lastModified);
session.save(_entity);
}
else {
setLastModified(lastModified);
}
// Update content relations to this document if it is a content
if (_content != null && _content.getStatus().equals(WGContent.STATUS_RELEASE)) {
_parent.updateContentRelations(_content);
}
// Update log entry
if (getType() != WGDocument.TYPE_USERPROFILE) {
_parent.createLogEntry(session, WGUpdateLog.TYPE_UPDATE, WGDocument.buildDocumentKey(this, _parent.getDb()).toString(), _entity.getId());
}
// Update file data in optimized file handling
if (_parent.useOptimizedFileHandling()) {
/**
* delete file data via HQL, otherwise Hibernate will load all file data into memory
*/
deleteFileData(_removedFiles.values().iterator());
/**
* flush session - we need the generated identifiers for metas in the next steps
*/
session.flush();
/**
* save data of attached files
*/
saveFileData(_attachedFiles.values().iterator());
}
// Commit transaction
_parent.commitHibernateTransaction();
// Clear temporary collector objects
_removedFiles.clear();
_attachedFiles.clear();
return true;
}
catch (HibernateException e) {
_parent.rollbackHibernateTransaction();
throw new WGBackendException("Error saving hibernate document.", e);
}
catch (WGAPIException e) {
_parent.rollbackHibernateTransaction();
throw e;
} catch (IOException e) {
_parent.rollbackHibernateTransaction();
throw new WGBackendException("Error saving hibernate document.", e);
}
}
/**
* saves file data of given metas
* @param metas
* @throws IOException
*/
private void saveFileData(Iterator metas) throws IOException {
// create digest for checksum computation
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
// ignore digest creation
}
while (metas.hasNext()) {
if (digest != null) {
digest.reset();
}
Object attachedMeta = metas.next();
if (attachedMeta instanceof ContentFileMeta) {
ContentFileMeta fileMeta = (ContentFileMeta) attachedMeta;
InputStream in = new BufferedInputStream(new FileInputStream(fileMeta.getSourceFile()));
// store file data
// split up file in parts with 64K end store each part
int partnr = 0;
byte[] buffer = new byte[ATTACHMENT_FILEPART_SIZE];
int len = in.read(buffer);
while (len > 0) {
// create new file part
ContentFilePart part = new ContentFilePart();
part.setMeta(fileMeta);
part.setPartnr(partnr);
Blob data = Hibernate.createBlob(new ByteArrayInputStream(buffer, 0, len));
part.setData(data);
// store file part
_parent.getSession().save(part);
_parent.getSession().flush();
_parent.getSession().evict(part);
// update md5 digest
if (digest != null) {
digest.update(buffer, 0, len);
}
// read next part from inputstream
partnr++;
len = in.read(buffer);
}
// store md5 sum as meta
if (digest != null) {
fileMeta.setChecksum(new String(Hex.encodeHex(digest.digest())));
}
} else if (attachedMeta instanceof ContainerFileMeta) {
ContainerFileMeta fileMeta = (ContainerFileMeta) attachedMeta;
InputStream in = new BufferedInputStream(new FileInputStream(fileMeta.getSourceFile()));
// store file data
// split up file in parts with 64K end store each part
int partnr = 0;
byte[] buffer = new byte[ATTACHMENT_FILEPART_SIZE];
int len = in.read(buffer);
while (len > 0) {
// create new file part
ContainerFilePart part = new ContainerFilePart();
part.setMeta(fileMeta);
part.setPartnr(partnr);
Blob data = Hibernate.createBlob(new ByteArrayInputStream(buffer, 0, len));
part.setData(data);
// store file part
_parent.getSession().save(part);
_parent.getSession().flush();
_parent.getSession().evict(part);
// update md5 digest
if (digest != null) {
digest.update(buffer, 0, len);
}
// read next part from inputstream
partnr++;
len = in.read(buffer);
}
// store md5 sum as meta
if (digest != null) {
fileMeta.setChecksum(new String(Hex.encodeHex(digest.digest())));
}
}
}
}
/**
* deletes all file data for the given meta entities
* deletion is done via HQL to not exhaust HEAP
* @param metas
*/
private void deleteFileData(Iterator metas) {
while (metas.hasNext()) {
Object removedMeta = metas.next();
if (removedMeta instanceof ContentFileMeta) {
Query query = _parent.getSession().createQuery("delete ContentFilePart cfp where cfp.meta = :meta");
query.setEntity("meta", removedMeta);
query.executeUpdate();
} else if (removedMeta instanceof ContainerFileMeta) {
Query query = _parent.getSession().createQuery("delete ContainerFilePart cfp where cfp.meta = :meta");
query.setEntity("meta", removedMeta);
query.executeUpdate();
}
}
}
/**
* @throws WGIllegalArgumentException
* @throws WGSystemException
* @see de.innovationgate.webgate.api.WGDocumentCore#setItemValue(String,
* Object)
*/
public boolean setItemValue(String strName, Object value) throws WGIllegalArgumentException, WGSystemException {
strName = strName.toLowerCase().trim();
if (value instanceof List) {
List valueList = (List) value;
if (valueList.size() == 0) {
value = null;
}
else if (valueList.size() == 1) {
value = valueList.get(0);
}
}
// Convert numbers to doubles
if (value instanceof Number && !(value instanceof Double)) {
value = new Double(((Number) value).doubleValue());
}
Map items;
Item item;
if (_content != null) {
items = _content.getItems();
item = (Item) items.get(strName);
if (item == null) {
ContentItem contentItem = new ContentItem();
contentItem.setName(strName);
contentItem.setParentcontent(_content);
ContentItem oldItem = (ContentItem) items.put(contentItem.getName(), contentItem);
item = contentItem;
}
}
else if (_profile != null) {
items = _profile.getItems();
item = (Item) items.get(strName);
if (item == null) {
UserProfileItem upItem = new UserProfileItem();
upItem.setName(strName);
upItem.setParentprofile(_profile);
UserProfileItem oldItem = (UserProfileItem) items.put(upItem.getName(), upItem);
item = upItem;
}
}
else {
return false;
}
writeItemValue(_parent, item, value);
return true;
}
protected static void writeItemValue(WGDatabaseImpl db, Item item, Object value) throws WGIllegalArgumentException {
if (value == null) {
item.setText(null);
item.setType(ITEMTYPE_STRING);
}
else if (value instanceof String) {
item.setText((String) value);
item.setType(ITEMTYPE_STRING);
}
else if (value instanceof Double) {
item.setNumber((Double) value);
item.setType(ITEMTYPE_NUMBER);
}
else if (value instanceof Date) {
item.setDate((Date) value);
item.setType(ITEMTYPE_DATE);
}
else if (value instanceof Boolean && db._ddlVersion >= WGDatabase.CSVERSION_WGA5) {
Boolean bool = (Boolean) value;
item.setNumber(new Double(bool.booleanValue() == true ? 1 : 0));
item.setType(ITEMTYPE_BOOLEAN);
}
else {
// serialize with xstream
try {
XStream xstream = new XStream(new Dom4JDriver());
String serializedValue = xstream.toXML(value);
item.setText(serializedValue);
item.setType(ITEMTYPE_SERIALIZED_XSTREAM);
} catch (Exception e) {
throw new WGIllegalArgumentException("Unable to serialize item value." , e);
}
}
}
/**
* @throws WGIllegalArgumentException
* @throws WGSystemException
* @throws WGBackendException
* @see de.innovationgate.webgate.api.WGDocumentCore#setMetaData(String,
* Object)
*/
public boolean setMetaData(String name, Object value) throws WGIllegalArgumentException, WGSystemException, WGBackendException {
// If value is an document implementation, extract it's entity
if (value instanceof WGDocumentImpl) {
value = ((WGDocumentImpl) value).getEntity();
}
else {
String designDocName = String.valueOf(value).toLowerCase();
// If value SHOULD be an entity (depending on meta name) but is only
// a key, the entity it is retrieved by the key
if (name.equals(WGStructEntry.META_AREA)) {
value = ((WGDocumentImpl) _parent.getDesignObject(WGDocument.TYPE_AREA, (String) designDocName, null)).getEntity();
}
else if (name.equals(WGStructEntry.META_CONTENTTYPE)) {
value = ((WGDocumentImpl) _parent.getDesignObject(WGDocument.TYPE_CONTENTTYPE, (String) designDocName, null)).getEntity();
}
else if (name.equals(WGContent.META_STRUCTENTRY)) {
value = ((WGDocumentImpl) _parent.getStructEntryByKey(value)).getEntity();
}
else if (name.equals(WGContent.META_LANGUAGE)) {
value = ((WGDocumentImpl) _parent.getDesignObject(WGDocument.TYPE_LANGUAGE, (String) designDocName, null)).getEntity();
}
// Some more custom conversions
if (value != null && (name.equals(WGStructEntry.META_POSITION)) && !(value instanceof Integer)) {
if (value instanceof Number) {
value = new Integer(((Number) value).intValue());
}
else {
try {
value = new Integer(String.valueOf(value));
}
catch (NumberFormatException e) {
throw new WGIllegalArgumentException("Cannot parse metadata type'" + name + "' as number. Value:" + value, e);
}
}
}
// The Structs workflow name is stored to the column ORIGINALKEY
if (_entity instanceof StructEntry && name.equals(WGStructEntry.META_WORKFLOW_NAME)) {
name = ENTITYPROP_STRUCTENTRY_WORKFLOW;
}
}
getBeanMap().put(name.toLowerCase(), value);
return true;
}
/**
* @see de.innovationgate.webgate.api.WGDocumentCore#setWGDocument(WGDocument)
*/
public void setWGDocument(WGDocument doc) {
_document = doc;
}
private void setCreated( Date date) {
getBeanMap().put(WGDocument.META_CREATED.toLowerCase(), date);
}
private void setLastModified(Date date) {
getBeanMap().put("lastmodified", date);
}
public Object getEntity() {
return _entity;
}
/*
* (Kein Javadoc)
*
* @see de.innovationgate.webgate.api.WGDocumentCore#isSaved()
*/
public boolean isSaved() throws WGSystemException {
return (!(getCreated() == null));
}
/*
* (Kein Javadoc)
*
* @see de.innovationgate.webgate.api.WGDocumentCore#getNativeObject()
*/
public Object getNativeObject() {
return _entity;
}
public String getOriginDatabase() {
return _parent.getDb().getDbReference();
}
protected WGDatabaseImpl getParent() {
return _parent;
}
public void renameFile(String oldFileName, String newFileName) throws WGAPIException {
if ((_entity instanceof Content || _entity instanceof FileContainer) == false) {
throw new WGIllegalStateException("Method renameFile() is not supported on '" + _entity.getClass().getName() + "'.");
}
if (!_parent.useOptimizedFileHandling()) {
throw new WGNotSupportedException("renameFile() is not supported on this document implementation.");
} else {
String convertedOldFileName = _parent.convertFileNameForAttaching(oldFileName);
String convertedNewFileName = _parent.convertFileNameForAttaching(newFileName);
if (_content != null) {
if (_content.getFiles().containsKey(convertedNewFileName)) {
throw new WGIllegalArgumentException("A file with the same name '" + convertedNewFileName + "' is already attached on this document, please remove it first.");
}
Hibernate.initialize(_content.getFiles());
ContentFileMeta meta = (ContentFileMeta) _content.getFiles().remove(convertedOldFileName);
if (meta != null) {
meta.setName(convertedNewFileName);
_content.getFiles().put(meta.getName(), meta);
meta.setLastmodified(new Date());
}
}
else {
FileContainer cont = (FileContainer) _entity;
if (cont.getFiles().containsKey(convertedNewFileName)) {
throw new WGIllegalArgumentException("A file with the same name '" + convertedNewFileName + "' is already present in this file container, please remove it first.");
}
Hibernate.initialize(cont.getFiles());
ContainerFileMeta meta = (ContainerFileMeta) cont.getFiles().remove(convertedOldFileName);
if (meta != null) {
meta.setName(convertedNewFileName);
cont.getFiles().put(meta.getName(), meta);
meta.setLastmodified(new Date());
}
}
}
}
public WGFileMetaData getFileMetaData(String filename) throws WGAPIException {
if ((_entity instanceof Content || _entity instanceof FileContainer) == false) {
throw new WGIllegalStateException("Method getFileMetaData() is not supported on '" + _entity.getClass().getName() + "'.");
}
if (_parent.useOptimizedFileHandling()) {
Entity metaEntity = retrieveFileMetaEntity(filename);
if (metaEntity != null) {
WGFileMetaData metaData = null;
if (metaEntity instanceof ContentFileMeta) {
ContentFileMeta meta = (ContentFileMeta) metaEntity;
metaData = new WGFileMetaData();
meta.fill(metaData);
}
else if (metaEntity instanceof ContainerFileMeta) {
ContainerFileMeta meta = (ContainerFileMeta) metaEntity;
metaData = new WGFileMetaData();
meta.fill(metaData);
}
if (metaData != null) {
if (_parent._ddlVersion >= WGDatabase.CSVERSION_WGA5) {
metaData.setExtensionDataHandler(new FileExtDataHandler(_parent, metaEntity));
}
return metaData;
}
else {
throw new WGIllegalArgumentException("Unsupported entity type '" + metaEntity.getClass().getName() + "'.");
}
}
else {
// file not found
return null;
}
} else {
throw new WGIllegalStateException("Method getFileMetaData() is not supported in the default file handling mode. You have to enable 'optimizedFileHandling'");
}
}
private Entity retrieveFileMetaEntity(String filename) {
if ((_entity instanceof Content || _entity instanceof FileContainer) == false) {
return null;
}
String convertedFilename = _parent.convertFileNameForAttaching(filename);
if (_content != null) {
return (Entity) _content.getFiles().get(convertedFilename);
} else {
return (Entity) ((FileContainer)_entity).getFiles().get(convertedFilename);
}
}
public WGDocumentCore getRelation(String name) throws WGAPIException {
name = name.toLowerCase();
if (_content != null) {
Map relations = _content.getRelations();
if (relations != null) {
ContentRelation relation = (ContentRelation) relations.get(name);
if (relation == null) {
return null;
}
return retrieveRelationTarget(relation);
}
else {
return null;
}
}
throw new WGNotSupportedException("Content Relations are not supported on this document type");
}
public WGRelationData getRelationData(String name) throws WGNotSupportedException {
name = name.toLowerCase();
if (_content != null) {
Map relations = _content.getRelations();
if (relations != null) {
ContentRelation relation = (ContentRelation) relations.get(name);
if (relation == null) {
return null;
}
return _parent.createWGRelationData(relation);
}
else {
return null;
}
}
throw new WGNotSupportedException("Content Relations are not supported on this document type");
}
public WGDocumentCore removeRelation(String name) throws WGAPIException {
name = name.toLowerCase();
if (_content != null) {
Hibernate.initialize(_content.getRelations());
Map relations = _content.getRelations();
if (relations != null) {
ContentRelation relation = (ContentRelation) relations.remove(name);
if (relation == null) {
return null;
}
return retrieveRelationTarget(relation);
}
}
throw new WGNotSupportedException("Content Relations are not supported on this document type");
}
private WGDocumentCore retrieveRelationTarget(ContentRelation relation) throws WGAPIException {
// Try to retrieve the relation in the most direct way by using the target column
try {
Content targetContent = relation.getTarget();
if (targetContent != null && targetContent.getStatus().equals(WGContent.STATUS_RELEASE)) {
if (targetContent == _entity) {
return this;
}
else {
_parent.getSession().refresh(targetContent);
return _parent.createDocumentImpl(targetContent);
}
}
}
// Relation points to a deleted document
catch (ObjectNotFoundException e) {
}
// If the relation is "broken" or empty we try to resolve it by using struct and language information
WGStructEntry entry = _parent.getDb().getStructEntryByKey(relation.getTargetstructentry());
if (entry == null) {
return null;
}
WGContent content = entry.getReleasedContent(relation.getTargetlanguage());
if (content != null) {
return content.getCore();
}
else {
return null;
}
}
public WGDocumentCore setRelation(WGRelationData relData) throws WGAPIException {
if (_content != null) {
Map relations = _content.getRelations();
if (relations != null) {
String structKey = String.valueOf(relData.getTargetStructkey());
Content targetContent = null;
// Try to retrieve the target content entity and look if it is already available
Query query = _parent.getSession().createQuery("select content from Content as content where content.structentry.key=:structkey and content.language.name=:lang and content.status='p'");
query.setParameter("structkey", structKey);
query.setParameter("lang", relData.getTargetLanguage());
if (query.list().size() > 0) {
targetContent = (Content) query.list().get(0);
}
String relName = relData.getName().toLowerCase();
ContentRelation relation = (ContentRelation) relations.get(relName);
if (relation == null) {
relation = new ContentRelation();
relation.setName(relName);
}
relation.setType(relData.getType());
relation.setParentcontent(_content);
if (targetContent != null) {
relation.setTarget(targetContent);
}
relation.setTargetstructentry(structKey);
relation.setTargetlanguage(relData.getTargetLanguage());
if (relData.getGroup() != null) {
relation.setGroup(relData.getGroup().toLowerCase());
}
ContentRelation previousRelation = (ContentRelation) relations.put(relation.getName(), relation);
if (previousRelation != null) {
return retrieveRelationTarget(previousRelation);
}
else {
return null;
}
}
}
throw new WGNotSupportedException("Content Relations are not supported on this document type");
}
public List<String> getRelationNames() throws WGAPIException {
if (_content != null) {
Map relations = _content.getRelations();
if (relations != null) {
return new ArrayList(relations.keySet());
}
else {
return Collections.emptyList();
}
}
throw new WGNotSupportedException("Content Relations are not supported on this document type");
}
public boolean hasFileMetadata() throws WGAPIException {
return _parent.useOptimizedFileHandling();
}
public boolean hasFile(String file) throws WGAPIException {
if (_parent.useOptimizedFileHandling()) {
String convertedFileName = _parent.convertFileNameForAttaching(file);
if (_content != null) {
return _content.getFiles().containsKey(convertedFileName);
}
else if (_entity instanceof FileContainer) {
return ((FileContainer)_entity).getFiles().containsKey(convertedFileName);
}
else {
throw new WGBackendException("Unknown entity type " + _entity.getClass().getName());
}
}
else {
return fetchFileEntity(file).hasNext();
}
}
public Object getExtensionData(String strName) throws WGAPIException {
strName = strName.toLowerCase().trim();
ExtensionData att = _entity.getExtensionData().get(strName);
if (att != null) {
return readItemValue(att);
}
else {
return null;
}
}
public List getExtensionDataNames() throws WGAPIException {
return new ArrayList(_entity.getExtensionData().keySet());
}
public void removeExtensionData(String name) throws WGAPIException {
name = name.toLowerCase().trim();
ExtensionData item = (ExtensionData) _entity.getExtensionData().get(name);
if (item != null) {
Hibernate.initialize(_entity.getExtensionData());
Item oldItem = (Item) _entity.getExtensionData().remove(name);
}
}
public void writeExtensionData(String strName, Object value) throws WGAPIException {
strName = strName.toLowerCase().trim();
// Convert numbers to doubles
if (value instanceof Number && !(value instanceof Double)) {
value = new Double(((Number) value).doubleValue());
}
Map atts = _entity.getExtensionData();
ExtensionData att = (ExtensionData) atts.get(strName);
if (att == null) {
ExtensionData newAtt = new ExtensionData();
newAtt.setEntity((Entity) _entity);
newAtt.setName(strName);
ExtensionData oldItem = (ExtensionData) atts.put(newAtt.getName(), newAtt);
att = newAtt;
}
writeItemValue(_parent, att, value);
}
private WGPortletRegistry createPortletRegistry() {
if (_parent._ddlVersion >= WGDatabase.CSVERSION_WGA5) {
return new PortletRegistryImplV5(_parent, this);
}
else {
return new PortletRegistryImplV4(_parent, this);
}
}
public List<String> getRelationNamesOfGroup(String group) throws WGBackendException {
group = group.toLowerCase();
if (_content != null) {
List<String> names = new ArrayList<String>();
Map<String,ContentRelation> relations = _content.getRelations();
if (relations != null) {
for (ContentRelation rel : relations.values()) {
if (group.equals(rel.getGroup())) {
names.add(rel.getName());
}
}
return names;
}
else {
return Collections.emptyList();
}
}
throw new WGNotSupportedException("Content Relations are not supported on this document type");
}
}