Source: core/kekule.structureBuilder.js

/**
 * @fileoverview
 * Classes and utils to help to build a chemical structure (such as molecule).
 * @author Partridge Jiang
 */

/*
 * requires /lan/classes.js
 * requires /lan/kekule.common.js
 * requires /data/kekule.dataUtils.js
 * requires /core/kekule.elements.js
 * requires /core/kekule.electrons.js
 * requires /core/kekule.structures.js
 */

/**
 * Class to help to build a legal chemical structure.
 * @class
 * @augments ObjectEx
 * @param {Kekule.StructureFragment} target Target object to build.
 *
 * @property {Kekule.StructureFragment} target Target object to build.
 */
Kekule.ChemStructureBuilder = Class.create(ObjectEx,
/** @lends Kekule.ChemStructureBuilder# */
{
	/** @private */
	CLASS_NAME: 'Kekule.ChemStructureBuilder',
	/** @constructs */
	initialize: function($super, target)
	{
		$super();
		if (target)
			this.setTarget(target);
	},
	/** @private */
	initProperties: function()
	{
		this.defineProp('target', {'dataType': 'Kekule.StructureFragment'});
		//this.defineProp('coordMode', {'dataType': DataType.INT, 'defaultValue': Kekule.CoordMode.COORD2D});
	},

	/**
	 * Set coordinates of a node. 2D or 3D will be automatically recognized.
	 * First parameter should be a node, then one or two hash of coordinates can be passed in.
	 * @param {Kekule.ChemStructureNode} node
	 * @param {Hash} coordinates
	 */
	setNodeCoord: function()
	{
		var a = Array.prototype.slice.call(arguments);
		var node = a.shift();
		var coords = a;
		for (var i = 0, l = coords.length; (i < l) && (i < 2); ++i)
		{
			var coord = coords[i];
			if (coord.z !== undefined)  // has z coord, a 3D one
				node.setCoordOfMode(coord, Kekule.CoordMode.COORD3D);
			else
				node.setCoordOfMode(coord, Kekule.CoordMode.COORD2D);
		}
	},

	/**
	 * A generic method to create a new {@link Kekule.ChemStructureNode}.
	 * The first parameter should be the class of node while second to be id of node.
	 * The third and forth parameters should be 2d and 3d coordinates.
	 * @returns {Kekule.ChemStructureNode}.
	 */
	createNode: function()
	{
		var a = Array.prototype.slice.call(arguments);
		var nodeClass = a.shift();
		var id = a.shift();
		var coords = a;
		var result = new nodeClass(id);
		this.setNodeCoord(result, coords);
		this.appendNode(result);
		return result;
	},

	/**
	 * Create a connector between connectedNodes.
	 * @param {Class} connectorClass
	 * @param {String} id Id of connector.
	 * @param {Array} connectedObjs
	 * @returns {Kekule.ChemStructureConnector}
	 */
	createConnector: function(connectorClass, id, connectedObjs)
	{
		var result = new connectorClass(id);
		result.setConnectedObjs(connectedObjs);
		return result;
	},

	/**
	 * Add a node to target structure.
	 * @param {Kekule.ChemStructureNode} node
	 * @returns {Kekule.ChemStructureNode}
	 */
	appendNode: function(node)
	{
		if (node && this.getTarget())
		{
			return this.getTarget().appendNode(node);
		}
		else
			return null;
	},

	/**
	 * Add a connector to target structure.
	 * @param {Kekule.ChemStructureConnector}
	 * @returns {Kekule.ChemStructureConnector}
	 */
	appendConnector: function(connector)
	{
		if (connector && this.getTarget())
		{
			return this.getTarget().appendConnector(connector);
		}
		else
			return null;
	},

	/**
	 * Create an atom object.
	 * First parameter should be id of atom.
	 * Second and third parameters should be elemSymbolOrAtomicNumber and massNumber,
	 * the rest of parameters should be coordinates of atom.
	 * @param {Object} elemSymbolOrAtomicNumber
	 * @param {Object} massNumber
	 */
	createAtom: function()
	{
		var a = Array.prototype.slice.call(arguments);
		var id = a.shift();
		var elemSymbolOrAtomicNumber = a.shift();
		var massNumber = a.shift();

		var result = new Kekule.Atom(id, elemSymbolOrAtomicNumber, massNumber);
		a.unshift(result);
		this.setNodeCoord.apply(this, a);
		this.appendNode(result)
		return result;
	},

	/**
	 * Create a bond berween connectedNodes.
	 * @param {String} id
	 * @param {Array} connectedObjs
	 * @param {Int} bondOrder
	 * @param {Int} bondStereo
	 * @param {String} bondType
	 */
	createBond: function(id, connectedObjs, bondOrder, bondStereo, bondType)
	{
		var result = new Kekule.Bond(id, connectedObjs, bondOrder);
		result.changeBondForm(bondOrder, null, bondType);
		if (bondStereo)
			result.setStereo(bondStereo);
		this.appendConnector(result);
		return result;
	},

	deleteNode: function()
	{

	},

	/**
	 * Group up nodes and turn them into a {@link Kekule.SubGroup}.
	 * @param {Array} groupNodes A set of {@link Kekule.ChemStructureNode}, must in target structure.
	 * @param {String} id of new sub group.
	 * @returns {Kekule.SubGroup}
	 */
	marshalSubGroup: function(groupNodes, id)
	{
		var target = this.getTarget();
		if (target && target.hasCtab())
		{
			var group = new Kekule.SubGroup(id);
			target.marshalSubFragment(groupNodes, group);
			return group;
		}
		else
			return null;
	}
});