package org.archstudio.archipelago2; import java.util.List; import java.util.concurrent.TimeUnit; import org.archstudio.bna.constants.DNDData; import org.archstudio.bna.ui.IUITransferProvider; import org.archstudio.xarchadt.ObjRef; import org.eclipse.swt.dnd.ByteArrayTransfer; import org.eclipse.swt.dnd.TransferData; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.Lists; public class ObjRefTransfer extends ByteArrayTransfer implements IUITransferProvider { private static Cache<ObjRef, Object> transferredObjRefs = CacheBuilder.newBuilder().expireAfterWrite(12, TimeUnit.HOURS).build(); private static final String OBJREF_TYPE_NAME = ObjRefTransfer.class.getName(); private static final int OBJREF_TYPE_ID = registerType(OBJREF_TYPE_NAME); private static final String TRANSFER_PREFIX = OBJREF_TYPE_NAME + ":"; private static ObjRefTransfer _instance = new ObjRefTransfer(); private ObjRefTransfer() { } public static ObjRefTransfer getInstance() { return _instance; } @Override public void addData(TransferData transferData, DNDData dndData) { List<ObjRef> objRefs = nativeToJava(transferData); if (objRefs != null) { dndData.addData(objRefs); if (objRefs.size() > 0) { dndData.addData(objRefs.get(0)); } } } @Override public void javaToNative(Object object, TransferData transferData) { if (object != null && isSupportedType(transferData)) { if (object instanceof Iterable<?>) { Iterable<?> refs = (Iterable<?>) object; StringBuilder sb = new StringBuilder(); sb.append(TRANSFER_PREFIX); boolean first = false; for (Object ref : refs) { if (!first) { sb.append(","); } if (!(ref instanceof ObjRef)) { throw new IllegalArgumentException( "Object " + ref + " in " + object + " is not an ObjRef"); } // hold the ObjRef so it is not garbage collected transferredObjRefs.put((ObjRef) ref, null); sb.append(((ObjRef) ref).getUID()); first = false; } super.javaToNative(sb.toString().getBytes(), transferData); } else if (object instanceof ObjRef) { ObjRef ref = (ObjRef) object; StringBuilder sb = new StringBuilder(); sb.append(TRANSFER_PREFIX); sb.append(ref.getUID()); super.javaToNative(sb.toString().getBytes(), transferData); } } } @Override public List<ObjRef> nativeToJava(TransferData transferData) { if (isSupportedType(transferData)) { byte[] buffer = (byte[]) super.nativeToJava(transferData); if (buffer != null) { String s = new String(buffer); if (s.startsWith(TRANSFER_PREFIX)) { String[] uids = s.substring(TRANSFER_PREFIX.length()).split(","); List<ObjRef> refs = Lists.newArrayList(); for (String uid : uids) { refs.add(ObjRef.lookupObjRef(Long.valueOf(uid))); } return refs; } } } return null; } @Override protected String[] getTypeNames() { return new String[] {OBJREF_TYPE_NAME}; } @Override protected int[] getTypeIds() { return new int[] {OBJREF_TYPE_ID}; } }