Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*-
*******************************************************************************
* Copyright (c) 2011, 2016 Diamond Light Source Ltd.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Matthew Gerring - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.dawnsci.nexus.builder.data;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.eclipse.dawnsci.analysis.api.tree.DataNode;
import org.eclipse.dawnsci.analysis.api.tree.Node;
import org.eclipse.dawnsci.nexus.NXdata;
import org.eclipse.dawnsci.nexus.NXobject;
import org.eclipse.dawnsci.nexus.NexusException;
import org.eclipse.dawnsci.nexus.builder.NexusObjectProvider;
import org.eclipse.dawnsci.nexus.builder.data.impl.AxisDataDeviceImpl;
import org.eclipse.dawnsci.nexus.builder.data.impl.AxisFieldModel;
import org.eclipse.dawnsci.nexus.builder.data.impl.DataDeviceImpl;
import org.eclipse.dawnsci.nexus.builder.data.impl.DataFieldModel;
import org.eclipse.dawnsci.nexus.builder.data.impl.PrimaryDataDeviceImpl;
/**
* A builder class for building a {@link DataDevice} from an {@link NexusObjectProvider}.
* Provides the ability to configure which fields from the underlying nexus object are
* are linked to the {@link NXdata} group and how.
*
* @author Matthew Dickie
*
* @param the sub-interface of {@link NXobject} that the nexus object was created from
*/
public class DataDeviceBuilder {
public static PrimaryDataDevice newPrimaryDataDevice(
NexusObjectProvider nexusObjectProvider) throws NexusException {
return (PrimaryDataDevice) newPrimaryDataDeviceBuilder(nexusObjectProvider).build();
}
public static PrimaryDataDevice newPrimaryDataDevice(
NexusObjectProvider nexusObjectProvider, String signalDataFieldName) throws NexusException {
DataDeviceBuilder builder = new DataDeviceBuilder<>(nexusObjectProvider, true);
builder.setSignalField(signalDataFieldName);
return (PrimaryDataDevice) builder.build();
}
public static DataDeviceBuilder newPrimaryDataDeviceBuilder(
NexusObjectProvider nexusObjectProvider) {
return new DataDeviceBuilder<>(nexusObjectProvider, true);
}
public static AxisDataDevice newAxisDataDevice(
NexusObjectProvider nexusObjectProvider) throws NexusException {
return (AxisDataDevice) newAxisDataDeviceBuilder(nexusObjectProvider).build();
}
public static AxisDataDevice newAxisDataDevice(
NexusObjectProvider nexusObjectProvider, Integer defaultAxisDimension) throws NexusException {
return (AxisDataDevice) newAxisDataDeviceBuilder(nexusObjectProvider, defaultAxisDimension).build();
}
public static AxisDataDevice newAxisDataDevice(
NexusObjectProvider nexusObjectProvider, String defaultAxisSourceFieldName,
Integer defaultAxisDimension) throws NexusException {
return (AxisDataDevice) newAxisDataDeviceBuilder(nexusObjectProvider,
defaultAxisSourceFieldName, defaultAxisDimension).build();
}
public static DataDeviceBuilder newAxisDataDeviceBuilder(
NexusObjectProvider nexusObjectProvider) {
return new DataDeviceBuilder<>(nexusObjectProvider, false);
}
public static DataDeviceBuilder newAxisDataDeviceBuilder(
NexusObjectProvider nexusObjectProvider, Integer defaultAxisDimension) {
DataDeviceBuilder builder = new DataDeviceBuilder<>(nexusObjectProvider, false);
builder.setDefaultAxisDimension(defaultAxisDimension);
return builder;
}
public static DataDeviceBuilder newAxisDataDeviceBuilder(
NexusObjectProvider nexusObjectProvider, String defaultAxisSourceFieldName,
Integer defaultAxisDimension) {
DataDeviceBuilder builder = new DataDeviceBuilder<>(nexusObjectProvider, false);
builder.setDefaultAxisSourceFieldName(defaultAxisSourceFieldName);
builder.setDefaultAxisDimension(defaultAxisDimension);
return builder;
}
private final boolean isPrimary;
private final NexusObjectProvider nexusObjectProvider;
private final N nexusObject;
private String signalFieldSourceName = null;
private boolean includeAddedFieldsOnly = false;
private List addedFields = null;
private Integer defaultAxisDimension = null;
private String defaultAxisSourceFieldName = null;
private Map overriddenDestinationFieldNames = null;
private Map overriddenDefaultAxisDimensions = null;
private Map overriddenDimensionMappings = null;
private int[] defaultDimensionMappings = null;
private Boolean useDeviceName = null;
private String destinationFieldNamePrefix = null;
private int numberOfAxisFieldsToAdd;
/**
* Create a new {@link DataDeviceBuilder} for the given {@link NexusObjectProvider}.
*
* @param nexusObjectProvider nexus object provider wrapping a {@link NXobject}
* @param isPrimary true to build a {@link PrimaryDataDevice}, containing
* the @signal field for the {@link NXdata} group,
* false to build an {@link AxisDataDevice}.
*/
public DataDeviceBuilder(NexusObjectProvider nexusObjectProvider, boolean isPrimary) {
Objects.requireNonNull(nexusObjectProvider);
this.nexusObjectProvider = nexusObjectProvider;
this.nexusObject = nexusObjectProvider.getNexusObject();
Objects.requireNonNull(nexusObject);
this.isPrimary = isPrimary;
if (isPrimary) {
signalFieldSourceName = nexusObjectProvider.getPrimaryDataFieldName();
Objects.requireNonNull(signalFieldSourceName);
}
}
public void setSignalField(String signalFieldSourceName) {
Objects.requireNonNull(signalFieldSourceName, "The signal field of an NXdata group cannot be null. Probably you have not set a primary data field for your nexus object.");
this.signalFieldSourceName = signalFieldSourceName;
}
public void clearAxisFields() {
addedFields = null;
includeAddedFieldsOnly = true;
}
public void addAxisField(String axisFieldName) {
Objects.requireNonNull(axisFieldName);
if (addedFields == null) {
addedFields = new ArrayList<>();
}
addedFields.add(axisFieldName);
}
public void addAxisField(String axisFieldName, int defaultAxisDimension) {
addAxisField(axisFieldName);
setDefaultAxisDimension(axisFieldName, defaultAxisDimension);
}
public void addAxisField(String axisFieldName, String axisFieldDestinationName) {
addAxisField(axisFieldName);
setDestinationFieldName(axisFieldName, axisFieldDestinationName);
}
public void setDefaultAxisDimension(String axisFieldName, int defaultAxisDimension) {
Objects.requireNonNull(axisFieldName);
if (overriddenDefaultAxisDimensions == null) {
overriddenDefaultAxisDimensions = new HashMap<>();
}
overriddenDefaultAxisDimensions.put(axisFieldName, defaultAxisDimension);
}
public void addAxisField(String axisFieldName, int[] dimensionMappings) {
addAxisField(axisFieldName);
setDimensionMappings(axisFieldName, dimensionMappings);
}
public void setDimensionMappings(String axisFieldName, int... dimensionMappings) {
Objects.requireNonNull(axisFieldName);
if (overriddenDimensionMappings == null) {
overriddenDimensionMappings = new HashMap<>();
}
overriddenDimensionMappings.put(axisFieldName, dimensionMappings);
}
public void addAxisFields(String... axisFieldNames) {
for (String axisFieldName : axisFieldNames) {
addAxisField(axisFieldName);
}
}
public void setAxisFields(String... axisFieldNames) {
clearAxisFields();
addAxisFields(axisFieldNames);
}
public void setDefaultAxisDimension(Integer defaultAxisDimension) {
this.defaultAxisDimension = defaultAxisDimension;
}
public void setDefaultAxisSourceFieldName(String defaultAxisSourceFieldName) {
Objects.requireNonNull(defaultAxisSourceFieldName);
addAxisField(defaultAxisSourceFieldName);
this.defaultAxisSourceFieldName = defaultAxisSourceFieldName;
}
public void setDefaultDimensionMappings(int[] defaultDimensionMappings) {
this.defaultDimensionMappings = defaultDimensionMappings;
}
public void setUseDeviceName(boolean useDeviceName) {
this.useDeviceName = useDeviceName;
}
public void setDestinationFieldNamePrefix(String prefix) {
destinationFieldNamePrefix = prefix;
}
public void setDestinationFieldName(String sourceFieldName, String destinationFieldName) {
Objects.requireNonNull(sourceFieldName);
Objects.requireNonNull(destinationFieldName);
if (overriddenDestinationFieldNames == null) {
overriddenDestinationFieldNames = new HashMap<>();
}
overriddenDestinationFieldNames.put(sourceFieldName, destinationFieldName);
}
private DataDeviceImpl createDataDevice() throws NexusException {
N nexusObject = nexusObjectProvider.getNexusObject();
if (isPrimary) {
DataFieldModel signalFieldModel = createSignalFieldModel();
return new PrimaryDataDeviceImpl(nexusObject, signalFieldModel);
}
return new AxisDataDeviceImpl(nexusObject);
}
/**
* Get the rank of the field with the given name .
* @param fieldName field name
* @return field rank
* @throws NexusException
*/
private int getFieldRank(String fieldName) throws NexusException {
final Node fieldNode = nexusObject.getNode(fieldName);
if (fieldNode != null) {
// the node is a data node
if (fieldNode.isDataNode()) {
return ((DataNode) fieldNode).getRank();
}
// the node is an external link. The rank should have been set in the NexusObjectProvider
if (fieldNode.isSymbolicNode()) {
return nexusObjectProvider.getExternalDatasetRank(fieldName);
}
}
// no such data node or external link
throw new NexusException(MessageFormat.format(
"The {0} does not have a data node or symbolic node with the name: {1}",
nexusObject.getNXclass().getSimpleName(), fieldName));
}
private Integer getDefaultAxisDimension(String axisFieldName) {
Integer defaultAxisDimension = null;
// first check if the value has been overridden (i.e. explicitly set)
if (overriddenDefaultAxisDimensions != null) {
defaultAxisDimension = overriddenDefaultAxisDimensions.get(axisFieldName);
}
// if this is the default axis field, apply the default axis dimension
if (defaultAxisDimension == null && axisFieldName.equals(defaultAxisSourceFieldName)) {
defaultAxisDimension = this.defaultAxisDimension;
}
// for a primary device, see if the nexus object provider knows the default axis dimension
// e.g. the axis field belongs to the same device as the signal field for the NXdata
if (defaultAxisDimension == null && isPrimary) {
defaultAxisDimension = nexusObjectProvider.getDefaultAxisDimension(
signalFieldSourceName, axisFieldName);
}
return defaultAxisDimension;
}
private int[] getDimensionMappings(String axisFieldName) throws NexusException {
int[] dimensionMappings = null;
// first check if the value has been overridden (i.e. explicitly set)
if (overriddenDimensionMappings != null) {
dimensionMappings = overriddenDimensionMappings.get(axisFieldName);
}
// if this is a default axis field and has size 1, this must be the dimension mapping
final int fieldRank = getFieldRank(axisFieldName);
if (dimensionMappings == null && fieldRank == 1) {
Integer defaultAxisDimensions = getDefaultAxisDimension(axisFieldName);
if (defaultAxisDimensions != null) {
dimensionMappings = new int[] { defaultAxisDimensions.intValue() };
}
}
// use the default dimension mappings for the device if set and of the same rank
if (dimensionMappings == null && defaultDimensionMappings != null &&
fieldRank == defaultDimensionMappings.length) {
dimensionMappings = defaultDimensionMappings;
}
return dimensionMappings;
}
private String getDestinationFieldName(String sourceFieldName) {
String destinationFieldName = null;
// first check if the value has been overridden (i.e. explicitly set)
if (overriddenDestinationFieldNames != null &&
overriddenDestinationFieldNames.containsKey(sourceFieldName)) {
return overriddenDestinationFieldNames.get(sourceFieldName);
}
// if a destination name prefix has been set, use that
if (destinationFieldName == null && destinationFieldNamePrefix != null) {
return destinationFieldNamePrefix + destinationFieldName;
}
if (useDeviceName()) {
String deviceName = nexusObjectProvider.getName();
// if there's just one field, use the device name as the destination field name
if (getNumberOfFieldsToAdd() == 1) {
destinationFieldName = deviceName;
} else {
// otherwise prepend the device name to the source field name
destinationFieldName = deviceName + '_' + sourceFieldName;
}
} else {
destinationFieldName = sourceFieldName;
}
return destinationFieldName;
}
private boolean useDeviceName() {
if (useDeviceName != null) {
return useDeviceName.booleanValue();
}
if (nexusObjectProvider.getUseDeviceNameInNXdata() != null) {
return nexusObjectProvider.getUseDeviceNameInNXdata();
}
return !isPrimary;
}
private int getNumberOfFieldsToAdd() {
return numberOfAxisFieldsToAdd + (isPrimary ? 1 : 0);
}
private DataFieldModel createSignalFieldModel() throws NexusException {
int fieldRank = getFieldRank(signalFieldSourceName);
String signalDestFieldName = getDestinationFieldName(signalFieldSourceName);
DataFieldModel signalFieldModel = new DataFieldModel(signalFieldSourceName, signalDestFieldName, fieldRank);
return signalFieldModel;
}
/**
* Creates and returns the {@link AxisFieldModel} for the field with the given name.
* @param axisFieldName axis field name
* @return axis field model
* @throws NexusException
*/
private AxisFieldModel createAxisFieldModel(String axisFieldName) throws NexusException {
Integer defaultAxisDimension = getDefaultAxisDimension(axisFieldName);
int[] dimensionMappings = getDimensionMappings(axisFieldName);
String destinationFieldName = getDestinationFieldName(axisFieldName);
int rank = getFieldRank(axisFieldName);
final AxisFieldModel axisFieldModel = new AxisFieldModel(axisFieldName, rank);
axisFieldModel.setDefaultAxisDimension(defaultAxisDimension);
axisFieldModel.setDimensionMappings(dimensionMappings);
axisFieldModel.setDestinationFieldName(destinationFieldName);
return axisFieldModel;
}
private Set calculateAxisFieldNamesToAdd() {
Set axisFieldNames = new LinkedHashSet<>();
if (!includeAddedFieldsOnly) {
// add the default fields according to the nexus object provider
if (isPrimary) {
// add any axis fields specific to this primary data field (i.e. signal field)
axisFieldNames.addAll(nexusObjectProvider.getAxisDataFieldsForPrimaryDataField(
signalFieldSourceName));
} else {
// if this is not a primary device, the primary data field of the
// nexus object provider is an axis field for the signal field
// (which is from the primary device)
if (nexusObjectProvider.getPrimaryDataFieldName() != null) {
axisFieldNames.add(nexusObjectProvider.getPrimaryDataFieldName());
}
}
if (nexusObjectProvider.getDefaultAxisDataFieldName() != null) {
axisFieldNames.add(nexusObjectProvider.getDefaultAxisDataFieldName());
}
axisFieldNames.addAll(nexusObjectProvider.getAxisDataFieldNames());
}
// add the fields added by calling addAxisField()
if (addedFields != null) {
axisFieldNames.addAll(addedFields);
}
if (isPrimary) {
// make sure the signal field name isn't included
axisFieldNames.remove(signalFieldSourceName);
}
return axisFieldNames;
}
/**
* Builds and returns the data device. If primary was set to true, a
* {@link PrimaryDataDevice} will be returned, otherwise an {@link AxisDataDevice} will be
* returned
* @return data device
* @throws NexusException
*/
public DataDevice build() throws NexusException {
final DataDeviceImpl dataDevice = createDataDevice();
// calculate the default axis source field name, if not set
if (defaultAxisSourceFieldName == null && defaultAxisDimension != null) {
defaultAxisSourceFieldName = nexusObjectProvider.getDefaultAxisDataFieldName();
if (defaultAxisSourceFieldName == null) {
defaultAxisSourceFieldName = nexusObjectProvider.getPrimaryDataFieldName();
}
}
// get the names of the axis fields to add
Set axisFieldNames = calculateAxisFieldNamesToAdd();
numberOfAxisFieldsToAdd = axisFieldNames.size();
for (String axisFieldName : axisFieldNames) {
AxisFieldModel axisFieldModel = createAxisFieldModel(axisFieldName); // add each field
dataDevice.addAxisField(axisFieldModel);
}
return dataDevice;
}
}