/** * The contents of this file are subject to the OpenMRS Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Copyright (C) OpenMRS, LLC. All Rights Reserved. */ package org.openmrs.module.sync.api.db.hibernate.usertype; import java.io.BufferedReader; import java.io.IOException; import java.io.Serializable; import java.sql.Clob; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Collection; import java.util.LinkedList; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.HibernateException; import org.hibernate.usertype.UserType; import org.openmrs.module.sync.SyncItem; import org.openmrs.module.sync.SyncUtil; import org.openmrs.module.sync.serialization.Item; import org.openmrs.module.sync.serialization.Package; import org.openmrs.module.sync.serialization.Record; import org.xml.sax.SAXParseException; public class SyncItemListSerializingUserType implements UserType { private static final int[] SQL_TYPES = {Types.CLOB}; /** Logger for this class and subclasses */ protected final Log log = LogFactory.getLog(getClass()); /** * @see org.hibernate.usertype.UserType#assemble(java.io.Serializable, java.lang.Object) */ public Object assemble(Serializable cached, Object owner) throws HibernateException { return cached; } /** * @see org.hibernate.usertype.UserType#deepCopy(java.lang.Object) */ public Object deepCopy(Object value) throws HibernateException { return value; } /** * @see org.hibernate.usertype.UserType#disassemble(java.lang.Object) */ public Serializable disassemble(Object value) throws HibernateException { return (Serializable) value; } /** * @see org.hibernate.usertype.UserType#equals(java.lang.Object, java.lang.Object) */ public boolean equals(Object x, Object y) throws HibernateException { //TODO: might need something more detailed here; p206 return x == y; } /** * @see org.hibernate.usertype.UserType#hashCode(java.lang.Object) */ public int hashCode(Object x) throws HibernateException { return x.hashCode(); } /** * @see org.hibernate.usertype.UserType#isMutable() */ public boolean isMutable() { return false; } /** * @see org.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object) */ public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException { if (rs.wasNull()) { return null; } else { Clob clob = rs.getClob(names[0]); if (clob == null) { return null; } else { // 2 Sep 2007 - Christian Allen - callen@pih.org // We need a workaround because clob.getSubString() and clob.length() throw an exception when used within the creating session //String content = clob.getSubString(1, (int)clob.length()); // Here's the workaround: StringBuilder content = new StringBuilder(); String line; BufferedReader br = new BufferedReader( rs.getCharacterStream( names[0] ) ); try { while( (line = br.readLine()) != null ) { content.append(line); } } catch (IOException e) { throw new SQLException( e.toString() ); } // End workaround Collection<SyncItem> items = SyncUtil.getSyncItemsFromPayload(content.toString()); return items; } } } /** * @see org.hibernate.usertype.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int) */ @SuppressWarnings("unchecked") public void nullSafeSet(PreparedStatement ps, Object value, int index) throws HibernateException, SQLException { if (value == null) { ps.setNull(index, Types.CLOB); } else if (value instanceof String) { // if the user is doing a search of the payload items ps.setString(index, (String)value); } else { Collection<SyncItem> items = (Collection<SyncItem>) value; Package pkg = new Package(); Record record; try { record = pkg.createRecordForWrite("items"); Item root = record.getRootItem(); for(SyncItem item : items) { item.save(record, root); } } catch (Exception e) { log.error("Could not serialize SyncItems:", e); throw new HibernateException("Could not serialize SyncItems", e); } String newRecord = record.toStringAsDocumentFragement(); //02/09/2008: replaced setClob() with setString() to deal with encoding issues: mysql Clob inexplicably truncates if // it encounters non-ASCII character //ps.setClob(index, Hibernate.createClob(record.toStringAsDocumentFragement())); ps.setString(index, newRecord); } } /** * @see org.hibernate.usertype.UserType#replace(java.lang.Object, java.lang.Object, java.lang.Object) */ public Object replace(Object original, Object target, Object owner) throws HibernateException { return original; } /** * @see org.hibernate.usertype.UserType#returnedClass() */ @SuppressWarnings("unchecked") public Class returnedClass() { return Collection.class; } /** * @see org.hibernate.usertype.UserType#sqlTypes() */ public int[] sqlTypes() { return SQL_TYPES; } }