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

org.coos.javaframe.ApplicationSpec Maven / Gradle / Ivy

/**
 * COOS - Connected Objects Operating System (www.connectedobjects.org).
 *
 * Copyright (C) 2009 Telenor ASA and Tellu AS. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 * You may also contact one of the following for additional information:
 * Telenor ASA, Snaroyveien 30, N-1331 Fornebu, Norway (www.telenor.no)
 * Tellu AS, Hagalokkveien 13, N-1383 Asker, Norway (www.tellu.no)
 */
package org.coos.javaframe;

import org.coos.actorframe.application.DomainSpec;
import org.coos.util.serialize.AFClassLoader;
import org.coos.util.serialize.AFSerializer;
import org.coos.util.serialize.HashtableHelper;
import org.coos.util.serialize.StringHelper;

import java.io.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

/**
 * @author geir
 * @author robert
 */
public class ApplicationSpec implements AFSerializer {
    public static byte TRACE_FORMAT_TEXT = 0;
    public static byte TRACE_FORMAT_XML = 1;
	/**
	 * Contains one actor spec for each actor defined in this system. The actor
	 * type is the key
	 */
	private Hashtable actorSpecs;

	/**
	 * Is the name of the application
	 */
	private String appName;

	/**
	 * Specifies if the trace is enabled
	 */
	private boolean traceEnabled = true;
	
	/**
	 * Specifies the format of trace log format. Defaults to TRACE_FORMAT_TEXT for backward compatibility.
	 */
	private byte traceFormat = TRACE_FORMAT_TEXT;

	/**
	 * A short description of the application
	 */
	private String description;

	/**
	 * Specifies the scheduler, threads and which actors should be run for each
	 * domain in this application
	 */
	private DomainSpec domainSpec;

	/**
	 * Router definitions
	 */
	private RouterAddress routerAddress;

	/**
	 * If stru starts the router automactically.
	 */
	private boolean autoStartRouter = false;

	private String routerType = "S";
	/**
	 * The class name for the scheduler to be used in this container. This is
	 * container specific.
	 */
	private String schedulerClass;

	/**
	 * Logfile name
	 */
	private String logFile;

	/*
	 * Validation
	 */
	private boolean error = false;
	private boolean warning = false;
	private boolean validated = false;

	public ApplicationSpec() {
		init();
	}

	public ApplicationSpec(String appName) {
		this.appName = appName;
		init();
	}

	private void init() {
		actorSpecs = new Hashtable();
		routerAddress = new RouterAddress(appName + "/tellu", "telluRouter");

		// insert default domain spec
		// domainSpec = new DomainSpec("default", "ActorDomain");
		if (appName == null) {
			appName = "Tellu";
		}
		logFile = "actorlog.txt";
	}

	public String getRouterType() {
		return routerType;
	}

	public void setRouterType(String routerType) {
		this.routerType = routerType;
	}

	public boolean autoStartRouter() {
		return autoStartRouter;
	}

	public void setAutoStartRouter(boolean autoStartRouter) {
		this.autoStartRouter = autoStartRouter;
	}

	public RouterAddress getRouterAddress() {
		return routerAddress;
	}

	public void setRouterAddress(String name, String type) {
		this.routerAddress = new RouterAddress(name, type);
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}
	
    /**
     * @return the trace format
     */
    public byte getTraceFormat() {
        return traceFormat;
    }

    /**
     * @param traceFormat the traceFormat to set
     */
    public void setTraceFormat(byte traceFormat) {
        this.traceFormat = traceFormat;
    }

    public boolean isTraceEnabled() {
		return traceEnabled;
	}

	public void setTraceEnabled(boolean traceEnabled) {
		this.traceEnabled = traceEnabled;
	}

	public String getLogFile() {
		return logFile;
	}

	public void setLogFile(String logFile) {
		this.logFile = logFile;
	}

	public String getAppName() {
		return appName;
	}

	public void setAppName(String appName) {
		this.appName = appName;
	}

	public Hashtable getActorSpecs() {
		if (actorSpecs == null) {
			return new Hashtable();
		} else {
			return actorSpecs;
		}
	}

	public ActorSpec getActorSpec(String actorType) {
		if (actorType != null) {
			return (ActorSpec) actorSpecs.get(actorType);
		}

		return null;
	}

	public ActorSpec getClonedActorSpec(String actorType) {
		if (actorType != null) {
			ActorSpec as = (ActorSpec) actorSpecs.get(actorType);
			return (ActorSpec) as.clone();
		}

		return new ActorSpec();
	}

	public void setDomainActor(String domainId, String actorType, String className) {
		DomainSpec ds = new DomainSpec(domainId, actorType);
		SchedulerSpec cs = new SchedulerSpec();
		cs.setId(domainId);
		cs.addActorType(actorType);
		ds.addSchedulerSpec(cs);
		addActorSpec(actorType, className);
		domainSpec = ds;
	}

	public DomainSpec getDomainSpec() {
		return domainSpec;
	}

	public void setDomainSpec(DomainSpec ps) {
		domainSpec = ps;
	}

	public void addActorSpec(ActorSpec actorSpec) {
		if (actorSpecs == null) {
			actorSpecs = new Hashtable();
		}

		if (actorSpec.getActorType() == null) {
			throw new ActorFrameException("ACTOR TYPE in ActorSpec is NULL. ActorSpec: " + actorSpec);
		}

		actorSpecs.put(actorSpec.getActorType(), actorSpec);
	}

	public void addActorSpec(String actorType, String classname) {
		addActorSpec(new ActorSpec(actorType, classname));
	}

	public void removeActorSpec(String actorType) {
		if (actorSpecs.containsKey(actorType)) {
			actorSpecs.remove(actorType);
			System.out.println("ApplicationSpec.removeActorSpecs: AppDesc for " + actorType + "removed");
		}
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("\nAPPLICATION SPEC: " + appName);
		sb.append("\n\nTRACE: " + traceEnabled);
		sb.append("\n\nDESCRITION: " + traceEnabled);
		if (description != null) {
			sb.append("\n   " + description);
		}
		sb.append("\n\nDOMAIN SPEC: " + domainSpec.toString());
		sb.append("ACTOR SPECS: ");
		Enumeration en = actorSpecs.elements();
		while (en.hasMoreElements()) {
			ActorSpec as = (ActorSpec) en.nextElement();
			sb.append("\n" + as.toString());

		}

		return sb.toString();

	}

	public Enumeration getPartSpecs() {
		return actorSpecs.elements();
	}

	public Enumeration getActorTypes() {
		return actorSpecs.keys();
	}

	public String getSchedulerClass() {
		return schedulerClass;
	}

	public void setSchedulerClass(String schedulerClass) {
		this.schedulerClass = schedulerClass;
	}

	public void removeActorSpecs(String actorDomain) {
		// todo
	}

	/**
	 * This function must implement the serialization of the object.
	 * 
	 * @return a byte array with the objects data
	 * @throws java.io.IOException
	 */
	public byte[] serialize() throws IOException {
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(bout);
		dout.write(HashtableHelper.persist(actorSpecs));
		dout.write(StringHelper.persist(appName));
		dout.write(StringHelper.persist(description));
		dout.write(StringHelper.persist(schedulerClass));
		dout.flush();

		return bout.toByteArray();
	}

	/**
	 * Use this function for resurrection of the object
	 * 
	 * @param data
	 *            The serialized data containing the object data
	 * @throws java.io.IOException
	 */
	public ByteArrayInputStream deSerialize(byte[] data, AFClassLoader cl) throws IOException {
		ByteArrayInputStream bin = new ByteArrayInputStream(data);
		DataInputStream din = new DataInputStream(bin);

		actorSpecs = HashtableHelper.resurrect(din, cl);
		appName = StringHelper.resurrect(din);
		description = StringHelper.resurrect(din);
		schedulerClass = StringHelper.resurrect(din);

		return bin;
	}

	public boolean containsError() {
		if (!validated) {
			validateAppSpec();
		}
		return error;
	}

	public boolean containsWarning() {
		if (!validated) {
			validateAppSpec();
		}
		return warning;
	}

	/**
	 * Validate the application spec for semantic errors. All actor types is
	 * tested for corrected parts and connectors.
	 * 
	 * @return string with error and warning messages
	 */

	public String validateAppSpec() {
		StringBuffer sb = new StringBuffer("\n\nVALIDATION OF APPLICATION SPEC: \n");

		StringBuffer errors = new StringBuffer();
		StringBuffer warnings = new StringBuffer();
		StringBuffer info = new StringBuffer();
		warning = false;
		error = false;

		if (appName == null || appName.length() == 0) {
			warnings.append("\tNo application name\n");
			warning = true;
		}

		if (getRouterAddress() == null) {
			warnings.append("\tNo router address\n");
			warning = true;
		}

		if (getDomainSpec() == null) {
			warnings.append("No domain spec defined. Default actor ActorDomain is used\n");
			warning = true;
		}

		if (getActorSpecs().isEmpty()) {
			warnings.append("\tNo Actors are defined.\n");
			warning = true;

		} else {
			// validate the actor types

			Enumeration en = actorSpecs.elements();
			while (en.hasMoreElements()) {
				ActorSpec as = (ActorSpec) en.nextElement();
				// validate the part description
				String actor = "\tActor: " + as.getActorType();
				info.append("Actor: " + as.getActorType());
				info.append(" " + as.getActorClassName());
				Vector parts = as.getPartDesc();
				boolean ok = true;
				for (int i = 0; i < parts.size(); i++) {
					PartSpec ps = (PartSpec) parts.elementAt(i);
					String rt = ps.getRoleType();
					ActorSpec ras = getActorSpec(rt);
					String str = actor + "\tPart: " + ps.getRoleType();
					// test if part name is not defined
					if (ras == null) {
						errors.append(str + ":\tIllegal part name\n");
						ok = false;
					}
					// test instance range
					if (ps.getHigh() < ps.getLow() || ps.getHigh() == 0) {
						errors.append(str + ":\tIllegal instance range [" + ps.getLow() + "," + ps.getHigh() + "]\n");
						ok = false;
					}

					error = error || !ok;
				}

				// test connector descriptions

				Vector connectors = as.getConnectorDesc();
				ok = true;
				for (int i = 0; i < connectors.size(); i++) {
					ConnectorSpec cs = (ConnectorSpec) connectors.elementAt(i);
					String who = "\tfrom";
					String str = actor + "\tConnector name: " + cs.getName() + who;

					// Check to address
					String portName = cs.getFrom().getActorPort();

					String type = cs.getFrom().getActorType();
					String instance = cs.getFrom().getActorID();
					if (type == null || getActorSpec(type) == null) {
						errors.append(str + ":\tIllegal actor type: " + type + "\n");
						ok = false;
					} else {
						if (portName != null) {
							ActorSpec spec = getActorSpec(type);
							// check the port name
							if (spec == null || !spec.containsPortName(portName)) {
								errors.append(str + ":\tIllegal port name: " + portName + " for type: " + type + "\n");
								ok = false;
							}
						}
						// check the instance name
						if (instance != null && instance.length() > 0) {
							PartSpec partSpec = as.getPartSpec(type);
							if (partSpec == null || !partSpec.containsInstance(instance)) {
								errors.append(str + ":\tIllegal instance name: " + instance + " for type: " + type
										+ "\n");
								ok = false;
							}
						}

					}

					// Check from address
					who = "\tTo";
					portName = cs.getTo().getActorPort();
					type = cs.getTo().getActorType();
					instance = cs.getTo().getActorID();

					if (type == null || getActorSpec(type) == null) {
						errors.append(str + ":\tIllegal actor type: " + type + "\n");
						ok = false;
					} else {
						if (portName != null) {
							ActorSpec spec = getActorSpec(type);
							if (spec == null || !spec.containsPortName(portName)) {
								errors.append(str + ":\tIllegal port name: " + portName + " for type: " + type + "\n");
								ok = false;
							}
						}
						// check the instance name
						if (instance != null && instance.length() > 0) {
							PartSpec partSpec = as.getPartSpec(type);
							if (partSpec == null || !partSpec.containsInstance(instance)) {
								errors.append(str + ":\tIllegal instance name: " + instance + " for type: " + type
										+ "\n");
								ok = false;
							}
						}
					}

					error = error || !ok;

				}

				info.append(ok ? " OK" : " ERROR");
				info.append("\n");
			}
		}

		if (error)
			sb.append("\nERRORS:\n" + errors);
		if (warning)
			sb.append("\nWARNINGS:\n" + warnings);

		sb.append("INFO:\n" + info);
		validated = true;
		return sb.toString();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy