void MindRegionDef::createFromXml( Xml xml ) {
	// attributes are properties
	id = xml.getAttribute( "id" );
	Object::setInstance( id );

	logger.logDebug( "define region id=" + id + "..." );

	typeName = xml.getAttribute( "type" );
	serviceName = xml.getAttribute( "service" );
	size = xml.getIntAttribute( "size" , 0 );

	String roleName = xml.getAttribute( "role" );

	if( roleName.equals( "processor" ) )
		role = MIND_REGION_ROLE_PROCESSOR;
	else if( roleName.equals( "relay" ) )
		role = MIND_REGION_ROLE_RELAY;
	else if( roleName.equals( "sensory" ) )
		role = MIND_REGION_ROLE_SENSORY;
	else if( roleName.equals( "sympathetic" ) )
		role = MIND_REGION_ROLE_SYMPATHETIC;
	else if( roleName.equals( "parasympathetic" ) )
		role = MIND_REGION_ROLE_PARASYMPATHETIC;
	else if( roleName.equals( "flexor" ) )
		role = MIND_REGION_ROLE_FLEXOR;
	else if( roleName.equals( "extensor" ) )
		role = MIND_REGION_ROLE_EXTENSOR;
	else
		ASSERTFAILED( "Invalid role of region id=" + id + ", role=" + roleName );
}
void MindLocalCircuitConnectionDef::createFromXml( Xml xml ) {
	// attributes are properties
	typeName = xml.getAttribute( "type" );

	primary = xml.getBooleanAttribute( "primary" , false );
	srcRegion = xml.getAttribute( "src" );
	dstRegion = xml.getAttribute( "dst" );

	Object::setInstance( srcRegion + "-" + dstRegion );
}
void MindRegionTypeDef::createFromXml( Xml xml ) {
	if( !xml.exists() )
		return;

	// attributes
	name = xml.getAttribute( "name" );
	Object::setInstance( name );

	implementation = xml.getAttribute( "implementation" );

	// childs
	createConnectorSetFromXml( xml );
}
void XmlSpinalCordLayout::load( Xml xmlDiv ) {
	Xml layout = xmlDiv.getFirstChild( "layout" );
	ASSERTMSG( layout.exists() , "layout is not found" );

	imgSrc = layout.getAttribute( "imgsrc" , "" );

	for( Xml xmlChild = layout.getFirstChild( "level" ); xmlChild.exists(); xmlChild = xmlChild.getNextChild( "level" ) ) {
		String id = xmlChild.getAttribute( "id" );
		MapStringToClass<StringList>& levelData = data.getRef( id );

		loadLevel( xmlChild , levelData );
	}
}
void XmlBrainTractPath::load( Xml xml ) {
	id = xml.getAttribute( "id" );
	type = xml.getAttribute( "type" );
	function = xml.getAttribute( "function" );
	pathway = xml.getAttribute( "pathway" );

	String src = xml.getAttribute( "src" );
	String dst = xml.getAttribute( "dst" );
	String mids = xml.getAttribute( "mids" , "" );

	items.add( src );
	StringList midlist;
	mids.split( midlist , "," );
	items.add( &midlist );
	items.add( dst );

	tract.addPath( this );

	String fibersvalue = xml.getAttribute( "fibers" );
	fibersvalue.split( fibers , "," );
	String value = xml.getAttribute( "endings" );
	value.split( endings , "," );

	for( Xml xmlChild = xml.getFirstChild( "path" ); xmlChild.exists(); xmlChild = xmlChild.getNextChild( "path" ) ) {
		XmlBrainTractPath *path = new XmlBrainTractPath( tract , this );
		path -> load( xmlChild );
		childs.add( path -> id , path );
	}
}
Xml AdminApiSocket::execute( Xml req ) {
    ASSERTMSG( connected , "Not connected" );

    // get request ID
    String requestId = req.getAttribute( "requestId" , "" );
    if( requestId.isEmpty() )
        requestId = setXmlRequestId( req );
    String request = req.serialize();

    bool disconnected = false;
    protocol.writeMessage( socket , request , disconnected );
    if( disconnected )
        connected = false;
    ASSERTMSG( connected , "Connection is closed from server side while making request" );

    String response;
    if( !protocol.readMessage( socket , response , true , disconnected ) ) {
        if( disconnected )
            connected = false;
        ASSERTMSG( connected , "Connection is closed from server side while reading response" );
        ASSERTFAILED( "Timeout while waiting response for request=" + requestId );
        return( Xml() );
    }

    Xml xml = Xml::read( response , "xmlcallresult" );
    return( xml );
}
void MindAreaInfo::createFromXml( Xml xml )
{
	// attributes are properties
	areaId = xml.getAttribute( "id" );

	int x , y , z;
	x = xml.getIntProperty( "posX" );
	y = xml.getIntProperty( "posY" );
	z = xml.getIntProperty( "posZ" );
	location.setPosition( x , y , z );

	int dx , dy , dz;
	dx = xml.getIntProperty( "sizeX" );
	dy = xml.getIntProperty( "sizeY" );
	dz = xml.getIntProperty( "sizeZ" );
	location.setDimensions( dx , dy , dz );

	size = location.getSize();

	// child elements are MindLink
	for( Xml xmlChild = xml.getFirstChild( "MindLink" ); xmlChild.exists(); xmlChild = xmlChild.getNextChild( "MindLink" ) ) {
		// construct MindArea from attributes
		MindLinkInfo *info = new MindLinkInfo;
		info -> createFromXml( xmlChild );

		// add
		links.add( info );
	}
}
void TargetRegionDef::defineEffectorRegion( Xml xml ) {
	MindRegionDef::id = xml.getAttribute( "id" );
	MindRegionDef::target = true;
	MindRegionDef::sensor = false;

	Object::setInstance( MindRegionDef::id );

	MindRegionDef::role = MIND_REGION_ROLE_TARGETEFFECTOR;
	MindRegionDef::size = xml.getIntAttribute( "size" , 0 );

	// region type for effector is the same as region itself
	TargetRegionTypeDef *regionTypeInfo = new TargetRegionTypeDef();
	regionTypeInfo -> defineEffectorRegionType( this , xml );
	MindRegionDef::type = regionTypeInfo;
	MindRegionDef::typeName = regionTypeInfo -> getName();
	MindRegionDef::serviceName = xml.getAttribute( "service" );
}
void MindConnectionTypeDef::createFromXml( Xml xml ) {
	// attributes
	name = xml.getAttribute( "name" );
	Object::setInstance( name );

	srcRegionType = xml.getAttribute( "regionsrc" );
	dstRegionType = xml.getAttribute( "regiondst" );

	// links
	for( Xml xmlChild = xml.getFirstChild( "link-type" ); xmlChild.exists(); xmlChild = xmlChild.getNextChild( "link-type" ) ) {
		// construct MindArea from attributes
		MindConnectionLinkTypeDef *link = new MindConnectionLinkTypeDef( this );
		link -> createFromXml( xmlChild );
		links.add( link );
		linkMap.add( link -> getName() , link );
	}
}
void XmlSpinalCordLayout::loadLevel( Xml xmlLevel , MapStringToClass<StringList>& levelData ) {
	for( Xml xmlChild = xmlLevel.getFirstChild( "lamina" ); xmlChild.exists(); xmlChild = xmlChild.getNextChild( "lamina" ) ) {
		String id = xmlChild.getAttribute( "id" );
		String elements = xmlChild.getAttribute( "elements" );

		StringList& items = levelData.getRef( id );
		StringList parts;
		elements.split( parts , "," );
		for( int k = 0; k < parts.count(); k++ ) {
			String element = parts.get( k );
			ASSERTMSG( hmind -> getIndexedElement( element ) != NULL , "unknown element index=" + element );

			if( items.find( element ) < 0 )
				items.add( element );
		}
	}
}
void MindCircuitDef::createFromXml( Xml xml ) {
	// attributes are properties
	id = xml.getAttribute( "id" );
	name = xml.getAttribute( "name" );
	Object::setInstance( name );

	enabled = xml.getBooleanAttribute( "enabled" , true );
	if( !enabled )
		return;

	// read connections
	for( Xml xmlChild = xml.getFirstChild( "connection" ); xmlChild.exists(); xmlChild = xmlChild.getNextChild( "connection" ) ) {
		// construct MindArea from attributes
		MindCircuitConnectionDef *connection = new MindCircuitConnectionDef( this );
		connection -> createFromXml( xmlChild );
		connections.add( connection );
	}
}
void MindAreaDef::createFromXml( Xml xml ) {
	// attributes are properties
	areaId = xml.getAttribute( "id" );
	areaType = xml.getAttribute( "type" );
	areaName = xml.getAttribute( "name" );
	areaFunction = xml.getAttribute( "function" );
	Object::setInstance( areaId );

	enabled = xml.getBooleanAttribute( "enabled" , true );
	if( !enabled )
		return;

	// read regions
	for( Xml xmlChild = xml.getFirstChild( "region" ); xmlChild.exists(); xmlChild = xmlChild.getNextChild( "region" ) ) {
		// construct MindArea from attributes
		MindRegionDef *region = new MindRegionDef( this );
		region -> createFromXml( xmlChild );
		regions.add( region );
		regionMap.add( region -> getId() , region );
	}
}
void AdminApiSocket::send( Xml req ) {
    ASSERTMSG( connected , "Not connected" );

    // get request ID
    String requestId = req.getAttribute( "requestId" , "" );
    if( requestId.isEmpty() )
        requestId = setXmlRequestId( req );
    String request = req.serialize();

    bool disconnected = false;
    protocol.writeMessage( socket , request , disconnected );
    if( disconnected )
        connected = false;
    ASSERTMSG( connected , "Connection is closed from server side while making request" );
}
void MindMap::createCircuitDefSet( Xml xml ) {
	if( !xml.exists() )
		return;

	// check using another file
	EnvService *es = EnvService::getService();
	String xmlFile = xml.getAttribute( "xmlfile" , "" );
	if( !xmlFile.isEmpty() )
		xml = es -> loadXml( xmlFile );

	for( Xml xmlChild = xml.getFirstChild( "circuit" ); xmlChild.exists(); xmlChild = xmlChild.getNextChild( "circuit" ) ) {
		// construct MindArea from attributes
		MindCircuitDef *circuit = new MindCircuitDef;
		circuit -> createFromXml( xmlChild );
		mindCircuitSet.add( circuit );
		mindCircuitMap.add( circuit -> getName() , circuit );
	}
}
Xml Xml::findChildByPathAttr( String path , String attr , String value ) {
	Xml xml = findChildByPath( path );
	if( !xml.exists() )
		return( xml );

	String key;
	int index = path.findLast( '/' );
	if( index < 0 )
		key = path;
	else
		key = path.getMid( index + 1 );

	while( xml.exists() ) {
		if( xml.getAttribute( attr , "" ).equals( value ) )
			return( xml );

		xml = xml.getNextChild( key );
	}
	return( xml );
}
void ScenarioPlayer::playSignal( Xml cmd ) {
    // find target connector
    MindService *ms = MindService::getService();

    String name = cmd.getAttribute( "name" );
    String component = cmd.getProperty( "component" );
    String connector = cmd.getProperty( "connector" );

    MindRegion *region = ms -> getMindRegion( component );
    ASSERTMSG( region != NULL , "unknown region=" + component );

    NeuroLinkTarget *target = region -> getNeuroLinkTarget( connector );
    if( connector == NULL )
        return;

    NeuroSignal *signal = new NeuroSignal();
    static int z = 0;
    signal -> setId( String( "TM" ) + (++z) );
    logger.logInfo( "send signal name=" + name + " to component=" + component + ", connector=" + connector + ", signal id=" + signal -> getId() + " ..." );
    NeuroSignalSet *set = target -> execute( NULL , signal );
    if( set == NULL ) {
        logger.logDebug( signal -> getId() + ": there are no derived signals from signal id=" + signal -> getId() );
        return;
    }

    // define IDs
    ClassList<NeuroSignal>& signals = set -> getSignals();
    for( int k = 0; k < signals.count(); k++ ) {
        NeuroSignal *signalExecuted = signals.get( k );
        signalExecuted -> setId( signal -> getId() + ".S" + (k+1) );
    }

    // follow links
    MindArea *area = region -> getArea();
    area -> followLinks( signal -> getId() , region , set );
    set -> destroy();
}
void MindGlobalCircuitRegionDef::createFromXml( Xml xml ) {
	id = xml.getAttribute( "id" );
	role = xml.getAttribute( "role" );
}