/*****************************************************************************
* 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.xmpbox.schema;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Random;
import org.apache.xmpbox.XMPMetadata;
import org.apache.xmpbox.type.AbstractSimpleProperty;
import org.apache.xmpbox.type.ArrayProperty;
import org.apache.xmpbox.type.Cardinality;
import org.apache.xmpbox.type.TypeMapping;
import org.apache.xmpbox.type.AbstractTypeTester;
import org.apache.xmpbox.type.Types;
import org.apache.xmpbox.xml.DomXmpParser;
import org.junit.Assert;
import org.junit.Test;
public abstract class AbstractSchemaTester extends AbstractTypeTester
{
protected XMPMetadata xmp;
protected String fieldName;
protected Types type;
protected Cardinality cardinality;
protected TypeMapping typeMapping = null;
protected DomXmpParser builder;
public void before() throws Exception
{
builder = new DomXmpParser();
xmp = XMPMetadata.createXMPMetadata();
typeMapping = xmp.getTypeMapping();
}
protected abstract XMPSchema getSchema();
protected Class<? extends XMPSchema> getSchemaClass()
{
return getSchema().getClass();
}
public AbstractSchemaTester(String fieldName, Types type, Cardinality card)
{
this.fieldName = fieldName;
this.type = type;
this.cardinality = card;
}
@Test
public void testInitializedToNull() throws Exception
{
XMPSchema schema = getSchema();
// default method
Assert.assertNull(schema.getProperty(fieldName));
// accessor
if (cardinality == Cardinality.Simple)
{
String getter = calculateSimpleGetter(fieldName);
Method get = getSchemaClass().getMethod(getter);
Object result = get.invoke(schema);
Assert.assertNull(result);
}
else
{
// arrays
String getter = calculateArrayGetter(fieldName);
Method get = getSchemaClass().getMethod(getter);
Object result = get.invoke(schema);
Assert.assertNull(result);
}
}
@Test
public void testSettingValue() throws Exception
{
internalTestSettingValue();
}
@Test
public void testRandomSettingValue() throws Exception
{
initializeSeed(new Random());
for (int i=0; i < RAND_LOOP_COUNT;i++)
{
internalTestSettingValue();
}
}
private void internalTestSettingValue() throws Exception
{
if (cardinality != Cardinality.Simple)
{
return;
}
XMPSchema schema = getSchema();
// only test simple properties
Object value = getJavaValue(type);
AbstractSimpleProperty property = schema.instanciateSimple(fieldName, value);
schema.addProperty(property);
String qn = getPropertyQualifiedName(fieldName);
Assert.assertNotNull(schema.getProperty(fieldName));
// check other properties not modified
List<Field> fields = getXmpFields(getSchemaClass());
for (Field field : fields)
{
// do not check the current name
String fqn = getPropertyQualifiedName(field.get(null).toString());
if (!fqn.equals(qn))
{
Assert.assertNull(schema.getProperty(fqn));
}
}
}
@Test
public void testSettingValueInArray() throws Exception
{
internalTestSettingValueInArray();
}
@Test
public void testRandomSettingValueInArray() throws Exception
{
initializeSeed(new Random());
for (int i=0; i < RAND_LOOP_COUNT;i++)
{
internalTestSettingValueInArray();
}
}
private void internalTestSettingValueInArray() throws Exception
{
if (cardinality == Cardinality.Simple)
{
return;
}
XMPSchema schema = getSchema();
// only test array properties
Object value = getJavaValue(type);
AbstractSimpleProperty property = schema.instanciateSimple(fieldName, value);
switch (cardinality)
{
case Seq:
schema.addUnqualifiedSequenceValue(property.getPropertyName(), property);
break;
case Bag:
schema.addBagValue(property.getPropertyName(), property);
break;
default:
throw new Exception("Unexpected case in test : " + cardinality.name());
}
String qn = getPropertyQualifiedName(fieldName);
Assert.assertNotNull(schema.getProperty(fieldName));
// check other properties not modified
List<Field> fields = getXmpFields(getSchemaClass());
for (Field field : fields)
{
// do not check the current name
String fqn = getPropertyQualifiedName(field.get(null).toString());
if (!fqn.equals(qn))
{
Assert.assertNull(schema.getProperty(fqn));
}
}
}
@Test
public void testPropertySetterSimple() throws Exception
{
internalTestPropertySetterSimple();
}
@Test
public void testRandomPropertySetterSimple() throws Exception
{
initializeSeed(new Random());
for (int i=0; i < RAND_LOOP_COUNT;i++)
{
internalTestPropertySetterSimple();
}
}
private void internalTestPropertySetterSimple() throws Exception
{
if (cardinality != Cardinality.Simple)
{
return;
}
XMPSchema schema = getSchema();
String setter = calculateSimpleSetter(fieldName) + "Property";
Object value = getJavaValue(type);
AbstractSimpleProperty asp = typeMapping.instanciateSimpleProperty(schema.getNamespace(), schema
.getPrefix(), fieldName, value, type);
Method set = getSchemaClass().getMethod(setter, type.getImplementingClass());
set.invoke(schema, asp);
// check property set
AbstractSimpleProperty stored = (AbstractSimpleProperty) schema.getProperty(fieldName);
Assert.assertEquals(value, stored.getValue());
// check getter
String getter = calculateSimpleGetter(fieldName) + "Property";
Method get = getSchemaClass().getMethod(getter);
Object result = get.invoke(schema);
Assert.assertTrue(type.getImplementingClass().isAssignableFrom(result.getClass()));
Assert.assertEquals(asp, result);
}
@Test
public void testPropertySetterInArray() throws Exception
{
internalTestPropertySetterInArray();
}
@Test
public void testRandomPropertySetterInArray() throws Exception
{
initializeSeed(new Random());
for (int i=0; i < RAND_LOOP_COUNT;i++)
{
internalTestPropertySetterInArray();
}
}
private void internalTestPropertySetterInArray() throws Exception
{
if (cardinality == Cardinality.Simple)
{
return;
}
XMPSchema schema = getSchema();
// add value
String setter = "add" + calculateFieldNameForMethod(fieldName);
// TypeDescription<AbstractSimpleProperty> td =
// typeMapping.getSimpleDescription(type);
Object value1 = getJavaValue(type);
Method set = getSchemaClass().getMethod(setter, getJavaType(type));
set.invoke(schema, value1);
// retrieve complex property
String getter = calculateArrayGetter(fieldName) + "Property";
Method getcp = getSchemaClass().getMethod(getter);
Object ocp = getcp.invoke(schema);
Assert.assertTrue(ocp instanceof ArrayProperty);
ArrayProperty cp = (ArrayProperty) ocp;
// check size is ok (1)
Assert.assertEquals(1, cp.getContainer().getAllProperties().size());
// add a new one
Object value2 = getJavaValue(type);
set.invoke(schema, value2);
Assert.assertEquals(2, cp.getContainer().getAllProperties().size());
// remove the first
String remover = "remove" + calculateFieldNameForMethod(fieldName);
Method remove = getSchemaClass().getMethod(remover, getJavaType(type));
remove.invoke(schema, value1);
Assert.assertEquals(1, cp.getContainer().getAllProperties().size());
}
protected String getPropertyQualifiedName(String name)
{
StringBuilder sb = new StringBuilder();
sb.append(getSchema().getPrefix()).append(":").append(name);
return sb.toString();
}
}