All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.dawnsci.nexus.builder.impl.DefaultNexusEntryBuilder Maven / Gradle / Ivy

/*-
 *******************************************************************************
 * Copyright (c) 2015 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 Dickie - initial API and implementation and/or initial documentation
 *******************************************************************************/

package org.eclipse.dawnsci.nexus.builder.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.eclipse.dawnsci.analysis.api.tree.DataNode;
import org.eclipse.dawnsci.analysis.api.tree.GroupNode;
import org.eclipse.dawnsci.analysis.api.tree.NodeLink;
import org.eclipse.dawnsci.nexus.NXcollection;
import org.eclipse.dawnsci.nexus.NXdata;
import org.eclipse.dawnsci.nexus.NXentry;
import org.eclipse.dawnsci.nexus.NXinstrument;
import org.eclipse.dawnsci.nexus.NXobject;
import org.eclipse.dawnsci.nexus.NXsample;
import org.eclipse.dawnsci.nexus.NXuser;
import org.eclipse.dawnsci.nexus.NexusApplicationDefinition;
import org.eclipse.dawnsci.nexus.NexusBaseClass;
import org.eclipse.dawnsci.nexus.NexusException;
import org.eclipse.dawnsci.nexus.NexusNodeFactory;
import org.eclipse.dawnsci.nexus.builder.CustomNexusEntryModification;
import org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder;
import org.eclipse.dawnsci.nexus.builder.NexusEntryModification;
import org.eclipse.dawnsci.nexus.builder.NexusMetadataProvider;
import org.eclipse.dawnsci.nexus.builder.NexusMetadataProvider.MetadataEntry;
import org.eclipse.dawnsci.nexus.builder.NexusObjectProvider;
import org.eclipse.dawnsci.nexus.builder.appdef.NexusApplicationBuilder;
import org.eclipse.dawnsci.nexus.builder.appdef.impl.DefaultApplicationFactory;
import org.eclipse.dawnsci.nexus.builder.data.NexusDataBuilder;
import org.eclipse.dawnsci.nexus.builder.data.impl.DefaultNexusDataBuilder;
import org.eclipse.dawnsci.nexus.validation.NexusValidationException;

/**
 * Default implementation of {@link NexusEntryBuilder}
 */
public class DefaultNexusEntryBuilder implements NexusEntryBuilder {

	private static final String APPDEF_SUBENTRY_SUFFIX = "_entry";

	private final String entryName;
	
	private final NXentry nxEntry;

	private NXinstrument nxInstrument = null;

	private NXsample nxSample = null;

	private List defaultGroups = null;

	private final List applications = new ArrayList<>();

	/**
	 * Creates a new {@link DefaultNexusEntryBuilder}. This constructor should only be called
	 * by {@link DefaultNexusFileBuilder}.
	 * @param entryName name of entry
	 * @param nxEntry entry to wrap
	 */
	protected DefaultNexusEntryBuilder(String entryName,
			final NXentry nxEntry) {
		this.nxEntry = nxEntry;
		this.entryName = entryName;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#add(org.eclipse.dawnsci.nexus.builder.NexusObjectProvider)
	 */
	@Override
	public  N add(NexusObjectProvider nexusObjectProvider) throws NexusException {
		final N nexusObject = nexusObjectProvider.getNexusObject();
		addGroupToNexusTree(nexusObjectProvider, nexusObject);

		return nexusObject;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#getNxEntry()
	 */
	@Override
	public NXentry getNXentry() {
		return nxEntry;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#getEntryName()
	 */
	@Override
	public String getEntryName() {
		return entryName;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#createDefaultData()
	 */
	@Override
	public NexusDataBuilder createDefaultData() {
		final NXdata nxData = NexusNodeFactory.createNXdata();
		nxEntry.setData(nxData);
		return new DefaultNexusDataBuilder(this, nxData);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#newData(java.lang.String)
	 */
	@Override
	public NexusDataBuilder newData(final String name) {
		final NXdata nxData = NexusNodeFactory.createNXdata();
		nxEntry.setData(name, nxData);
		return new DefaultNexusDataBuilder(this, nxData);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#newApplication(org.eclipse.dawnsci.nexus.NexusApplicationDefinition)
	 */
	@Override
	public NexusApplicationBuilder newApplication(NexusApplicationDefinition applicationDefinition) throws NexusException {
		final String appDefName = applicationDefinition.name();
		final String subentryName = appDefName.substring(appDefName.indexOf('_') + 1).toLowerCase() + APPDEF_SUBENTRY_SUFFIX;

		return newApplication(subentryName, applicationDefinition);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#newApplication(java.lang.String, org.eclipse.dawnsci.nexus.NexusApplicationDefinition)
	 */
	@Override
	public NexusApplicationBuilder newApplication(String subentryName,
			NexusApplicationDefinition applicationDefinition)
			throws NexusException {
		final NexusApplicationBuilder appBuilder = DefaultApplicationFactory.getApplicationDefinitionFactory().newApplicationDefinitionModel(
				this, applicationDefinition, subentryName);
		applications.add(appBuilder);

		return appBuilder;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#add(java.util.Collection)
	 */
	@Override
	public List addAll(Collection> nexusObjectProviders) throws NexusException {
		final List nexusObjects = new ArrayList(nexusObjectProviders.size());
		for (final NexusObjectProvider nexusObjectProvider : nexusObjectProviders) {
			final NXobject nexusObject = add(nexusObjectProvider);
			nexusObjects.add(nexusObject);
		}

		return nexusObjects;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#modifyEntry(org.eclipse.dawnsci.nexus.builder.CustomNexusEntryModification)
	 */
	@Override
	public void modifyEntry(CustomNexusEntryModification modification) throws NexusException {
		modification.modifyEntry(nxEntry);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#addMetadata(org.eclipse.dawnsci.nexus.builder.NexusMetadataProvider)
	 */
	@Override
	public void addMetadata(NexusMetadataProvider metadataProvider) throws NexusException {
		final NexusBaseClass category = metadataProvider.getCategory();
		NXobject group;
		if (category == null) {
			group = nxEntry;
		} else {
			group = findGroupForCategory(category);
		}

		final Iterator metadataEntryIterator = metadataProvider.getMetadataEntries();
		while (metadataEntryIterator.hasNext()) {
			final MetadataEntry entry = metadataEntryIterator.next();
			((NXobject) group).setField(entry.getName(), entry.getValue());
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#modifyEntry(org.eclipse.dawnsci.nexus.builder.NexusEntryModification)
	 */
	@Override
	public void modifyEntry(NexusEntryModification modification) throws NexusException {
		if (modification instanceof NexusObjectProvider) {
			add((NexusObjectProvider) modification);
		} else if (modification instanceof NexusMetadataProvider) {
			addMetadata((NexusMetadataProvider) modification);
		} else if (modification instanceof CustomNexusEntryModification) {
			modifyEntry((CustomNexusEntryModification) modification);
		} else {
			throw new IllegalArgumentException("Unknown modification type: " + modification.getClass());
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#modifyEntry(java.util.Collection)
	 */
	@Override
	public void modifyEntry(
			Collection modifications) throws NexusException {
		for (final NexusEntryModification modification : modifications) {
			modifyEntry(modification);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#setInstrumentName(java.lang.String)
	 */
	@Override
	public void setInstrumentName(String instrumentName) {
		nxInstrument.setNameScalar(instrumentName);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#getDataNode(java.lang.String)
	 */
	@Override
	public DataNode getDataNode(String relativePath) throws NexusException {
		final NodeLink nodeLink = nxEntry.findNodeLink(relativePath);
		if (nodeLink == null) {
			throw new NexusException("Cannot find expected data node within the entry with relative path: " + relativePath);
		}
		if (!nodeLink.isDestinationData()) {
			throw new NexusException("Node found was not a data node, relative path within the entry: " + relativePath);
		}

		return (DataNode) nodeLink.getDestination();
	}

	/**
	 * Adds the default groups for the entry. Subclasses may override as appropriate.
	 */
	@Override
	public void addDefaultGroups() {
		// TODO is this correct for all nexus trees we might want to create?
		// how do we configure it? (or just let subclasses override if they want?)
		defaultGroups = new ArrayList<>();
		defaultGroups.add(nxEntry);

		nxInstrument = NexusNodeFactory.createNXinstrument();
		defaultGroups.add(nxInstrument);
		nxEntry.setInstrument(nxInstrument);

		nxSample = NexusNodeFactory.createNXsample();
		defaultGroups.add(nxSample);
		nxEntry.setSample(nxSample);
		
		NXuser nxUser = NexusNodeFactory.createNXuser(); // TODO how to add multiple users?
		defaultGroups.add(nxUser);
		nxEntry.setUser(nxUser);
		
	}

	/* (non-Javadoc)
	 * @see org.eclipse.dawnsci.nexus.builder.NexusEntryBuilder#validate()
	 */
	@Override
	public void validate() throws NexusValidationException {
		for (final NexusApplicationBuilder appDef : applications) {
			appDef.validate();
		}
	}

	/**
	 * Adds the new nexus object to the first skeleton class instance that it
	 * can be added to, unless category is specified, in which case it is added to the first
	 * element of that category that it can be added to.
	 * A special case is where the nexus object is of base class {@link NexusBaseClass#NX_SAMPLE},
	 * in which case this replaces the existing NXsample base class in the nexus tree.
	 * @param nexusObjectProvider
	 * @param nexusObject
	 * @throws NexusException
	 */
	protected  void addGroupToNexusTree(NexusObjectProvider nexusObjectProvider, N nexusObject) throws NexusException {
		if (defaultGroups == null) {
			throw new IllegalStateException("There are no groups to add this element to. defaultGroups() must be invoked on this method before child groups can be added.");
		}

		if (nexusObject.getNexusBaseClass() == NexusBaseClass.NX_SAMPLE) {
			// special case for NXsample, replace the existing skeleton NXsample group
			nxSample = (NXsample) nexusObject;
			nxEntry.removeGroupNode("sample");
			nxEntry.setSample(nxSample);
			defaultGroups.remove(nxSample); // update the default groups list
			defaultGroups.add(nexusObject);
		} else {
			// normal case
			final String name = nexusObjectProvider.getName();
			final NexusBaseClass category = nexusObjectProvider.getCategory();

			// find the parent group
			NXobject parentGroup = null;
			if (category != null) {
				// if a category is specified, the parent group is the first group for this category
				parentGroup = findGroupForCategory(category);
			} else {
				// otherwise the parent group is the first group we can add this type of object to
				for (final NXobject group : defaultGroups) {
					if (group.canAddChild(nexusObject)) {
						parentGroup = group;
						break;
					}
				}
				if (parentGroup == null) {
					throw new NexusException("Cannot find a parent group that accepts a " + nexusObject.getNexusBaseClass());
				}
			}
			
			// if a collection name is specified, get the parent collection - creating it if necessary
			String collectionName = nexusObjectProvider.getCollectionName();
			if (collectionName != null) {
				parentGroup = getCollection(parentGroup, collectionName);
			}

			parentGroup.addGroupNode(name, nexusObject);
		}
	}
	
	private NXcollection getCollection(NXobject group, String collectionName) {
		NXcollection collection = null;
		
		GroupNode collectionGroup = group.getGroupNode(collectionName);
		if (collectionGroup == null) {
			collection = NexusNodeFactory.createNXcollection();
			group.addGroupNode(collectionName, collection);
		} else if (collectionGroup instanceof NXcollection) {
			collection = (NXcollection) collectionGroup;
		} else {
			throw new IllegalArgumentException("Cannot add collection " + collectionName +
					". A child group with that name already exists");
		}

		return collection;
	}

	private NXobject findGroupForCategory(NexusBaseClass category) throws NexusException {
		if (category == NexusBaseClass.NX_ENTRY) {
			return nxEntry;
		}

		for (final NXobject group : defaultGroups) {
			if (category == group.getNexusBaseClass()) {
				return group;
			}
		}

		throw new NexusException("No group found for category " + category);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy