/*
* Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Florent Guillaume
*/
package org.eclipse.ecr.core.storage.sql.coremodel;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.ecr.core.api.Blob;
import org.eclipse.ecr.core.api.DocumentException;
import org.eclipse.ecr.core.model.Property;
import org.eclipse.ecr.core.model.PropertyContainer;
import org.eclipse.ecr.core.schema.types.ComplexType;
import org.eclipse.ecr.core.schema.types.Field;
import org.eclipse.ecr.core.storage.sql.Node;
/**
* A {@link SQLComplexProperty} gives access to a wrapped SQL-level {@link Node}
* . This is used for documents and for complex properties.
*
* @author Florent Guillaume
*/
public class SQLComplexProperty extends SQLBaseProperty implements
PropertyContainer {
private static final Log log = LogFactory.getLog(SQLComplexProperty.class);
private final Node node;
protected final SQLSession session;
/**
* Creates a {@link SQLComplexProperty} to wrap a {@link Node}.
*/
public SQLComplexProperty(Node node, ComplexType type, SQLSession session,
boolean readonly) {
super(type, node == null ? null : node.getName(), readonly);
this.node = node;
this.session = session;
}
// for SQLDocument
public Node getNode() {
return node;
}
/*
* ----- org.eclipse.ecr.core.model.Property -----
*/
@Override
public String getName() {
return node.getName();
}
@Override
public Object getValue() throws DocumentException {
Map<String, Object> map = new HashMap<String, Object>();
Collection<Property> properties = getProperties();
for (Property property : properties) {
map.put(property.getName(), property.getValue());
}
return map;
}
@Override
@SuppressWarnings("unchecked")
public void setValue(Object value) throws DocumentException {
checkWritable();
if (value == null) {
// XXX should delete the node?
for (Property property : getProperties()) {
property.setValue(null);
}
} else {
if (!(value instanceof Map)) {
throw new DocumentException(
"Invalid value for complex property (map needed): "
+ value);
}
Map<String, Object> map = (Map<String, Object>) value;
for (Entry<String, Object> entry : map.entrySet()) {
Property property = getProperty(entry.getKey());
property.setValue(entry.getValue());
}
}
}
/*
* ----- Property & PropertyContainer -----
*/
@Override
public boolean isPropertySet(String name) throws DocumentException {
throw new UnsupportedOperationException();
}
@Override
public Property getProperty(String name) throws DocumentException {
return session.makeProperty(node, name, (ComplexType) type, null,
readonly);
}
@Override
public Collection<Property> getProperties() throws DocumentException {
Collection<Field> fields = ((ComplexType) type).getFields();
List<Property> properties = new ArrayList<Property>(fields.size());
for (Field field : fields) {
properties.add(getProperty(field.getName().getPrefixedName()));
}
return properties;
}
@Override
public Iterator<Property> getPropertyIterator() throws DocumentException {
return getProperties().iterator();
}
/*
* ----- org.eclipse.ecr.core.model.PropertyContainer -------------------
* (used for SQLDocument, SQLComplexProperty itself doesn't need it)
*/
@Override
public Map<String, Object> exportFlatMap(String[] schemas)
throws DocumentException {
throw new UnsupportedOperationException();
}
@Override
public Map<String, Map<String, Object>> exportMap(String[] schemas)
throws DocumentException {
throw new UnsupportedOperationException();
}
@Override
public Map<String, Object> exportMap(String schemaName)
throws DocumentException {
throw new UnsupportedOperationException();
}
@Override
public void importFlatMap(Map<String, Object> map) throws DocumentException {
checkWritable();
throw new UnsupportedOperationException();
}
@Override
public void importMap(Map<String, Map<String, Object>> map)
throws DocumentException {
checkWritable();
throw new UnsupportedOperationException();
}
@Override
public List<String> getDirtyFields() {
throw new UnsupportedOperationException();
}
@Override
public Object getPropertyValue(String name) throws DocumentException {
// when called from AbstractSession.getDataModelFields,
// we may get an unprefixed name...
return getProperty(name).getValue();
}
@Override
public String getString(String name) throws DocumentException {
return (String) getProperty(name).getValue();
}
@Override
public boolean getBoolean(String name) throws DocumentException {
Boolean value = (Boolean) getProperty(name).getValue();
return value == null ? false : value.booleanValue();
}
@Override
public long getLong(String name) throws DocumentException {
Long value = (Long) getProperty(name).getValue();
return value == null ? 0L : value.longValue();
}
@Override
public double getDouble(String name) throws DocumentException {
Double value = (Double) getProperty(name).getValue();
return value == null ? 0D : value.doubleValue();
}
@Override
public Calendar getDate(String name) throws DocumentException {
return (Calendar) getProperty(name).getValue();
}
@Override
public Blob getContent(String name) throws DocumentException {
throw new UnsupportedOperationException();
}
@Override
public void setPropertyValue(String name, Object value)
throws DocumentException {
// TODO check constraints
try {
getProperty(name).setValue(value);
// TODO mark dirty fields
} catch (DocumentException e) {
// we log a debugging message here as it is a point where the
// property name is known
log.debug("Error setting property: " + name + " value: " + value);
throw e;
}
}
@Override
public void setString(String name, String value) throws DocumentException {
setPropertyValue(name, value);
}
@Override
public void setBoolean(String name, boolean value) throws DocumentException {
setPropertyValue(name, Boolean.valueOf(value));
}
@Override
public void setLong(String name, long value) throws DocumentException {
setPropertyValue(name, Long.valueOf(value));
}
@Override
public void setDouble(String name, double value) throws DocumentException {
setPropertyValue(name, Double.valueOf(value));
}
@Override
public void setDate(String name, Calendar value) throws DocumentException {
setPropertyValue(name, value);
}
@Override
public void setContent(String name, Blob value) throws DocumentException {
throw new UnsupportedOperationException();
}
@Override
public void removeProperty(String name) throws DocumentException {
throw new UnsupportedOperationException();
}
}