/* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You 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 org.apache.poi.hsmf.datatypes; import java.math.BigInteger; import java.util.Calendar; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LocaleUtil; /** * An instance of a {@link MAPIProperty} inside a {@link PropertiesChunk}. Where * the {@link Types} type is a fixed length one, this will contain the actual * value. Where the {@link Types} type is a variable length one, this will * contain the length of the property, and the value will be in the associated * {@link Chunk}. */ public class PropertyValue { private MAPIProperty property; private long flags; protected byte[] data; public PropertyValue(MAPIProperty property, long flags, byte[] data) { this.property = property; this.flags = flags; this.data = data; } public MAPIProperty getProperty() { return property; } /** * Get the raw value flags. TODO Also provide getters for the flag meanings */ public long getFlags() { return flags; } public Object getValue() { return data; } public void setRawValue(byte[] value) { this.data = value; } @Override public String toString() { Object v = getValue(); if (v == null) { return "(No value available)"; } if (v instanceof byte[]) { return ByteChunk.toDebugFriendlyString((byte[]) v); } else { // Just use the normal toString on the value return v.toString(); } } public static class NullPropertyValue extends PropertyValue { public NullPropertyValue(MAPIProperty property, long flags, byte[] data) { super(property, flags, data); } @Override public Void getValue() { return null; } } public static class BooleanPropertyValue extends PropertyValue { public BooleanPropertyValue(MAPIProperty property, long flags, byte[] data) { super(property, flags, data); } @Override public Boolean getValue() { short val = LittleEndian.getShort(data); return val > 0; } public void setValue(boolean value) { if (data.length != 2) { data = new byte[2]; } if (value) { LittleEndian.putShort(data, 0, (short) 1); } } } public static class ShortPropertyValue extends PropertyValue { public ShortPropertyValue(MAPIProperty property, long flags, byte[] data) { super(property, flags, data); } @Override public Short getValue() { return LittleEndian.getShort(data); } public void setValue(short value) { if (data.length != 2) { data = new byte[2]; } LittleEndian.putShort(data, 0, value); } } public static class LongPropertyValue extends PropertyValue { public LongPropertyValue(MAPIProperty property, long flags, byte[] data) { super(property, flags, data); } @Override public Integer getValue() { return LittleEndian.getInt(data); } public void setValue(int value) { if (data.length != 4) { data = new byte[4]; } LittleEndian.putInt(data, 0, value); } } public static class LongLongPropertyValue extends PropertyValue { public LongLongPropertyValue(MAPIProperty property, long flags, byte[] data) { super(property, flags, data); } @Override public Long getValue() { return LittleEndian.getLong(data); } public void setValue(long value) { if (data.length != 8) { data = new byte[8]; } LittleEndian.putLong(data, 0, value); } } public static class FloatPropertyValue extends PropertyValue { public FloatPropertyValue(MAPIProperty property, long flags, byte[] data) { super(property, flags, data); } @Override public Float getValue() { return LittleEndian.getFloat(data); } public void setValue(float value) { if (data.length != 4) { data = new byte[4]; } LittleEndian.putFloat(data, 0, value); } } public static class DoublePropertyValue extends PropertyValue { public DoublePropertyValue(MAPIProperty property, long flags, byte[] data) { super(property, flags, data); } @Override public Double getValue() { return LittleEndian.getDouble(data); } public void setValue(double value) { if (data.length != 8) { data = new byte[8]; } LittleEndian.putDouble(data, 0, value); } } /** * signed 64-bit integer that represents a base ten decimal, with four * digits to the right of the decimal point */ public static class CurrencyPropertyValue extends PropertyValue { private static final BigInteger SHIFT = BigInteger.valueOf(10000); public CurrencyPropertyValue(MAPIProperty property, long flags, byte[] data) { super(property, flags, data); } @Override public BigInteger getValue() { long unshifted = LittleEndian.getLong(data); return BigInteger.valueOf(unshifted).divide(SHIFT); } public void setValue(BigInteger value) { if (data.length != 8) { data = new byte[8]; } long shifted = value.multiply(SHIFT).longValue(); LittleEndian.putLong(data, 0, shifted); } } /** * 64-bit integer specifying the number of 100ns periods since Jan 1, 1601 */ public static class TimePropertyValue extends PropertyValue { private static final long OFFSET = 1000L * 60L * 60L * 24L * (365L * 369L + 89L); public TimePropertyValue(MAPIProperty property, long flags, byte[] data) { super(property, flags, data); } @Override public Calendar getValue() { long time = LittleEndian.getLong(data); time = (time / 10 / 1000) - OFFSET; Calendar timeC = LocaleUtil.getLocaleCalendar(); timeC.setTimeInMillis(time); return timeC; } public void setValue(Calendar value) { if (data.length != 8) { data = new byte[8]; } long time = value.getTimeInMillis(); time = (time + OFFSET) * 10 * 1000; LittleEndian.putLong(data, 0, time); } } }