/* * Copyright (c) 2014 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.io.csv.writer; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import eu.esdihumboldt.hale.common.instance.io.impl.AbstractInstanceWriter; import eu.esdihumboldt.hale.common.instance.model.Group; import eu.esdihumboldt.hale.common.instance.model.Instance; import eu.esdihumboldt.hale.common.instance.model.InstanceCollection; import eu.esdihumboldt.hale.common.instance.model.TypeFilter; import eu.esdihumboldt.hale.common.schema.model.GroupPropertyDefinition; import eu.esdihumboldt.hale.common.schema.model.TypeDefinition; /** * Default instance export provider for table files (xls and csv) * * @author Patrick Lieb */ public abstract class AbstractTableInstanceWriter extends AbstractInstanceWriter { /** * @see eu.esdihumboldt.hale.common.core.io.IOProvider#isCancelable() */ @Override public boolean isCancelable() { return false; } /** * Iterates over properties of the instance and creates a map of the given * properties * * @param instance the Instance to check * @param headerRow the current header row of the table * @param solveNestedProperties <code>true</code> if nested properties * should be solved, otherwise <code>false</code> * @return a map of properties with string of localpart of the QName of the * property as key */ protected Map<String, Object> getPropertyMap(Instance instance, List<String> headerRow, boolean solveNestedProperties) { // properties of current instance Iterable<QName> allProperties = instance.getPropertyNames(); // write properties to map; currently only the first property of nested // properties is selected Map<String, Object> row = new HashMap<String, Object>(); for (QName qname : allProperties) { // get properties of the current instance Object[] properties = instance.getProperty(qname); if (properties != null && properties.length != 0) { String cellValue = ""; // only the first property is evaluated Object property = properties[0]; if (shouldBeDisplayed(property)) { cellValue = qname.getLocalPart(); } // if property is an OInstance or OGroup, it's a nested property if (solveNestedProperties && property instanceof Group) { Group nextInstance = (Group) property; iterateBuild(nextInstance, qname, headerRow, row, cellValue); // Group inst = (Group) property; // // check if property has a value and add it // checkValue(inst, headerRow, row, cellValue); // // go through nested properties to get other properties // Iterator<QName> propertyIt = inst.getPropertyNames().iterator(); // if (propertyIt.hasNext()) { // QName value = propertyIt.next(); // Object nextProp = inst.getProperty(value)[0]; // // check if current property should be displayed in map // if (shouldBeDisplayed(nextProp)) { // cellValue += "."; // cellValue += value.getLocalPart(); // } // // // iterate over all nested properties // while (nextProp instanceof Group) { // Group oinst = (Group) nextProp; // checkValue(oinst, headerRow, row, cellValue); // // // get localparts of all nested properties // Iterator<QName> qnames = oinst.getPropertyNames().iterator(); // if (qnames.hasNext()) { // value = qnames.next(); // nextProp = oinst.getProperty(value)[0]; // if (shouldBeDisplayed(nextProp)) { // cellValue += "."; // cellValue += value.getLocalPart(); // } // else // continue; // } // else // break; // } // // add property with corresponding cellValue (localpart) // // to map // // no resolving of nested properties // addProperty(headerRow, row, nextProp, cellValue); // } } else { // add property with corresponding cellValue (localpart) to // map if (property instanceof Group && shouldBeDisplayed(property)) { checkValue((Group) property, headerRow, row, cellValue); } else { addProperty(headerRow, row, property, cellValue); } } } } return row; } /** * * @param instance the actual instance * @param qNameOfTheInstance the qname of the instance * @param headerRow property names * @param row actual map with data * @param propertyPath the path, e.g. att1.att2.value, points at the actual * instance name/path */ private void iterateBuild(Group instance, QName qNameOfTheInstance, List<String> headerRow, Map<String, Object> row, String propertyPath) { if (shouldBeDisplayed(instance)) { // check if the actual instance has a value an add it checkValue(instance, headerRow, row, propertyPath); } // children properties of current instance Iterable<QName> children = instance.getPropertyNames(); for (QName qname : children) { if (instance.getProperty(qname).length > 0) { // only the first instance Object child = instance.getProperty(qname)[0]; if (child instanceof Group && shouldBeDisplayed(child)) { iterateBuild((Group) instance.getProperty(qname)[0], qname, headerRow, row, propertyPath + "." + qname.getLocalPart()); } else if (child instanceof Group) { // the child is a choice or packege, etc. iterateBuild((Group) instance.getProperty(qname)[0], qname, headerRow, row, propertyPath); } else { // child is an attribute addProperty(headerRow, row, child, propertyPath + "." + qname.getLocalPart()); } } } } // currently names of group property definitions should not be displayed, so // filter them private boolean shouldBeDisplayed(Object obj) { if (obj instanceof Group) { return !(((Group) obj).getDefinition() instanceof GroupPropertyDefinition); } return true; } private void addProperty(List<String> headerRow, Map<String, Object> row, Object property, String propertyTypeName) { if (!headerRow.contains(propertyTypeName)) { headerRow.add(propertyTypeName); } row.put(propertyTypeName, property); } // check if value of current property isn't null and add it private void checkValue(Group group, List<String> headerRow, Map<String, Object> row, String propertyTypeName) { if (group instanceof Instance) { Object value = ((Instance) group).getValue(); if (value != null) { addProperty(headerRow, row, value, propertyTypeName); } } } /** * Call this to get an instance collection based on the selected Type * * @param typeName the QName of the typeDefinition * @return The instance collection for the given type, can be empty * collection */ protected InstanceCollection getInstanceCollection(QName typeName) { if (typeName == null) { return getInstances(); } // get all instances of the selected Type InstanceCollection instances = null; TypeDefinition selectedType = getTargetSchema().getType(typeName); if (selectedType != null) { instances = getInstances().select(new TypeFilter(selectedType)); } // if there is no selected type return random instance ??? else instances = getInstances(); return instances; } }