| /* |
| * 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.chemistry.opencmis.commons.impl.xml; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.lang.reflect.Method; |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.GregorianCalendar; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Random; |
| import java.util.Set; |
| import java.util.TimeZone; |
| |
| import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement; |
| import org.apache.chemistry.opencmis.commons.data.PropertyData; |
| import org.apache.chemistry.opencmis.commons.data.PropertyId; |
| import org.apache.chemistry.opencmis.commons.enums.PropertyType; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractPropertyData; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.CmisExtensionElementImpl; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanImpl; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeImpl; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDecimalImpl; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyHtmlImpl; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdImpl; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerImpl; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyUriImpl; |
| import org.junit.Before; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Base test class for converter tests. |
| */ |
| public abstract class AbstractConverterTest { |
| |
| private final static Logger LOG = LoggerFactory.getLogger(AbstractConverterTest.class); |
| |
| private final static long SEED = 1234567890; |
| |
| protected Random rnd; |
| |
| @Before |
| public void init() throws Exception { |
| rnd = new Random(SEED); |
| } |
| |
| protected PropertyData<?> createPropertyData(PropertyType propertyType, int numValues) { |
| AbstractPropertyData<?> result = null; |
| |
| switch (propertyType) { |
| case BOOLEAN: |
| result = new PropertyBooleanImpl(); |
| if (numValues > 0) { |
| List<Boolean> values = new ArrayList<Boolean>(); |
| for (int i = 0; i < numValues; i++) { |
| values.add(randomBoolean()); |
| } |
| ((PropertyBooleanImpl) result).setValues(values); |
| } |
| break; |
| case DATETIME: |
| result = new PropertyDateTimeImpl(); |
| if (numValues > 0) { |
| List<GregorianCalendar> values = new ArrayList<GregorianCalendar>(); |
| for (int i = 0; i < numValues; i++) { |
| values.add(randomDateTime()); |
| } |
| ((PropertyDateTimeImpl) result).setValues(values); |
| } |
| break; |
| case DECIMAL: |
| result = new PropertyDecimalImpl(); |
| if (numValues > 0) { |
| List<BigDecimal> values = new ArrayList<BigDecimal>(); |
| for (int i = 0; i < numValues; i++) { |
| values.add(randomDecimal()); |
| } |
| ((PropertyDecimalImpl) result).setValues(values); |
| } |
| break; |
| case HTML: |
| result = new PropertyHtmlImpl(); |
| if (numValues > 0) { |
| List<String> values = new ArrayList<String>(); |
| for (int i = 0; i < numValues; i++) { |
| values.add(randomString()); |
| } |
| ((PropertyHtmlImpl) result).setValues(values); |
| } |
| break; |
| case ID: |
| result = new PropertyIdImpl(); |
| if (numValues > 0) { |
| List<String> values = new ArrayList<String>(); |
| for (int i = 0; i < numValues; i++) { |
| values.add(randomString()); |
| } |
| ((PropertyIdImpl) result).setValues(values); |
| } |
| break; |
| case INTEGER: |
| result = new PropertyIntegerImpl(); |
| if (numValues > 0) { |
| List<BigInteger> values = new ArrayList<BigInteger>(); |
| for (int i = 0; i < numValues; i++) { |
| values.add(randomInteger()); |
| } |
| ((PropertyIntegerImpl) result).setValues(values); |
| } |
| break; |
| case STRING: |
| result = new PropertyStringImpl(); |
| if (numValues > 0) { |
| List<String> values = new ArrayList<String>(); |
| for (int i = 0; i < numValues; i++) { |
| values.add(randomString()); |
| } |
| ((PropertyStringImpl) result).setValues(values); |
| } |
| break; |
| case URI: |
| result = new PropertyUriImpl(); |
| if (numValues > 0) { |
| List<String> values = new ArrayList<String>(); |
| for (int i = 0; i < numValues; i++) { |
| values.add(randomUri()); |
| } |
| ((PropertyUriImpl) result).setValues(values); |
| } |
| break; |
| default: |
| assert false; |
| } |
| |
| result.setId(randomString()); |
| result.setDisplayName(randomString()); |
| result.setLocalName(randomString()); |
| result.setQueryName(randomString()); |
| |
| return result; |
| } |
| |
| protected PropertyId createIdPropertyData(String id, String value) { |
| PropertyIdImpl result = new PropertyIdImpl(); |
| |
| result.setId(id); |
| result.setDisplayName(id); |
| result.setLocalName(id); |
| result.setQueryName(id); |
| result.setValue(value); |
| |
| return result; |
| } |
| |
| protected List<CmisExtensionElement> createExtensions(int depth) { |
| List<CmisExtensionElement> result = new ArrayList<CmisExtensionElement>(); |
| |
| String[] namespaces = new String[] { "http://ext1.com", "http://ext2.org", "http://ext3.net" }; |
| |
| for (int i = 0; i < randomInt(4) + 1; i++) { |
| String ns = namespaces[randomInt(namespaces.length)]; |
| |
| Map<String, String> attr = new HashMap<String, String>(); |
| for (int j = 0; j < randomInt(3); j++) { |
| attr.put(randomTag(), randomString()); |
| } |
| |
| CmisExtensionElementImpl element; |
| if (randomBoolean() || depth < 1) { |
| element = new CmisExtensionElementImpl(ns, randomTag(), attr, randomString()); |
| } else { |
| element = new CmisExtensionElementImpl(ns, randomTag(), attr, createExtensions(depth - 1)); |
| } |
| |
| result.add(element); |
| } |
| |
| return result; |
| } |
| |
| protected String randomString() { |
| StringBuilder sb = new StringBuilder(); |
| |
| int length = rnd.nextInt(21) + 3; |
| for (int i = 0; i < length; i++) { |
| sb.append((char) (rnd.nextInt(94) + 32)); |
| } |
| |
| return sb.toString(); |
| } |
| |
| protected String randomUri() { |
| StringBuilder sb = new StringBuilder("urn:test:"); |
| |
| int length = rnd.nextInt(21) + 3; |
| for (int i = 0; i < length; i++) { |
| sb.append((char) (rnd.nextInt(26) + 97)); |
| } |
| |
| return sb.toString(); |
| } |
| |
| protected Boolean randomBoolean() { |
| return Boolean.valueOf(rnd.nextBoolean()); |
| } |
| |
| protected BigInteger randomInteger() { |
| return BigInteger.valueOf(rnd.nextInt()); |
| } |
| |
| protected BigDecimal randomDecimal() { |
| return BigDecimal.valueOf(rnd.nextDouble() * rnd.nextInt()); |
| } |
| |
| protected GregorianCalendar randomDateTime() { |
| GregorianCalendar cal = new GregorianCalendar(); |
| cal.setTimeZone(TimeZone.getTimeZone("GMT" + (rnd.nextBoolean() ? "+" : "-") + (rnd.nextInt(23) - 12) + ":00")); |
| cal.set(1583 + rnd.nextInt(8416), rnd.nextInt(12), rnd.nextInt(31) + 1, rnd.nextInt(23), rnd.nextInt(60), |
| rnd.nextInt(60)); |
| cal.set(Calendar.MILLISECOND, 0); |
| |
| return cal; |
| } |
| |
| protected int randomInt(int n) { |
| return rnd.nextInt(n); |
| } |
| |
| @SuppressWarnings("unchecked") |
| protected <T extends Enum<?>> T randomEnum(Class<T> enumClass) { |
| T[] values = null; |
| try { |
| values = (T[]) enumClass.getMethod("values", new Class<?>[0]).invoke(null, new Object[0]); |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| return values[rnd.nextInt(values.length)]; |
| } |
| |
| protected String randomTag() { |
| StringBuilder sb = new StringBuilder(); |
| |
| int length = rnd.nextInt(7) + 3; |
| for (int i = 0; i < length; i++) { |
| sb.append((char) (rnd.nextInt(26) + 'a')); |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Compares two data objects. |
| */ |
| protected void assertDataObjectsEquals(String name, Object expected, Object actual, Set<String> ignoreMethods) { |
| |
| LOG.debug(name + ": " + expected + " / " + actual); |
| |
| if ((expected == null) && (actual == null)) { |
| return; |
| } |
| |
| if ((expected == null) || (actual == null)) { |
| fail("Data object is null! name: " + name + " / expected: " + expected + " / actual: " + actual); |
| } |
| |
| // handle simple types |
| if ((expected instanceof String) || (expected instanceof Boolean) || (expected instanceof BigInteger) |
| || (expected instanceof BigDecimal) || (expected instanceof Enum<?>)) { |
| assertEquals(name, expected, actual); |
| |
| return; |
| } else if (expected instanceof GregorianCalendar) { |
| long expectedMillis = ((GregorianCalendar) expected).getTimeInMillis(); |
| long actualMillis = ((GregorianCalendar) actual).getTimeInMillis(); |
| |
| assertEquals(name, expectedMillis, actualMillis); |
| |
| return; |
| } else if (expected instanceof List<?>) { |
| List<?> expectedList = (List<?>) expected; |
| List<?> actualList = (List<?>) actual; |
| |
| assertEquals(name + ".length", expectedList.size(), actualList.size()); |
| |
| for (int i = 0; i < expectedList.size(); i++) { |
| assertDataObjectsEquals(name + "[" + i + "]", expectedList.get(i), actualList.get(i), ignoreMethods); |
| } |
| |
| return; |
| } else if (expected instanceof Map<?, ?>) { |
| Map<?, ?> expectedMap = (Map<?, ?>) expected; |
| Map<?, ?> actualMap = (Map<?, ?>) actual; |
| |
| assertEquals(name + ".length", expectedMap.size(), actualMap.size()); |
| |
| for (Map.Entry<?, ?> entry : expectedMap.entrySet()) { |
| assertTrue(name + ".contains[" + entry.getKey() + "]", actualMap.containsKey(entry.getKey())); |
| assertDataObjectsEquals(name + "[" + entry.getKey() + "]", entry.getValue(), |
| actualMap.get(entry.getKey()), ignoreMethods); |
| } |
| |
| return; |
| } else if (expected instanceof Set<?>) { |
| Set<?> expectedSet = (Set<?>) expected; |
| Set<?> actualSet = (Set<?>) actual; |
| |
| assertEquals(name + ".length", expectedSet.size(), actualSet.size()); |
| |
| for (Object item : expectedSet) { |
| assertTrue(name + ".contains[" + item + "]", actualSet.contains(item)); |
| } |
| |
| return; |
| } |
| |
| for (Method m : expected.getClass().getMethods()) { |
| if (!m.getName().startsWith("get") && !m.getName().startsWith("is") && !m.getName().startsWith("supports")) { |
| continue; |
| } |
| |
| if (ignoreMethods != null && ignoreMethods.contains(m.getName())) { |
| continue; |
| } |
| |
| if (m.getName().equals("getClass")) { |
| continue; |
| } |
| |
| if (m.getParameterTypes().length != 0) { |
| continue; |
| } |
| |
| try { |
| Object expectedValue = m.invoke(expected, new Object[0]); |
| Object actualValue = m.invoke(actual, new Object[0]); |
| |
| assertDataObjectsEquals(name + "." + m.getName(), expectedValue, actualValue, ignoreMethods); |
| } catch (Exception e) { |
| fail(e.toString()); |
| } |
| } |
| } |
| } |