Package de.innovationgate.webgate.api.jdbc

Source Code of de.innovationgate.webgate.api.jdbc.WGDocumentImpl

/*******************************************************************************
* 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");   
    }


}
TOP

Related Classes of de.innovationgate.webgate.api.jdbc.WGDocumentImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.