001/* 002 * Copyright (c) 2006-2014 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Bogdan Stefanescu 011 * Florent Guillaume 012 */ 013package org.nuxeo.ecm.core.api.model.impl.primitives; 014 015import java.io.ByteArrayInputStream; 016import java.io.Serializable; 017import java.util.Map; 018 019import org.apache.commons.lang.ObjectUtils; 020import org.nuxeo.ecm.core.api.Blob; 021import org.nuxeo.ecm.core.api.NuxeoException; 022import org.nuxeo.ecm.core.api.PropertyException; 023import org.nuxeo.ecm.core.api.model.Property; 024import org.nuxeo.ecm.core.api.model.PropertyConversionException; 025import org.nuxeo.ecm.core.api.model.PropertyNotFoundException; 026import org.nuxeo.ecm.core.api.model.impl.MapProperty; 027import org.nuxeo.ecm.core.api.model.impl.ScalarProperty; 028import org.nuxeo.ecm.core.schema.types.Field; 029 030/** 031 * Blob property, reading and writing from a {@link Blob} object. 032 */ 033public class BlobProperty extends MapProperty { 034 035 private static final long serialVersionUID = 1L; 036 037 private static final String NAME = "name"; 038 039 private static final String MIME_TYPE = "mime-type"; 040 041 private static final String ENCODING = "encoding"; 042 043 private static final String DIGEST = "digest"; 044 045 private static final String LENGTH = "length"; 046 047 protected Serializable value; 048 049 public BlobProperty(Property parent, Field field, int flags) { 050 super(parent, field, flags); 051 } 052 053 @Override 054 public Serializable getDefaultValue() { 055 return null; 056 } 057 058 @Override 059 public Serializable internalGetValue() throws PropertyException { 060 return value; 061 } 062 063 @Override 064 public void internalSetValue(Serializable value) throws PropertyException { 065 this.value = value; 066 } 067 068 @Override 069 public final Object clone() throws CloneNotSupportedException { 070 return (BlobProperty) super.clone(); 071 } 072 073 @Override 074 public boolean isNormalized(Object value) { 075 return value == null || ((value instanceof Blob) && (value instanceof Serializable)); 076 } 077 078 @Override 079 public Serializable normalize(Object value) throws PropertyConversionException { 080 if (isNormalized(value)) { 081 // TODO specific blob support? 082 return (Serializable) value; 083 } 084 throw new PropertyConversionException(value.getClass(), Blob.class); 085 } 086 087 @SuppressWarnings("unchecked") 088 @Override 089 public <T> T convertTo(Serializable value, Class<T> toType) throws PropertyConversionException { 090 if (value == null) { 091 return null; 092 } 093 if (Blob.class.isAssignableFrom(toType)) { 094 return (T) value; 095 } 096 throw new PropertyConversionException(value.getClass(), toType); 097 } 098 099 @Override 100 public Object newInstance() { 101 return new ByteArrayInputStream("".getBytes()); // TODO not serializable 102 } 103 104 @Override 105 public boolean isContainer() { 106 return false; 107 } 108 109 @SuppressWarnings("unchecked") 110 @Override 111 public void setValue(Object value) throws PropertyException { 112 if (value instanceof Map) { 113 setMap(getValue(), (Map<String, Object>) value); 114 setIsModified(); 115 } else { 116 super.setValue(value); 117 } 118 } 119 120 @Override 121 protected boolean isSameValue(Serializable value1, Serializable value2) { 122 // for now, blob property are considered always as dirty when update - see NXP-16322 123 return false; 124 } 125 126 @Override 127 public void init(Serializable value) throws PropertyException { 128 if (value == null) { 129 // IGNORE null values - properties will be 130 // considered PHANTOMS 131 return; 132 } 133 if (value instanceof Blob) { 134 internalSetValue(value); 135 } 136 removePhantomFlag(); 137 } 138 139 @Override 140 public Serializable getValueForWrite() throws PropertyException { 141 return getValue(); 142 } 143 144 @Override 145 protected Property internalGetChild(Field field) { 146 return new ScalarMemberProperty(this, field, isPhantom() ? IS_PHANTOM : 0); 147 } 148 149 protected void setMap(Object object, Map<String, Object> value) throws PropertyException { 150 if (object == null) { 151 throw new NuxeoException("Trying to access a member of a null object"); 152 } 153 if (!(object instanceof Blob)) { 154 throw new NuxeoException("Not a Blob: " + object); 155 } 156 Blob blob = (Blob) object; 157 for (Entry<String, Object> entry : value.entrySet()) { 158 String name = entry.getKey(); 159 Object v = entry.getValue(); 160 setMemberValue(blob, name, v); 161 } 162 } 163 164 protected void setMemberValue(Blob blob, String name, Object value) throws PropertyNotFoundException { 165 if (NAME.equals(name)) { 166 blob.setFilename((String) value); 167 } else if (MIME_TYPE.equals(name)) { 168 blob.setMimeType((String) value); 169 } else if (ENCODING.equals(name)) { 170 blob.setEncoding((String) value); 171 } else if (DIGEST.equals(name)) { 172 blob.setDigest((String) value); 173 } else { 174 throw new PropertyNotFoundException(name); 175 } 176 } 177 178 protected Object getMemberValue(Object object, String name) throws PropertyException { 179 if (object == null) { 180 throw new NuxeoException("Trying to access a member of a null object: " + name); 181 } 182 if (!(object instanceof Blob)) { 183 throw new NuxeoException("Not a Blob: " + object); 184 } 185 Blob blob = (Blob) object; 186 if (NAME.equals(name)) { 187 return blob.getFilename(); 188 } else if (MIME_TYPE.equals(name)) { 189 return blob.getMimeType(); 190 } else if (ENCODING.equals(name)) { 191 return blob.getEncoding(); 192 } else if (DIGEST.equals(name)) { 193 return blob.getDigest(); 194 } else if (LENGTH.equals(name)) { 195 return Long.valueOf(blob.getLength()); 196 } else { 197 throw new PropertyNotFoundException(name); 198 } 199 } 200 201 protected void setMemberValue(Object object, String name, Object value) throws PropertyException { 202 if (object == null) { 203 throw new NuxeoException("Trying to access a member of a null object: " + name); 204 } 205 if (!(object instanceof Blob)) { 206 throw new NuxeoException("Not a Blob: " + object); 207 } 208 Blob blob = (Blob) object; 209 setMemberValue(blob, name, value); 210 } 211 212 public static class ScalarMemberProperty extends ScalarProperty { 213 214 private static final long serialVersionUID = 1L; 215 216 public ScalarMemberProperty(Property parent, Field field, int flags) { 217 super(parent, field, flags); 218 } 219 220 @Override 221 public void internalSetValue(Serializable value) throws PropertyException { 222 ((BlobProperty) parent).setMemberValue(parent.getValue(), getName(), value); 223 } 224 225 @Override 226 public Serializable internalGetValue() throws PropertyException { 227 Object value = ((BlobProperty) parent).getMemberValue(parent.getValue(), getName()); 228 if (value != null && !(value instanceof Serializable)) { 229 throw new PropertyException("Non serializable value: " + value); 230 } 231 return (Serializable) value; 232 } 233 } 234 235 @Override 236 public boolean isSameAs(Property property) throws PropertyException { 237 if (!(property instanceof BlobProperty)) { 238 return false; 239 } 240 BlobProperty other = (BlobProperty) property; 241 return ObjectUtils.equals(getValue(), other.getValue()); 242 } 243 244}