import java.io.IOException;
+import com.healthmarketscience.jackcess.PropertyMap;
import com.healthmarketscience.jackcess.complex.ComplexColumnInfo;
+import com.healthmarketscience.jackcess.complex.ComplexDataType;
import com.healthmarketscience.jackcess.complex.ComplexValue;
import com.healthmarketscience.jackcess.impl.complex.ComplexColumnInfoImpl;
+import com.healthmarketscience.jackcess.impl.complex.MultiValueColumnInfoImpl;
+import com.healthmarketscience.jackcess.impl.complex.MultiValueColumnPropertyMap;
/**
* ColumnImpl subclass which is used for complex data types.
{
/** additional information specific to complex columns */
private final ComplexColumnInfo<? extends ComplexValue> _complexInfo;
+ /** properties for multi-value column */
+ private PropertyMap _mvProps;
ComplexColumnImpl(InitArgs args) throws IOException
{
super.postTableLoadInit();
}
+ @Override
+ public PropertyMap getProperties() throws IOException {
+ if(_complexInfo.getType() == ComplexDataType.MULTI_VALUE) {
+ if(_mvProps == null) {
+ PropertyMap primaryProps = super.getProperties();
+ PropertyMap complexProps = ((MultiValueColumnInfoImpl)_complexInfo)
+ .getValueColumn().getProperties();
+ _mvProps = new MultiValueColumnPropertyMap(primaryProps, complexProps);
+ }
+ return _mvProps;
+ }
+ return super.getProperties();
+ }
+
@Override
public ComplexColumnInfo<? extends ComplexValue> getComplexInfo() {
return _complexInfo;
}
for(Property prop : props) {
- byte flag = 0;
- if(prop instanceof PropertyImpl) {
- flag = ((PropertyImpl)prop).getFlag();
- }
- put(prop.getName(), prop.getType(), flag, prop.getValue());
+ put(prop);
}
}
+ public PropertyImpl put(Property prop) {
+ byte flag = 0;
+ if(prop instanceof PropertyImpl) {
+ flag = ((PropertyImpl)prop).getFlag();
+ }
+ return put(prop.getName(), prop.getType(), flag, prop.getValue());
+ }
+
/**
* Puts a property into this map with the given information.
*/
@Override
public String toString() {
+ return toString(this);
+ }
+
+ public static String toString(PropertyMap map) {
StringBuilder sb = new StringBuilder();
- sb.append(PropertyMaps.DEFAULT_NAME.equals(getName()) ?
- "<DEFAULT>" : getName())
+ sb.append(PropertyMaps.DEFAULT_NAME.equals(map.getName()) ?
+ "<DEFAULT>" : map.getName())
.append(" {");
- for(Iterator<Property> iter = iterator(); iter.hasNext(); ) {
+ for(Iterator<Property> iter = map.iterator(); iter.hasNext(); ) {
sb.append(iter.next());
if(iter.hasNext()) {
sb.append(",");
}
sb.append("}");
return sb.toString();
- }
+ }
public static Property createProperty(String name, DataType type, Object value) {
return createProperty(name, type, (byte)0, value);
--- /dev/null
+/*
+Copyright (c) 2016 James Ahlborn
+
+Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.healthmarketscience.jackcess.impl.complex;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import com.healthmarketscience.jackcess.DataType;
+import com.healthmarketscience.jackcess.PropertyMap;
+import com.healthmarketscience.jackcess.impl.PropertyMapImpl;
+
+/**
+ * PropertyMap implementation for multi-value, complex properties. The
+ * properties for these columns seem to be dispersed between both the primary
+ * column and the complex value column. The primary column only seems to have
+ * the simple "multi-value" property and the rest seem to be on the complex
+ * value column. This PropertyMap implementation combines them into one
+ * synthetic map.
+ *
+ * @author James Ahlborn
+ */
+public class MultiValueColumnPropertyMap implements PropertyMap
+{
+ /** properties from the primary column */
+ private final PropertyMap _primary;
+ /** properties from the complex column */
+ private final PropertyMap _complex;
+
+ public MultiValueColumnPropertyMap(PropertyMap primary, PropertyMap complex)
+ {
+ _primary = primary;
+ _complex = complex;
+ }
+
+ public String getName() {
+ return _primary.getName();
+ }
+
+ public int getSize() {
+ return _primary.getSize() + _complex.getSize();
+ }
+
+ public boolean isEmpty() {
+ return _primary.isEmpty() && _complex.isEmpty();
+ }
+
+ public Property get(String name) {
+ Property prop = _primary.get(name);
+ if(prop != null) {
+ return prop;
+ }
+ return _complex.get(name);
+ }
+
+ public Object getValue(String name) {
+ return getValue(name, null);
+ }
+
+ public Object getValue(String name, Object defaultValue) {
+ Property prop = get(name);
+ return ((prop != null) ? prop.getValue() : defaultValue);
+ }
+
+ public Property put(String name, Object value) {
+ return put(name, null, value);
+ }
+
+ public Property put(String name, DataType type, Object value) {
+ // the only property which seems to go in the "primary" is the "multi
+ // value" property
+ if(ALLOW_MULTI_VALUE_PROP.equals(name)) {
+ return _primary.put(name, DataType.BOOLEAN, value);
+ }
+ return _complex.put(name, value);
+ }
+
+ public void putAll(Iterable<? extends Property> props) {
+ if(props == null) {
+ return;
+ }
+
+ for(Property prop : props) {
+ if(ALLOW_MULTI_VALUE_PROP.equals(prop.getName())) {
+ ((PropertyMapImpl)_primary).put(prop);
+ } else {
+ ((PropertyMapImpl)_complex).put(prop);
+ }
+ }
+ }
+
+ public Property remove(String name) {
+ if(ALLOW_MULTI_VALUE_PROP.equals(name)) {
+ return _primary.remove(name);
+ }
+ return _complex.remove(name);
+ }
+
+ public void save() throws IOException {
+ _primary.save();
+ _complex.save();
+ }
+
+ public Iterator<Property> iterator() {
+ final List<Iterator<Property>> iters = new ArrayList<Iterator<Property>>(2);
+ iters.add(_primary.iterator());
+ iters.add(_complex.iterator());
+
+ return new Iterator<Property>() {
+ private Iterator<Property> _cur;
+ private Property _next = findNext();
+
+ private Property findNext() {
+ while(!iters.isEmpty()) {
+ _cur = iters.get(0);
+ if(_cur.hasNext()) {
+ return _cur.next();
+ }
+ iters.remove(0);
+ _cur = null;
+ }
+ return null;
+ }
+
+ public boolean hasNext() {
+ return (_next != null);
+ }
+
+ public Property next() {
+ if(!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ Property prop = _next;
+ _next = findNext();
+ return prop;
+ }
+
+ public void remove() {
+ if(_cur != null) {
+ _cur.remove();
+ _cur = null;
+ }
+ }
+ };
+ }
+
+ @Override
+ public String toString() {
+ return PropertyMapImpl.toString(this);
+ }
+}