TypeScript Templates External_System - samchon/framework GitHub Wiki

External System

Module External System provides interfaces for interaction with external network systems.

References

Conceptual Diagram

Conceptual Diagram

Class Diagram

Protocol - External System

API Documents

Source Codes

Basic Classes

ExternalSystemArray

An array and manager of external system drivers, ExternalSystem objects.

ExternalSystemArray is an abstract class contains and manages external system drivers, ExternalSystem objects. Within framework of network, then ExternalSystemArray represents your system and ExternalSystem objects represent external system connected with yours.

You can specify this ExternalSystemArray object to be a server accepting external clients or a client connecting to external servers. Even both of them is also possible.

ExternalSystem

An external system driver.

The ExternalSystem class represents an external system, connected and interact with this sytem. ExternalSystem also takes full charge of network communication with the external system has connected. However, handling Invoke messages in ExternalSystem is not recommended. Replied Invoke message from the external system is shifted to and processed in children elements of this class, ExternalSystemRole objects.

namespace samchon.protocol.external
{
	class ExternalSystem 
		extends protocol.EntityDeque<ExternalSystemRole> 
		implements protocol.IProtocol
	{
		// EXTERNAL_SYSTEM HAS COMMUNICATOR
		private communicator_: protocol.ICommunicator;
		
		public replyData(invoke: protocol.Invoke): void
		{
			// HANDLING REPLIED MESSAGE, IT IS NOT HANDLED IN EXTERNAL_SYSTEM
			// THE INVOKE MESSAGE WILL SHIFTED TO EXTERNAL_SYSTEM_ROLE OBJECTS
			// AND THEY WILL PROCESS THE INVOKE MESSAGE
			for (let i: number = 0; i < this.size(); i++)
				this.at(i).replyData(invoke);
		}
	}
}

ExternalSystemRole

A role belonged to an external system.

The ExternalSystemRole class represents a role, what to do. Extends this class and defines methods handling Invoke message, which are related the specified role, what to do.

ExternalSystemRole can be a Logical Proxy for an ExternalSystem which is containing the ExternalSystemRole. Of course, the ExternalSystemRole is belonged to an ExternalSystem. However, if you access an ExternalSystemRole from an ExternalSystemArray directly, not passing by a belonged ExternalSystem, and send an Invoke message even you're not knowing which ExternalSystem is related in, the ExternalSystemRole acted a role of proxy.

With the Logical Proxy, you can only concentrate on ExternalSystemRole itself, what to do with Invoke messages, irrespective of the ExternalSystemRole is belonged to which ExternalSystem object. Those pattern is called Proxy Pattern.

/// <reference types="samchon-framework.d.ts" />

import samchon = require("samchon-framework");
import protocol = samchon.protocol;
import external = samchon.templates,external;

//--------
// MANAGER OF EXTERNAL FILE SERVERS' DRIVERS
//--------
var file_servers: external.ExternalSystemArray;

var png_data: Uint8Array; // DATA TO SAVE
var invoke: protocol.Invoke = new protocol.Invoke("save", "my_picture", "png", png_data); 
	// MESSAGE TO SEND

//--------
// YOU CAN SEND AN INVOKE MESSAGE WITHOUT SPECIFYING TARGET SYSTEM
// THE ExternalSystemRole OBJECT WILL ACT A ROLE NAMED "PROXY"
//--------
file_servers.getRole("image").sendData(invoke);

Proxy Pattern

The ExternalSystemArray class can use the Proxy Pattern. In framework within developer, which external system is being connected or which external system can do something, it's not important. Only interested in developer's perspective is which can be done. Another word:

By using the logical proxy, developer doesn't need to know which ExternalSystemRole is belonged to which ExternalSystem. Just access to an ExternalSystemRole via ExternalSystemArray. Sending and replying Invoke messages, process them in the ExternalSystemRole object. The ExternalSystemRole objects will subrogate Invoke message I/O instead of related ExternalSystem object.

ExternalSystemArray has accessors to ExternalSystemRole objects.
namespace samchon.protocol.external
{
	abstract class ExternalSystemArray 
		extends protocol.EntityDequeCollection<ExternalSystem> 
		implements protocol.IProtocol
	{
		// ACCESSORS TO EXTENRAL_SYSTEM_ROLE OBJECTS
		public hasRole(name: string): boolean;
		public getRole(name: string): ExternalSystemRole;
	}
}
ExternalSystemRole can subrogate Invoke message I/O.
namespace samchon.protocol.external
{
	abstract class ExternalSystemRole implements protocol.IProtocol
	{
		// LINKED WITH EXTENRAL_SYSTEM OBJECT.
		private system: ExternalSystem;

		public sendData(invoke: protocol.Invoke): void
		{
			// YOU CAN SEND INVOKE MESSAGE 
			// VIA THIS EXTENRAL_SYSTEM_ROLE OBJECT
			this.system.sendData(invoke);
		}

		// ExternalSystem.replyData() SHIFTS INVOKE MESSAGE TO 
		// THIS EXTENRAL_SYSTEM_ROLE OBJECT.
		public abstract replyData(invoke: protocol.Invoke): void;
	}
}
An example sending Invoke message via Proxy Pattern.
/// <reference types="samchon-framework.d.ts" />

import samchon = require("samchon-framework");
import protocol = samchon.protocol;
import external = samchon.templates,external;

//--------
// MANAGER OF EXTERNAL FILE SERVERS' DRIVERS
//--------
var file_servers: external.ExternalSystemArray;

var png_data: Uint8Array; // DATA TO SAVE
var invoke: protocol.Invoke = new protocol.Invoke("save", "my_picture", "png", png_data); 
	// MESSAGE TO SEND

//--------
// YOU CAN SEND AN INVOKE MESSAGE WITHOUT SPECIFYING TARGET SYSTEM
// THE ExternalSystemRole OBJECT WILL ACT A ROLE NAMED "PROXY"
//--------
file_servers.getRole("image").sendData(invoke);

Derived Classes

ExternalSystemArray

You can specify an ExternalSystemArray object to be:

ExternalClientArray

You can specify an ExternalSystemArray object to be a server accepting external clients. Just extends ExternalClientArray and override two methods; createServerBase() and createExternalClient().

Do you remember that; the easiest way to defining a server is to extending protocol.Server. However, if extending protocol.Server is impossible becuase the target class already extended another one, then you can use protocol.IServerBase object with implementing protocol.IServer. ExternalClientArray.createServerBase() is a factory method creating the protocol.IServerBase object. Override the ExternalClientArray.createServerBase() method and return one of them considering which protocol is used in the server:

ExternalClientArray.createExternalClient() is a factory method creating ExternalSystem object. This is called by IServer.addClient() whenever an external client has connected. Override the creatExternalClient() method and return specified type of ExternalSystem.

IExternalClientArray

The easiest way to defining an ExternalSystemArray class opening a server and accept external clients is to extending the ExternalClientArray class. However, if you can't specify your derived ExternalSystemArray to be server, client or both of them, then make an abstract class extending ExternalSystemArray (Now, I name it BaseSystemArray). When you need a BaseSystemArray class opening a server and accepting external clients, make a new class to extening the BaseSystemArray and implements IExternalClientArray (Name it BaseClientArray). Fill the BaseClientArray following below code:

namespace samchon.templates.external
{
	export interface IExternalClientArray 
		extends ExternalSystemArray, IServer
	{
	}
	
	export abstract class ExternalClientArray
		extends ExternalSystemArray
		implements IExternalClientArray
	{
		private server_base: IServerBase = null;
		
		//--------
		// METHODS TO OVERRIDE
		//--------
		// FACTORY METHOD CREATING SERVER_BASE OBJECT
		// RETURN ONE OF THEM FOLLOWING SPECIFIED PROTOCOL
		// 	- ServerBase
		// 	- WebServerBase
		// 	- SharedWorkerServerBase
		protected abstract createServerBase(): IServerBase;
		
		// FACTORY METHOD CREATING EXTERNAL_SYSTEM OBJECT
		protected abstract createExternalClient(driver: IClientDriver): ExternalSystem;
		
		//--------
		// METHODS OF ISERVER -> HOOK TO SERVER_BASE OBJECT
		//--------
		public open(port: number): void
		{
			this.server_base = this.createServerBase();
			this.server_base.open(port);
		}
		public close(): vcid
		{
			this.server_base.close();
		}
		public addClient(driver: IClientDriver): void
		{
			let system: ExternalSystem = this.createExternalClient(driver);
			this.push_back(system);
		}
	}
}
ExternalServerArray

You can specify an ExternalSystemArray object to be a client connecting to external servers. Just extends ExternalServerArray and override only a method; createChild() who makes child IExternalServer object via XML.

If you already read Entity module, then you may know that; IEntityGroup.createChild() is a factory method creating a child object via XML message called by IEntityGroup.construct(). A client connecting to external servers; the word means that my system (ExternalServerArray) knows ip addresses and port numbers to connect. They are already being specified. Thus storing the ip addresses and port nubmers to an XML document construct ExternalServerArray from the XML message is possible.

/// <reference path="typings/samchon-framework/samchon-framework.d.ts" />

import samchon = require("samchon-framework");
import library = samchon.library;
import protocol = samchon.protocol;
import external = samchon.templates.external;

class FileServerArray extends external.ExternalServerArray
{
	public createChild(xml: library.XML): protocol.external.ExternalServer
	{
		let name: string = xml.getProperty("name");
		
		if (name == "document")
			return DocumentServer(this);
		else if (name == "image")
			reutrn ImageServer(this);
		else if (name == "video")
			return VideoServer(this);
		else
			return null;
	}
}

// AN XML MESSAGE STORING ADDRESSES OF EXTERNAL SERVERS TO CONNECT
var xml: library.XML = new library.XML
(
	"<systemArray>\n" +
	"	<system name='document' ip='192.168.0.202' port='17112' />\n" +
	"	<system name='image' ip='192.168.0.203' port='17112' />\n" +
	"	<system name='document' ip='192.168.0.204' port='17112' />\n" +
	"</systemArray>"
);

// CREATE EXTERENAL_SERVER_ARRAY
var file_servers: FileServerArray = new FileServerArray();

// CONSTRUCT EXTERNAL_SERVER OBJECTS VIA THE XML MESSAGE
file_servers.construct(xml);

// START CONNECTION
file_servers.connect();
IExternalServerArray

The easiest way to defining an ExternalSystemArray class who is a client connecting to external servers is to extending the ExternalServerArray class. However, if you can't specify your derived ExternalSystemArray to be server, client or both of them, then make an abstract class extending ExternalSystemArray (Now, I name it BaseSystemArray). When you need a BaseSystemArray class to be a client connecting to external servers, make a new class to extening the BaseSystemArray and implements IExternalServerArray (Name it BaseServerArray). Fill the BaseServerArray following below code:

namespace samchon.protocol.external
{
	export interface IExternalServerArray
		extends ExternalSystemArray
	{
		// MAY CALL CHILDREN IExternalServer.connect() METHODS
		connect(): void;
	}
	
	export abstract class ExternalServerArray
		extends ExternalSystemArray
	{
		// VERY SIMPLE. JUST CALL CHILDREN IExternalServer.connect()
		public connect(): void
		{
			for (let i: number = 0; i < this.size(); i++)
				(this.at(i) as IExternalServer).connect();
		}
	}
}
ExternalServerClientArray

You can specify an ExternalSystemArray object to be a server accepting external clients and a client connecting to external servers at the same timee by just extending ExternalServerClientArray. Extending the ExternalServerClientArray, you can take functions of ExternalServerArray and ExternalClientArray. Repeat again; ExternalServerClientArray can do what ExternalServerArray and ExternalClientArray at the same time. Thus, ExternalServerClientArray needs to override methods from ExternalServerArray and ExternalClientArray, too. Override those methods:

/// <reference types="samchon-framework" />

import samchon = require("samchon-framework");
import protocol = samchon.protocol;

class MyExternalServerClientArray 
	extends protocol.external.ExternalServerClientArray
{
	//--------
	// METHODS OF EXTERNAL_CLIENT_ARRAY
	//--------
	protected createServerBase(): protocol.IServerBase
	{
		return new protocol.WebServerBase(this);
	}
	protected createExternalClient(driver: protocol.IClientDriver): protocol.external.ExternalSystem
	{
		return new MyExternalClient(this, driver);
	}
	
	//--------
	// METHOD OF EXTERNAL_SERVER_ARRAY
	//--------
	protected createExternalServer(): protocol.external.IExternalServer
	{
		return new MyExternalServer(this);
	}
}
IExternalServerClientArray

As I've mentioned in IExternalClientArrat and IExternalServerArray, the easiest way to defining an ExternalSystemArray class opening a server and accept external clients and connecting to external servers at the same time is to extending the ExternalServerClientArray class. However, if you can't specify your derived ExternalSystemArray to be server, client or both of them, then make an abstract class extending ExternalSystemArray (Now, I name it BaseSystemArray). When you need a BaseSystemArray class opening a server and accepting external clients and connecting to external servers at the same time, make a new class to extening the BaseSystemArray and implements IExternalClientArray and IExternalServerArray (Name it BaseServerClientArray). Fill the BaseServerClientArray following below codes:

If you already made a class implementing IExternalClientArray, then extends the class and just implements IExternalServerArray additionally. Of course, filling methods of the IExternalServerArray is required.

namespace samchon.protocol.external
{
	export abstract class ExternalServerClientArray
		extends ExternalClientArray // a server accepting external clients
		implements IExternalServerArray // a client connecting to external servers
	{
		//--------
		// A METHOD TO OVERRIDE
		//--------
		// FACTORY METHOD CREATING EXTERNAL_SERVER OBJECT VIA XML
		protected createExternalServer(xml: library.XML): IExternalServer;
	
		//--------
		// METHODS OF EXTERNAL_SERVER_ARRAY
		//--------
		// SHIFT FACTORY METHOD TO CREATE_EXTERNAL_SERVER
		public createChild(xml: library.XML): IExternalServer
		{
			return this.createExternalServer(xml);
		}
		
		// WHEN CHILD IS A TYPE OF IExternalServer,
		// THEN CALL IExternalServer.connect()
		public connect(): void
		{
			for (let i: number = 0; i < this.size(); i++)
				if (this.at(i)["connect"] != undefined)
					(this.at(i) as IExternalServer).connect();
		}
	}
}

Otherwise, you haven't made a class implementing the IExternalClientArray interface, then extends ExternalSystemArray and implements two interfaces, IExternalClientArray and IExternalServerArray. Make such class referencing below code:

namespace samchon.protocol.external
{
	export abstract class ExternalServerClientArray
		extends ExternalSystemArray
		implements IExternalClientArray, IExternalServerArray
	{
		private server_base: IServerBase = null;
		
		//--------
		// METHODS TO OVERRIDE
		//--------
		// FACTORY METHOD CREATING SERVER_BASE OBJECT
		// RETURN ONE OF THEM FOLLOWING SPECIFIED PROTOCOL
		// 	- ServerBase
		// 	- WebServerBase
		// 	- SharedWorkerServerBase
		protected abstract createServerBase(): IServerBase;
		
		// FACTORY METHOD CREATING EXTERNAL_SYSTEM OBJECT
		protected abstract createExternalClient(driver: IClientDriver): ExternalSystem;
		
		// FACTORY METHOD CREATING EXTERNAL_SERVER OBJECT VIA XML
		protected createExternalServer(xml: library.XML): IExternalServer;
		
		//--------
		// METHODS OF ISERVER -> HOOK TO SERVER_BASE OBJECT
		//--------
		public open(port: number): void
		{
			this.server_base = this.createServerBase();
			this.server_base.open(port);
		}
		public close(): vcid
		{
			this.server_base.close();
		}
		public addClient(driver: IClientDriver): void
		{
			let system: ExternalSystem = this.createExternalClient(driver);
			this.push_back(system);
		}
		
		//--------
		// METHODS OF EXTERNAL_SERVER_ARRAY
		//--------
		// SHIFT FACTORY METHOD TO CREATE_EXTERNAL_SERVER
		public createChild(xml: library.XML): IExternalServer
		{
			return this.createExternalServer(xml);
		}
		
		// WHEN CHILD IS A TYPE OF IExternalServer,
		// THEN CALL IExternalServer.connect()
		public connect(): void
		{
			for (let i: number = 0; i < this.size(); i++)
				if (this.at(i)["connect"] != undefined)
					(this.at(i) as IExternalServer).connect();
		}
	}
}

ExternalSystem

You can specify an ExternalSystem to be:

ExternalClient

You want to make an ExternalSystem class who handles external client connecting to my server, then just extends the ExternalSystem class and initialize with super.constructor(systemArray: protocol.external.SystemArray, driver: protocol.IClientDriver). The IClientDriver object, it comes from ExternalSystemArray.createExternalClient().

/// <reference types="samchon-framework" />

import samchon = require("samchon-framework");
import protocol = samchon.protocol;

class MyExternalClientArray
	extends protocol.external.ExternalClientArray
{
	protected createServerBase(): protocol.IServerBase
	{
		return new protocol.WebServerBase(this);
	}
	protected createExternalClient(driver: protocol.IClientDriver): protocol.external.ExternalSystem
	{
		return new MyExternalClient(this, driver);
	}
}

class MyExternalClient
	extends protocol.external.ExternalSystem
{
	public constructor(systemArray: MyExternalClientArray, driver: protocol.IClientDriver)
	{
		super(systemArray, driver);
		
		this.push
		(
			new MyExternalClientRole1(this),
			new MyExternalClientRole2(this),
			new MyExternalClientRole3(this)
		);
	}
}
ExternalServer

You can specify an ExternalSystem object who connects to external server. Just extends ExternalServer and overrides two methods; createServerConnector() and createChild().

The createServerConnector() is a factory method creating IServerConnector object. Return one of them considering which protocol is used in the external server.

The createChild() is a factory method creating child ExternalSystemRole object from XML object. Extends ExternalServer class following below code:

/// <reference types="samchon-framework" />

import samchon = require("samchon-framework");
import library = samchon.library;
import protocol = samchon.protocol;

class MyExternalServerArray exnteds protocol.external.ExternalServerArray
{
	public createChild(xml: library.XML): protocol.external.IExternalServer
	{
		return new MyExternalServer(this);
	}
}

class MyExternalServer extends protocol.external.ExternalServer
{
	// FACTORY METHOD CREATING SERVER_CONNECTOR OBJECT
	// RETURN ONE OF THEM FOLLOWING SPECIFIED PROTOCOL
	// 	- ServerConnector
	// 	- WebServereConnector
	// 	- SharedWorkerServeerConnector
	protected createServerConnector(): protocol.IServerConnector
	{
		return new protocol.WebServerConnector(this);
	}
	
	// FACTORY METHOD CREATING EXTERNAL_SYSTEM_ROLE OBJECT
	// THIS IS CALLED BY IEntityGroup.construct() WITH XML MESSAGE
	public createChild(xml: library.XML): protocol.external.ExternalSystemRole
	{
		let name: string = xml.getProperty("name");
		
		if (name == "role1")
			return new MyExternalClientRole1(this);
		else if (name == "role2")
			return new MyExternalClientRole2(this);
		else if (name == "role3")
			return new MyExternalClientRole3(this);
		else
			return null;
	}
}
IExternalServer

The easiest way to defining an ExternalSystem class who connects to external server is to extending the ExternalServer class. However, if you can't specify your derived ExternalSystem is interacting with an external server that I connect or an external client connecting to my system, then make an abstract class extending ExternalSystem (Nowm I am it BaseSystem). When you need a BaseSystem class who connects to external server, make a new class extending the BaseSystem and implements IExternalServer. Fill the BaseServer following below code:

namespace samchon.protocol.external
{
	export interface IExternalServer
		extends ExternalSystem
	{
		// CALLED BY IExternalServerArray.connect()
		connect(): void;
	}
	
	export abstract class ExternalServer
		extends ExternalSystem
		implements IExternalServer
	{
		// IP ADDRESS AND PORT NUMBER TO CONNECT
		protected ip: string = "";
		protected port: number = 0;
	
		//--------
		// METHODS OF IEXTERNAL_SERVER
		//--------
		// FACTORY METHOD CREATING SERVER_CONNECTOR OBJECT
		// RETURN ONE OF THEM FOLLOWING SPECIFIED PROTOCOL
		// 	- ServerConnector
		// 	- WebServereConnector
		// 	- SharedWorkerServeerConnector
		protected abstract createServerConnector(): IServerConnector;
	
		public connect(): void
		{
			// CREATE SERVER_CONNECTOR VIA FACTORY METHOD
			this.communicator = this.createServerConnector();
			
			// AND CONNECT
			(this.communicator as ServerConnector).connect(this.ip, this.port);
		}
	}
}

Derived Modules

Parallel System

Conceptual Diagram

Parallel System Module, it is extended from this External System Module.

On top of the External System Module who indendently separates each role to each system exclusively, Parallel Sysetm module also can do parallel processing. Parallel System Module separates a process to number of pieces and distributes the pieces to its slave systems. The slave systems process the pieces all together.

Go to the Parallel System Module

Distributed System

Conceptual Diagram

Distributed System Moudle, it is extended from the Parallel System Module.

On top of External System Moudle and Parallel System Module, Distributed System Module's system doesn't monopolize a role. The role can be shared in multiple systems. When developer requests to process belonged to a role, then DistributedSystemArray will deliver the role to the most idle slave system.

Go to the Distributed System Module

Slave System

Go to the Slave System Module

Example Project

Derived Modules

The Derived Modules can be very helpful for understanding how to utilize and specify type of classes in this External System module.

Name Source Documents
Parallel System templates/parallel API, Guidance
Distributed System templates/distributed API, Guidance
Slave System templates/slave API, Guidance

Interaction

Conceptual Diagram

Interaction is an example implemented Tree-structured Distributed & Parallel Processing System. The Interaction provides ultimate guidance; how to use External System and its derived modules.

Go to the Interaction