text:
package name.heavycarbon.utils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

/* 34567890123456789012345678901234567890123456789012345678901234567890123456789
 *******************************************************************************
 * Date generation
 *
 * TODO: Most of this probably needs to be thrown away.
 *
 * 1999.02.00 - Working on it
 * 1999.10.24 - Uploaded to server
 * 1999.11.10 - FindSQLEscapable() and SQLize() separated into functions for
 *              mSQL and and Interbase; decision is made on SCMSGlobal's
 *              ThisMachine() return value
 * 1999.11.21 - MakeLogFilename() added
 * 1999.11.22 - MakeLogFilename() modified; now takes boolean 'addrandom'
 * 1999.11.25 - Added CoveredP() as system-wide way of 'interval cover'
 * 1999.11.26 - Added TextAMonth()
 * 1999.12.07 - Annoying initialization messages in static() removed
 * 1999.12.12 - FuseVectors() added
 * 2000.04.07 - Modfied naming for logfile
 * 2000.07.21 - Added function for taking apart parameters passed to main()
 * 2001.09.04 - Reformed for m-plify; most of the functions left out at first.
 * 2001.11.20 - Added mangleString()
 * 2001.11.20 - Added the MEDIUM format for writing dates
 * 2001.11.22 - Added verifyStopfile(), testForStopFile(), testWatchdogPort()
 * 2001.11.29 - Added onlyDigitsP()
 * 2002.01.17 - Added texters for Calendar values
 * 2002.01.22 - Added 'cookPolyline()'
 * 2002.03.21 - Added XML-escaping procedures
 * 2003.06.13 - Added setUpAlphaLayoutOnRootLogger()
 * 2004.01.13 - Indent now does a lookup in spaceStrings[]
 * 2004.01.20 - writeVector() reviewed and renamed writeStory()
 * 2004.03.04 - Added facilities for logging Web Requests
 * 2004.04.17 - Modified parseCommaSeparatedAtoms() somewhat
 * 2004.08.05 - scanServices() moved here from PropertiesReader
 * 2004.08.11 - Added loadPropertiesFromResource()
 * 2004.10.19 - Completly ripped apart until only 'date' facilities were left,
 *              then moved to m3p.utils.date and renamed to DateToText
 * 2005.05.02 - Nice weather today. The class becomes an enumeration type
 *              enumerating the different formats. It then exports non-static
 *              but thread-safe formatting methods. One could also add
 *              static one but we don't bother. Using a homegrown 'enumeration
 *              type' eliminates the need for a MAX_FORMAT and MIN_FORMAT.
 * 2005.05.02 - Fused in part of mm3p.utils.divers.DateParserFormatter.
 *              Also texts Times - but that is of course a weakness because
 *              dates are dates and not times. Use LocalTime in preference to
 *              this if you deal with times.
 * 2005.10.18 - Frenchified, i.e. added ALTERNATE 8
 * 2009.01.26 - Moved to m3p_ignition (com.mplify.logging) in the standalone
 *              message server.
 * 2010.12.27 - Added buildDurationStringShort()
 * 2012.01.03 - Added a buildDurationStringShort() that takes a BigDecimal,
 *              for Groovy.
 ******************************************************************************/

@SuppressWarnings({ "unchecked", "rawtypes" })
public class DateTexter {

    /*
     * Trivial timezones
     */

    private final static TimeZone DEFAULT = TimeZone.getDefault();
    private final static TimeZone UTC = TimeZone.getTimeZone("UTC");

    /*
     * Members. The DateToText has a 'name' and formats according to a
     * 'formatText'. The unique "SimpleDateFormat" (to which access is
     * synchronized) is set up with "formatText".
     */

    private final String name;
    private final SimpleDateFormat sdf; // TODO: Should be a per-instance pool,
                                        // not a single instance

    /*
     * Possible format values
     */

    static final public DateTexter COMPLETE;
    static final public DateTexter EXTENDED;
    static final public DateTexter NORMAL;
    static final public DateTexter SHORT;
    static final public DateTexter ALTERNATE0;
    static final public DateTexter ALTERNATE1;
    static final public DateTexter ALTERNATE2;
    static final public DateTexter ALTERNATE3;
    static final public DateTexter ALTERNATE4;
    static final public DateTexter ALTERNATE5;
    static final public DateTexter ALTERNATE6;
    static final public DateTexter ALTERNATE7;
    static final public DateTexter ALTERNATE8;
    static final public DateTexter ALTERNATE9;
    static final public DateTexter TIME0;
    static final public DateTexter TIME1;
    static final public DateTexter TIME2;

    /*
     * An list of the values, public but immutable
     */

    public final static List<DateTexter> LIST;

    /*
     * Static construction takes care to assign unique (and constant) numeric
     * identifiers to the various instances. They must be stable because they
     * are used in the database. At the same time, the values are assigned to
     * the 'list', which will then be made immutable and assigned to LIST.
     */

    static {
        ArrayList<DateTexter> list = new ArrayList();
        list.add(COMPLETE = new DateTexter("complete", "yyyy.MM.dd HH:mm:ss:SSS (EEEE) (zzzz)"));
        list.add(EXTENDED = new DateTexter("extended", "yyyy.MM.dd HH:mm:ss:SSS"));
        list.add(NORMAL = new DateTexter("normal", "yyyy.MM.dd HH:mm:ss"));
        list.add(SHORT = new DateTexter("short", "yyyy.MM.dd"));
        list.add(ALTERNATE0 = new DateTexter("alternate0", "yyyy-MM-dd HH:mm:ss"));
        list.add(ALTERNATE1 = new DateTexter("alternate1", "yyyy-MM-dd HH:mm"));
        list.add(ALTERNATE2 = new DateTexter("alternate2", "yyyy-MM-dd"));
        list.add(ALTERNATE3 = new DateTexter("alternate3", "dd/MM/yyyy HH:mm:ss"));
        list.add(ALTERNATE4 = new DateTexter("alternate4", "dd/MM/yyyy HH:mm"));
        list.add(ALTERNATE5 = new DateTexter("alternate5", "dd/MM/yyyy"));
        list.add(ALTERNATE6 = new DateTexter("alternate6", "yyyy.MM.dd"));
        list.add(ALTERNATE7 = new DateTexter("alternate7", "yyyy_MM_dd_HH_mm_ss"));
        list.add(ALTERNATE8 = new DateTexter("alternate8")); // special, needs
                                                             // more than a
                                                             // simple pattern
        list.add(ALTERNATE9 = new DateTexter("alternate9", "yyyyMMddHHmmss"));
        list.add(TIME0 = new DateTexter("time0", "HH:mm:ss:SSS"));
        list.add(TIME1 = new DateTexter("time1", "HH:mm:ss"));
        list.add(TIME2 = new DateTexter("time2", "HH:mm"));
        LIST = Collections.unmodifiableList(list);
    }

    /**
     * The constructor, can only called by this class. The class defines the
     * possible cases using the constructor and that's it. Constructor is
     * PRIVATE!
     */

    private DateTexter(String name, String formatText) {
        this.name = name;
        this.sdf = new SimpleDateFormat(formatText);
        // formatting always takes place in some timezone; by default, use the
        // 'default' timezone
        // which should be 'local time'
        this.sdf.setCalendar(Calendar.getInstance(TimeZone.getDefault()));
    }

    /**
     * Some don't have a format text
     */

    private DateTexter(String name) {
        this.name = name;
        if ("alternate8".equals(name)) {
            this.sdf = new SimpleDateFormat("d '$MONTH$' yyyy à HH:mm:ss");
        } else {
            throw new IllegalStateException("Can't be called for '" + name + "'");
        }
    }

    /**
     * Create a string for a date expressed in the passed TimeZone. Synchronized
     * so that threads do not mess up the SimpleDateFormat structure when
     * several try to format through this same method. Returns (null) if called
     * with a (null) 'when'. Throws if called with a (null) TimeZone.
     */

    public synchronized String textADate(Date when, TimeZone tz) {
        if (tz == null) {
            throw new IllegalArgumentException("The passed 'time zone' is (null)");
        }
        if (when == null) {
            return "(null)";
        }
        if ("alternate8".equals(name)) {
            final String[] mn = { "janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre" };
            sdf.getCalendar().setTimeZone(tz);
            sdf.getCalendar().setTime(when);
            sdf.getCalendar().get(Calendar.MONTH);
            String template = sdf.format(when);
            return template.replace("$MONTH$", mn[sdf.getCalendar().get(Calendar.MONTH)]);
        } else {
            sdf.getCalendar().setTimeZone(tz);
            return sdf.format(when);
        }
    }

    /**
     * Create a string for a date expressed in the default TimeZone.
     */

    public synchronized String inDefault(Date when) {
        return textADate(when, DEFAULT);
    }

    /**
     * Create a string for a date expressed in UTC.
     */

    public synchronized String inUTC(Date when) {
        return textADate(when, UTC);
    }

    /**
     * Access the 'name'
     */

    public String getName() {
        return name;
    }

    /**
     * An old helper function: Translate the opaque Calendar weekday to a string
     */

    public static String weekdayValueToString(int x) {
        switch (x) {
        case Calendar.MONDAY:
            return "Monday";
        case Calendar.TUESDAY:
            return "Tuesday";
        case Calendar.WEDNESDAY:
            return "Wednesday";
        case Calendar.THURSDAY:
            return "Thursday";
        case Calendar.FRIDAY:
            return "Friday";
        case Calendar.SATURDAY:
            return "Saturday";
        case Calendar.SUNDAY:
            return "Sunday";
        default:
            return "<unknown weekday value " + x + ">";
        }
    }

    private static class DurationVector {

        public int days, hours, minutes, seconds;

    }

    /**
     * Helper
     */

    private static DurationVector breakDurationUp(long duration_s) {
        DurationVector res = new DurationVector();
        final int MINUTE_S = 60;
        final int HOUR_S = 60 * MINUTE_S;
        final int DAY_S = 24 * HOUR_S;
        res.days = (int) (duration_s / DAY_S);
        res.hours = (int) ((duration_s - res.days * DAY_S) / HOUR_S);
        res.minutes = (int) ((duration_s - res.days * DAY_S - res.hours * HOUR_S) / MINUTE_S);
        res.seconds = (int) ((duration_s - res.days * DAY_S - res.hours * HOUR_S - res.minutes * MINUTE_S));
        return res;
    }

    /**
     * Helper function, generates a duration string in h,m,s notation from a
     * duration in s
     */

    public static String buildDurationString(long duration_s, boolean noSeconds, boolean elide) {
        StringBuilder result = new StringBuilder();
        if (duration_s == 0) {
            return "0";
        }
        DurationVector dv = breakDurationUp(duration_s);
        boolean front = true; // indicates whether we are writing at the front
        if (dv.days > 0) {
            result.append(dv.days);
            result.append(" day");
            if (dv.days != 1) {
                result.append("s");
            }
            front = false;
        }
        if (dv.hours > 0 || (!front && !elide)) {
            if (!front) {
                result.append(", ");
            }
            result.append(dv.hours);
            result.append(" hour");
            if (dv.hours != 1) {
                result.append("s");
            }
            front = false;
        }
        if (dv.minutes > 0 || (!front && !elide)) {
            if (!front) {
                result.append(", ");
            }
            result.append(dv.minutes);
            result.append(" minute");
            if (dv.minutes != 1) {
                result.append("s");
            }
            front = false;
        }
        if (!noSeconds) {
            if (dv.seconds > 0 || (!front && !elide)) {
                if (!front) {
                    result.append(", ");
                }
                result.append(dv.seconds);
                result.append(" second");
                if (dv.seconds != 1) {
                    result.append("s");
                }
                front = false;
            }
        }
        return result.toString();
    }

    /**
     * Helper function, generates a duration string in h,m,s notation from a
     * duration in s This one is used by Groovy.
     */

    public static String buildDurationStringShort(BigDecimal duration_s) {
        return buildDurationStringShort(duration_s.longValue());
    }

    /**
     * Helper function, generates a duration string in h,m,s notation from a
     * duration in s
     */

    public static String buildDurationStringShort(long duration_s) {
        StringBuilder result = new StringBuilder();
        if (duration_s == 0) {
            return "0s";
        }
        DurationVector dv = breakDurationUp(duration_s);
        boolean front = true; // indicates whether we are writing at the front
        if (dv.days > 0) {
            result.append(dv.days);
            result.append(" days");
            front = false;
        }
        if (dv.hours > 0 || !front) {
            if (!front) {
                result.append(", ");
                if (dv.hours < 10) {
                    result.append("0");
                }
            }
            result.append(dv.hours);
            front = false;
        }
        if (dv.minutes > 0 || !front) {
            if (!front) {
                result.append(":");
                if (dv.minutes < 10) {
                    result.append("0");
                }
            }
            result.append(dv.minutes);
            front = false;
        }
        if (dv.seconds > 0 || !front) {
            if (!front) {
                result.append(":");
                if (dv.seconds < 10) {
                    result.append("0");
                }
            }
            result.append(dv.seconds);
            front = false;
        }
        result.append("s");
        return result.toString();
    }

}


text:
module PactBroker
  module Services

    SERVICE_FACTORIES = {}

    extend self

    def register_service(name, &block)
      SERVICE_FACTORIES[name] = block
    end

    def get_service(name)
      SERVICE_FACTORIES[name].call
    end

    def index_service
      get_service(:index_service)
    end

    def pact_service
      get_service(:pact_service)
    end

    def pacticipant_service
      get_service(:pacticipant_service)
    end

    def tag_service
      get_service(:tag_service)
    end

    def label_service
      get_service(:label_service)
    end

    def group_service
      get_service(:group_service)
    end

    def webhook_service
      get_service(:webhook_service)
    end

    def version_service
      get_service(:version_service)
    end

    def verification_service
      get_service(:verification_service)
    end

    def badge_service
      get_service(:badge_service)
    end

    def matrix_service
      get_service(:matrix_service)
    end

    def certificate_service
      get_service(:certificate_service)
    end

    def integration_service
      get_service(:integration_service)
    end

    def webhook_trigger_service
      get_service(:webhook_trigger_service)
    end

    def metrics_service
      get_service(:metrics_service)
    end

    def environment_service
      get_service(:environment_service)
    end

    def deployed_version_service
      get_service(:deployed_version_service)
    end

    def released_version_service
      get_service(:released_version_service)
    end

    def contract_service
      get_service(:contract_service)
    end

    def branch_service
      get_service(:branch_service)
    end

    # rubocop: disable Metrics/MethodLength
    def register_default_services
      register_service(:index_service) do
        require "pact_broker/index/service"
        Index::Service
      end

      register_service(:metrics_service) do
        require "pact_broker/metrics/service"
        Metrics::Service
      end

      register_service(:matrix_service) do
        require "pact_broker/matrix/service"
        Matrix::Service
      end

      register_service(:pact_service) do
        require "pact_broker/pacts/service"
        Pacts::Service
      end

      register_service(:pacticipant_service) do
        require "pact_broker/pacticipants/service"
        Pacticipants::Service
      end

      register_service(:tag_service) do
        require "pact_broker/tags/service"
        Tags::Service
      end

      register_service(:label_service) do
        require "pact_broker/labels/service"
        Labels::Service
      end

      register_service(:group_service) do
        require "pact_broker/groups/service"
        Groups::Service
      end

      register_service(:webhook_service) do
        require "pact_broker/webhooks/service"
        Webhooks::Service
      end

      register_service(:version_service) do
        require "pact_broker/versions/service"
        Versions::Service
      end

      register_service(:verification_service) do
        require "pact_broker/verifications/service"
        Verifications::Service
      end

      register_service(:badge_service) do
        require "pact_broker/badges/service"
        Badges::Service
      end

      register_service(:certificate_service) do
        require "pact_broker/certificates/service"
        Certificates::Service
      end

      register_service(:integration_service) do
        require "pact_broker/integrations/service"
        Integrations::Service
      end

      register_service(:webhook_trigger_service) do
        require "pact_broker/webhooks/trigger_service"
        Webhooks::TriggerService
      end

      register_service(:environment_service) do
        require "pact_broker/deployments/environment_service"
        Deployments::EnvironmentService
      end

      register_service(:deployed_version_service) do
        require "pact_broker/deployments/deployed_version_service"
        PactBroker::Deployments::DeployedVersionService
      end

      register_service(:released_version_service) do
        require "pact_broker/deployments/released_version_service"
        PactBroker::Deployments::ReleasedVersionService
      end

      register_service(:contract_service) do
        require "pact_broker/contracts/service"
        PactBroker::Contracts::Service
      end

      register_service(:branch_service) do
        require "pact_broker/versions/branch_service"
        PactBroker::Versions::BranchService
      end
    end
    # rubocop: enable Metrics/MethodLength
  end
end

PactBroker::Services.register_default_services

redpajama_set_name: RedPajamaGithub


text:
#ifndef _ATCOMMANDER_H_
#define _ATCOMMANDER_H_

#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>

#define AT_PLATFORM_RN41 AT_PLATFORM_RN42

#ifdef __cplusplus
extern "C" {
#endif

static const int VALID_BAUD_RATES[] = {230400, 115200, 9600, 19200, 38400,
    57600, 460800};

typedef struct {
    const char* request_format;
    const char* expected_response;
    const char* error_response;
} AtCommand;

typedef struct {
    int response_delay_ms;
    int (*baud_rate_mapper)(int baud);
    AtCommand enter_command_mode_command;
    AtCommand exit_command_mode_command;
    AtCommand set_baud_rate_command;
    AtCommand set_configuration_timer_command;
    AtCommand store_settings_command;
    AtCommand reboot_command;
    AtCommand set_name_command;
    AtCommand set_serialized_name_command;
    AtCommand get_name_command;
    AtCommand get_device_id_command;
} AtCommanderPlatform;

extern const AtCommanderPlatform AT_PLATFORM_RN42;
extern const AtCommanderPlatform AT_PLATFORM_XBEE;

typedef struct {
    AtCommanderPlatform platform;
    void (*baud_rate_initializer)(void* device, int);
    void (*write_function)(void* device, uint8_t);
    int (*read_function)(void* device);
    void (*delay_function)(unsigned long);
    void (*log_function)(const char*, ...);

    bool connected;
    int baud;
    int device_baud;
    void* device;
} AtCommanderConfig;

/** Public: Switch to command mode.
 *
 * If unable to determine the current baud rate and enter command mode, returns
 * false.
 *
 * Returns true if successful, or if already in command mode.
 */
bool at_commander_enter_command_mode(AtCommanderConfig* config);

/** Public: Switch to data mode (from command mode).
 *
 * Returns true if the device was successfully switched to data mode.
 */
bool at_commander_exit_command_mode(AtCommanderConfig* config);

/** Public: Soft-reboot the attached AT device.
 *
 * After rebooting, it's good practice to wait a few hundred ms for the device
 * to restart before trying any other commands.
 *
 * Returns true if the device was successfully rebooted.
 */
bool at_commander_reboot(AtCommanderConfig* config);

/** Public: Change the UART baud rate of the attached AT device, regardless of
 *      the current baud rate.
 *
 *  Attempts to automatically determine the current baud rate in order to enter
 *  command mode and change the baud rate. After updating the baud rate
 *  successfully, it reboots the device.
 *
 *      baud - the desired baud rate.
 *
 *  Returns true if the baud rate was successfully changed.
 */
bool at_commander_set_baud(AtCommanderConfig* config, int baud);

/** Public: Change the configuration timeout of the attached AT device.
 *
 *  Attempts to automatically determine the current baud rate in order to enter
 *  command mode and change the configuration timer (in seconds). A timeout of 0
 *  means that remote configuration is not allowed (configuration is always
 *  allowed via UART).
 *
 *      timeout - the desired configuration timeout in seconds.
 *
 *  Returns true if the configuration timer was successfully changed.
 */
bool at_commander_set_configuration_timer(AtCommanderConfig* config, int timeout_s);

/** Public: Change the attached AT device's name.
 *
 *  name - the desired name.
 *  serialized - if true, will request the AT device append a unique serial
 *  number to the end of the name (e.g. the last 2 digits of the MAC address).
 *
 *  Returns true if the name was set successfully.
 */
bool at_commander_set_name(AtCommanderConfig* config, const char* name,
        bool serialized);

/** Public: Retrieve the attached AT device's ID (usually MAC).
 *
 *  buffer - a string buffer to store the retrieved device ID.
 *  buflen - the length of the buffer.
 *
 *  Returns the length of the response, or -1 if an error occurred.
 */
int at_commander_get_device_id(AtCommanderConfig* config, char* buffer,
        int buflen);

/** Public: Retrieve the attached AT device's name.
 *
 *  buffer - a string buffer to store the retrieved name.
 *  buflen - the length of the buffer.
 *
 *  Returns the length of the response, or -1 if an error occurred.
 */
int at_commander_get_name(AtCommanderConfig* config, char* buffer,
        int buflen);

/** Public: Retrieve the attached AT device's name.
 *
 *  buffer - a string buffer to store the retrieved name.
 *  buflen - the length of the buffer.
 *
 *  Returns the length of the response, or -1 if an error occurred.
 */
int at_commander_get_name(AtCommanderConfig* config, char* buffer,
        int buflen);

/** Public: Send an AT "get" query, read a response, and verify it doesn't match
 * any known errors.
 *
 *  Returns the length of the response, or -1 if an error occurred.
 */
int at_commander_get(AtCommanderConfig* config, AtCommand* command,
        char* response_buffer, int response_buffer_length);

/** Public: Send an AT command, read a response, and verify it matches the
 * expected value.
 *
 * Returns true if the response matches the expected.
 */
bool at_commander_set(AtCommanderConfig* config, AtCommand* command,
        ...);

int rn42_baud_rate_mapper(int baud);
int xbee_baud_rate_mapper(int baud);

#ifdef __cplusplus
}
#endif

#endif // _ATCOMMANDER_H_


text:
package graph.algorithms.connectivity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import graph.algorithms.planarity.BoyerMyrvoldPlanarity;
import graph.algorithms.planarity.FraysseixMendezPlanarity;
import graph.algorithms.planarity.PlanarityTestingAlgorithm;
import graph.elements.Edge;
import graph.elements.Graph;
import graph.elements.Vertex;
import graph.exception.CannotBeAppliedException;
import graph.traversal.GraphTraversal;
import graph.tree.bc.BCTree;
import graph.tree.bc.BCTreeEdge;
import graph.tree.bc.BCTreeNode;
import graph.tree.bc.BCNodeType;
import graph.util.Util;

/**
 * Given a connected, but not biconnected planar graph, the algorithm
 * adds a minimum number of edges to turn it into a biconnected graph
 * while not ruining the planarity
 * This implementation is based on Fialko and Mutzel's 5/3 approximation
 * @author Renata
 * @param <V> The vertex type
 * @param <E> The edge type
 */
public class PlanarAugmentation<V extends Vertex, E extends Edge<V>> {

	/**
	 * Algorithm used to check the planarity
	 */
	private PlanarityTestingAlgorithm<V, E> planarityTest;
	/**
	 * Boyer-Myrvold planarity, used to determine outside vertices of certain blocks
	 */
	private BoyerMyrvoldPlanarity<V, E> boyerMyrvold;
	/**
	 * Block-cut vertex tree used in the algorithm
	 */
	private BCTree<V, E> bcTree;
	/**
	 * A map of nodes and their degrees
	 */
	private Map<BCTreeNode, Integer> deg;

	private boolean debug = false;

	private Logger log = Logger.getLogger(PlanarAugmentation.class);

	public PlanarAugmentation(){
		planarityTest = new FraysseixMendezPlanarity<V,E>();
		boyerMyrvold = new BoyerMyrvoldPlanarity<V,E>();
	}

	/**
	 * Finds edges which need to be added in order to transform the graph into a planar
	 * biconnected one.
	 * @param graph Graph that should be connected and planar that is to be turned into a biconnected graph
	 * @return Edges to be added
	 * @throws CannotBeAppliedException if the planar augmentation algorithm cannot be applied (graph is not planar or is not connected)
	 */
	@SuppressWarnings("unchecked")
	public List<E> planarBiconnected(Graph<V,E> graph) throws CannotBeAppliedException{
		if (!planarityTest.isPlannar(graph))
			throw new CannotBeAppliedException("Graph is not planar");

		//technically, if it is not it can first be made connected
		//in a similar fashion to this algorithm
		//for now, only apply the algorithm if the graph is already connected
		if (!graph.isConnected())
			throw new CannotBeAppliedException("Graph is not connected");

		//keep a track of all created edges between vertices of blocks
		//and add them when merging the blocks
		List<E> addedEdges = new ArrayList<E>();

		if (graph.isBiconnected())
			return addedEdges;

		//step one
		//Construct the block tree
		//initialize P (list containing all pendants in T)
		//pendant is a block which contains only one cut vertex

		if (debug){
			log.info("initialization");
			log.info("Cut vertices: " + graph.listCutVertices());
			log.info("Blocks: " + graph.listBiconnectedComponents());
		}

		bcTree = new BCTree<V,E>(graph);

		if (debug)
			log.info(bcTree);

		Graph<V,E> ret = Util.copyGraph(graph);

		//degrees will be modified so a map which holds them is used and initialized here
		deg = new HashMap<BCTreeNode, Integer>();

		for (BCTreeNode bcNode : bcTree.getVertices()){
			deg.put(bcNode, bcTree.vertexDegree(bcNode));
		}

		List<Graph<V,E>> pendants = bcTree.getPendants();
		//initialize the list of labels by calling reduce chains
		List<PlanarAugmentationLabel<V, E>> labels = reduceChains(graph, pendants);
		PlanarAugmentationLabel<V, E> l1, l2;

		Set<BCTreeNode> pathNodes = new HashSet<BCTreeNode>();

		BCTreeNode pPrimNode;
		Set<BCTreeNode> cutVertices = new HashSet<BCTreeNode>();

		//while T(G) has c-vertices
		while(bcTree.getcVertices().size() > 0){
			//l1 - label with maximum size
			//l2 - match_labels(l1)

			l1 = labels.get(0);
			for (int i = 1; i < labels.size(); i++){
				PlanarAugmentationLabel<V, E> label = labels.get(i);
				if (labels.size() > l1.size())
					l1 = label;
			}

			if (debug)
				log.info("l1: " + l1);

			l2 = matchLabels(l1, labels); //search for a partner label for l1

			if (debug)
				log.info("l2: " + l2);

			//if there is no label that can be matched to l1
			if (l2 == null){
				//Add L(l1) - 1 (size(l1) - 1) edges from an outside node
				//in the first child of l1 to the outside nodes of other children of l1
				//merge all bc nodes along the paths between l1 and the children of l1
				//and the children themselves to a new pendant p'

				//don't connect cut vertices, connect vertices inside blocks
				//all children are pendants, which means that
				//they only have one cut vertex and one edge

				BCTreeNode c1 = l1.getParent();
				Graph<V,E> firstChild = l1.getChildren().get(0);
				boyerMyrvold.isPlannar(firstChild);
				List<V> outsideFace = boyerMyrvold.getOutsideFace();
				BCTreeEdge edge = bcTree.adjacentEdges(bcTree.getVertexByContent(firstChild)).get(0);
				BCTreeNode cutNode = edge.getOrigin() == bcTree.getVertexByContent(firstChild) ? edge.getDestination() : edge.getOrigin();
				outsideFace.remove(cutNode.getContent());
				V v1 = outsideFace.get(0);

				pathNodes.clear();

				for (int i = 1; i < l1.getChildren().size(); i++){
					Graph<V,E> otherChild = l1.getChildren().get(i);
					boyerMyrvold.isPlannar(otherChild);
					outsideFace = boyerMyrvold.getOutsideFace();
					edge = bcTree.adjacentEdges(bcTree.getVertexByContent(otherChild)).get(0);
					cutNode = edge.getOrigin() == bcTree.getVertexByContent(firstChild) ? edge.getDestination() : edge.getOrigin();
					outsideFace.remove(cutNode.getContent());
					V v2 = outsideFace.get(0);
					E newEdge = Util.createEdge(v1, v2, graph.getEdges().get(0).getClass());
					addedEdges.add(newEdge);
					ret.addEdge(newEdge);
					if (debug)
						log.info("added edge " + newEdge);
					List<BCTreeNode> currentPath = GraphTraversal.nonrecursiveDFSPath(bcTree, bcTree.getVertexByContent(firstChild),
							bcTree.getVertexByContent(otherChild)).getUniqueVertices();
					pathNodes.addAll(currentPath);
				}

				//now add path between the children themselves
				//and also between l1 and the children
				List<BCTreeNode> currentPath;
				currentPath = GraphTraversal.nonrecursiveDFSPath(bcTree, bcTree.getVertexByContent(firstChild),
						l1.getParent()).getUniqueVertices();
				pathNodes.addAll(currentPath);
				for (int i = 0; i < l1.getChildren().size(); i++){
					Graph<V,E> child1 = l1.getChildren().get(i);
					currentPath = GraphTraversal.nonrecursiveDFSPath(bcTree, l1.getParent(), bcTree.getVertexByContent(child1)).pathVertices();
					pathNodes.addAll(currentPath);

					//if a nodes on the path is not a child (and it can't be since only pendants are children of a label)
					//and since the nodes are supposed to be merged to form a new pendant
					//the formed graph (block) must be biconnected
					//that means that these non-pendant blocks on the path also need to be connected
					//to other blocks
					if (debug){
						log.info("l1 child " + child1 + " path: " + currentPath);
						log.info("Connect blocks on this path");
					}
					for (int j = 1; j < currentPath.size() - 2; j+=2){
						Graph<V,E> block1 = (Graph<V, E>) currentPath.get(j).getContent();
						Graph<V,E> block2 = (Graph<V, E>) currentPath.get(j + 2).getContent();
						boyerMyrvold.isPlannar(block1);
						V cutVertex = (V) currentPath.get(j + 1).getContent();
						List<V> face1 = boyerMyrvold.getOutsideFace();
						face1.remove(cutVertex);
						boyerMyrvold.isPlannar(block2);
						List<V> face2 = boyerMyrvold.getOutsideFace();
						face2.remove(cutVertex);
						V block1V = face1.get(0);
						V block2V = face2.get(0);
						E newEdge = Util.createEdge(block1V, block2V, graph.getEdges().get(0).getClass());
						if (debug)
							log.info("added edge: " + newEdge);
						addedEdges.add(newEdge);
						ret.addEdge(newEdge);
					}
					if (i == 0)
						continue;

					if (i < l1.getChildren().size() - 1)
						for (int j = 2; j < l1.getChildren().size(); j++){
							Graph<V,E> child2 = l1.getChildren().get(j);
							currentPath = GraphTraversal.nonrecursiveDFSPath(bcTree, bcTree.getVertexByContent(child1),
									bcTree.getVertexByContent(child2)).getUniqueVertices();
							pathNodes.addAll(currentPath);
						}
				}

				if (debug)
					log.info("All nodes on paths: "  + pathNodes);

				//merge all bc nodes on the paths to one new pendant p'
				Graph<V,E> pPrim = new Graph<V,E>();
				mergeNodes(pathNodes, pPrim);
				for (E e : addedEdges)
					pPrim.addEdge(e);

				if (debug)
					log.info("P' " + pPrim);

				//after merging the nodes, the bc tree should be updated
				//the old nodes removed, the new ones added
				//if l1 is c1-label
				//c1 is the only cut vertex of the new block
				pPrimNode = new BCTreeNode(pPrim);
				//set parent of the node
				pPrimNode.setParent(l1.getParent());
				pPrimNode.setType(BCNodeType.B);

				bcTree.addVertex(pPrimNode);
				//connect the new node to c1
				BCTreeEdge pPrimEdge = new BCTreeEdge(c1, pPrimNode);
				bcTree.addEdge(pPrimEdge);

				if (debug){
					log.info("BCTree after merging blocks: ");
					log.info(bcTree);
				}

				//f - the cut vertex found in the first pass of reduce_chains(p')
				BCTreeNode f = reduceChainsFirstPass(graph, pPrim);

				if (debug)
					log.info("f: " + f);
				//b - the block adjacent to f but not belonging to the path {p', f)
				List<BCTreeNode> pPrimFPath = GraphTraversal.nonrecursiveDFSPath(bcTree, pPrimNode, f).getUniqueVertices();

				if (debug)
					log.info("p' f path " + pPrimFPath);

				BCTreeNode b = null;
				for (BCTreeEdge bcEdge : bcTree.adjacentEdges(f)){
					BCTreeNode otherNode = bcEdge.getOrigin() == f ? bcEdge.getDestination() : bcEdge.getOrigin();
					if (otherNode.getType() == BCNodeType.B)
						if (!pPrimFPath.contains(otherNode)){
							b = otherNode;
							break;
						}
				}

				//add an edge from an outside node of p' to a node of b adjacent to f
				//choose a node of p' that is adjacent to c1

				v1 = pPrim.adjacentVertices((V)c1.getContent()).get(0);

				Graph<V,E> bBlock = (Graph<V, E>) b.getContent();
				V v2 = bBlock.adjacentVertices((V) f.getContent()).get(0);
				E newEdge = Util.createEdge(v1, v2, graph.getEdges().get(0).getClass());

				if (debug)
					log.info("Adding new edge " + newEdge);
				addedEdges.add(newEdge);
				ret.addEdge(newEdge);

				pathNodes.clear();
				List<BCTreeNode> pPrimBPath = GraphTraversal.nonrecursiveDFSPath(bcTree, pPrimNode, b).getUniqueVertices();
				pathNodes.add(pPrimNode);
				pathNodes.add(b);
				pathNodes.addAll(pPrimBPath);

				//p' - construct in T(G) a new block from p', b and bc_nodes along the path {p', b)
				if (debug)
					log.info("Forming new p' from " + pathNodes);

				initCutVerticesOnPath(pathNodes, cutVertices);

				Graph<V,E> pPrimNew = new Graph<V,E>();
				mergeNodes(pathNodes, pPrimNew);
				pPrimNew.addEdge(newEdge);
				pPrimNode = new BCTreeNode(pPrimNew);
				bcTree.addVertex(pPrimNode);
				pPrimNode.setType(BCNodeType.B);

				setNewParents(cutVertices, pathNodes, pPrimNode);

				//new root of the tree
				if (pPrimNode.getParent() == null)
					bcTree.setRoot(pPrimNode);

				if (debug){
					log.info("Created new p' node: " + pPrimNode);
					log.info("BC tree after creation of a new p' node " + bcTree);
				}
			}

			else{ //l2 is the partner label of l1
				//connect every child of l2 with a child of l1
				//so, not with every child of l1
				//let's merge all of the with the first child of l1
				//because it is not specified with which child
				//revise this if the result is not satisfactory

				List<V> outsideFace1, outsideFace2;
				addedEdges.clear();
				Graph<V,E> l1Child = l1.getChildren().get(0);
				boyerMyrvold.isPlannar(l1Child);
				outsideFace1 = boyerMyrvold.getOutsideFace();
				BCTreeEdge edge = bcTree.adjacentEdges(bcTree.getVertexByContent(l1Child)).get(0);
				BCTreeNode cutNode = edge.getOrigin() == bcTree.getVertexByContent(l1Child) ? edge.getDestination() : edge.getOrigin();
				outsideFace1.remove(cutNode.getContent());
				V v1 = outsideFace1.get(0);

				if (debug){
					log.info("labels l1 " + l1 + " and l2 " + l2);
					log.info("choose child " + l1Child + " of l1 to merge");
				}

				//list of l1 and l2 children to be merged
				List<BCTreeNode> l1ChildNodes = new ArrayList<BCTreeNode>(), l2ChildNodes = new ArrayList<BCTreeNode>();
				l1ChildNodes.add(bcTree.getVertexByContent(l1Child));

				for (Graph<V,E> l2Child : l2.getChildren()){
					l2ChildNodes.add(bcTree.getVertexByContent(l2Child));
					boyerMyrvold.isPlannar(l2Child);
					outsideFace2 = boyerMyrvold.getOutsideFace();
					edge = bcTree.adjacentEdges(bcTree.getVertexByContent(l2Child)).get(0);
					cutNode = edge.getOrigin() == bcTree.getVertexByContent(l2Child) ? edge.getDestination() : edge.getOrigin();
					outsideFace2.remove(cutNode.getContent());
					V v2 = outsideFace2.get(0);
					E newEdge = Util.createEdge(v1, v2, graph.getEdges().get(0).getClass());
					addedEdges.add(newEdge);
					if (debug)
						log.info("adding edge " + newEdge);
					ret.addEdge(newEdge);
				}

				pathNodes.clear();
				//merge all connected pendants, all bc nodes on the path
				//between them and their parents (l1 or l2), l1, l2 and all bc nodes
				//on the path {l1,l2) to a new block p'

				BCTreeNode l1Parent = l1.getParent();
				BCTreeNode l2Parent = l2.getParent();

				for (BCTreeNode node : l1ChildNodes){
					List<BCTreeNode> currentPath = GraphTraversal.nonrecursiveDFSPath(bcTree, node, l1Parent).getUniqueVertices();
					currentPath.remove(l1Parent);
					pathNodes.addAll(currentPath);
				}

				for (BCTreeNode node : l2ChildNodes){
					List<BCTreeNode> currentPath = GraphTraversal.nonrecursiveDFSPath(bcTree, node, l2Parent).getUniqueVertices();
					pathNodes.addAll(currentPath);
				}

				List<BCTreeNode> currentPath = GraphTraversal.nonrecursiveDFSPath(bcTree, l1Parent, l2Parent).getUniqueVertices();
				pathNodes.addAll(currentPath);

				if (debug)
					log.info("Should merge all on path " + pathNodes);

				//now to determine how to connect it
				//try the same logic as before

				initCutVerticesOnPath(pathNodes, cutVertices);

				Graph<V,E> pPrim = new Graph<V,E>();
				mergeNodes(pathNodes, pPrim);
				for (E e : addedEdges)
					pPrim.addEdge(e);

				pPrimNode = new BCTreeNode(pPrim);
				pPrimNode.setType(BCNodeType.B);
				bcTree.addVertex(pPrimNode);

				setNewParents(cutVertices, pathNodes, pPrimNode);

				if (pPrimNode.getParent() == null)
					bcTree.setRoot(pPrimNode);

				if (debug){
					log.info("p' node: " + pPrimNode);
					log.info("BC tree after creation of a new p' node " + bcTree);
				}
			}

			//Updates after the main part is completed

			//update degrees
			deg.clear();
			for (BCTreeNode bcNode : bcTree.getVertices()){
				deg.put(bcNode, bcTree.vertexDegree(bcNode));
			}
			//update pendants and labels
			bcTree.updatePendants();
			pendants = bcTree.getPendants();
			labels = reduceChains(ret, pendants);

			if (l2 != null && l1.size() == l2.size()) //l1 has no more children
				labels.remove(l1); //remove l1 form the list of labels

		}

		return addedEdges;
	}

	/**
	 * Sets new parents of bc tree nodes after nodes on the path are merged into a new node
	 * @param cutVertices
	 * @param pathNodes
	 * @param pPrimNode
	 */
	private void setNewParents(Set<BCTreeNode> cutVertices, Set<BCTreeNode> pathNodes, BCTreeNode pPrimNode){

		//the edges in the bc trees are between cut vertices and blocks that contain them
		//if a cut vertex is on a lower level than the block, the block is its parent
		//otherwise, the vertex is the parent
		//so, some cut vertices of this block will have it as the parent
		//the cut vertex that has none of the blocks of the path as its parent
		//should be the new parent of the block

		for (BCTreeNode cNode : cutVertices){
			BCTreeEdge newPPrimEdge = new BCTreeEdge(pPrimNode, cNode);
			bcTree.addEdge(newPPrimEdge);
			if (cNode.getParent() == null || !pathNodes.contains(cNode.getParent()))
				pPrimNode.setParent(cNode);
			else if (cNode.getParent() != null)
				cNode.setParent(pPrimNode); //also updating the parent of the cut vertex since its parent was merged

		}
	}

	/**
	 * All bc tree nodes on the path are to be merged
	 * Some of the cut vertices will no longer be that
	 * If all blocks that contained them are merged and connected
	 * This method finds the vertices which are still cut vertices
	 * That is, checks if a c node is connected to some other block
	 * not on the path
	 * @param pathNodes Nodes on the path
	 * @param cutVertices A set if cut vertices that is initialized
	 */
	private void initCutVerticesOnPath(Set<BCTreeNode> pathNodes, Set<BCTreeNode> cutVertices){
		cutVertices.clear();
		for (BCTreeNode pathNode : pathNodes){
			if (pathNode.getType() == BCNodeType.B){
				for (BCTreeEdge bcEdge : bcTree.adjacentEdges(pathNode)){
					BCTreeNode other = bcEdge.getOrigin() == pathNode ? bcEdge.getDestination() : bcEdge.getOrigin();
					if (other.getType() == BCNodeType.C){
						//see if this vertex has an edge to a block not on the current path
						for (BCTreeEdge cutVertexEdge : bcTree.adjacentEdges(other)){
							BCTreeNode connected = cutVertexEdge.getOrigin() == other ? cutVertexEdge.getDestination() : cutVertexEdge.getOrigin();
							if (!pathNodes.contains(connected)){
								cutVertices.add(other);
								break;
							}
						}
					}
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	private void mergeNodes(Set<BCTreeNode> nodes, Graph<V,E> constructedGraph){
		if (debug)
			log.info("Merge nodes " + nodes);
		if (nodes.size() == 1)
			return;
		for (BCTreeNode pathNode : nodes){
			if (debug)
				log.info("curent node: " + pathNode);
			if (pathNode.getType() == BCNodeType.B){
				Graph<V,E> currentPendant = (Graph<V, E>) pathNode.getContent();
				if (debug)
					log.info("curent pendant: " + currentPendant);
				for (V v : currentPendant.getVertices())
					constructedGraph.addVertex(v);
				for (E e : currentPendant.getEdges())
					constructedGraph.addEdge(e);
				//removing the node from the tree
				bcTree.removeVertex(pathNode);
			}
		}

		//if node is a c node
		//and it is not adjacent to any edges other than the ones that were on the path
		//it is no longer a cut vertex, so remove it
		for (BCTreeNode pathNode : nodes)
			if (pathNode.getType() == BCNodeType.C && bcTree.adjacentEdges(pathNode).size() == 0)
				bcTree.removeVertex(pathNode);
	}

	@SuppressWarnings("unchecked")
	private BCTreeNode reduceChainsFirstPass(Graph<V,E> graph, Graph<V,E> p){
		//c - the cut vertex adjacent to p
		BCTreeNode pendantNode = bcTree.getVertexByContent(p);
		BCTreeNode c = null;
		for (BCTreeNode adj : bcTree.adjacentVertices(pendantNode)){
			if (adj.getType() == BCNodeType.C){
				c = adj;
				break;
			}
		}

		if (debug)
			log.info("Cut vertex adjacent to the pendant " + c);

		//while deg(c) = 2 and c is not the root of T(G)

		BCTreeNode lastC = null;

		while (c != bcTree.getRoot() && deg.get(c) == 2){

			//if c is a b-vertex
			if (c.getType() == BCNodeType.B){
				List<BCTreeEdge> edges = bcTree.adjacentEdges(c);
				//let c1 and c2 be 2 cut vertices adjacent to b
				BCTreeEdge e1 = edges.get(0);
				BCTreeEdge e2 = edges.get(1);
				BCTreeNode c1 = e1.getOrigin() == c ? e1.getDestination() : e1.getOrigin();
				BCTreeNode c2 = e1.getOrigin() == c ? e2.getDestination() : e2.getOrigin();

				//if !planar(G+(c1,c2))
				//break;

				if (!checkPlanarity(graph, (V)c1.getContent(), (V)c2.getContent()))
					break;
			}
			else{
				//keep track of the last reached c vertex
				lastC = c;
			}
			//c - parent(c)
			c = c.getParent();

		}

		if (debug){
			log.info("c: " + c);
			log.info("last cut vertex: " + lastC);
		}

		//if c is a b-vertex
		if (c.getType() == BCNodeType.B){
			//c - the last cut vertex that we have reached
			c = lastC;
		}

		return c;

	}

	/**
	 * Finds all labels in T(G). Applying this procedure to one pendant p too.
	 * That way, the first loop (first) pass) is only run for p and the second
	 * loop (second pass) only for the cut vertex c found in the first loop
	 * @param pendants
	 * @param labels List of labels to be updated or formed
	 */
	private List<PlanarAugmentationLabel<V, E>> reduceChains(Graph<V,E> graph, List<Graph<V,E>> pendants){

		//for each p in pendants
		//the first pass

		List<PlanarAugmentationLabel<V, E>> labels =
				new ArrayList<PlanarAugmentationLabel<V,E>>();

		Map<BCTreeNode, PlanarAugmentationLabel<V,E>> nodeLabelsMap =
				new HashMap<BCTreeNode, PlanarAugmentationLabel<V,E>>();
		for (PlanarAugmentationLabel<V,E> label : labels)
			nodeLabelsMap.put(label.getParent(), label);

		for (Graph<V,E> p : pendants){

			if (debug)
				log.info("Current pendant " + p );

			BCTreeNode c = reduceChainsFirstPass(graph, p);

			//c is a c-label
			//p is a child of c
			PlanarAugmentationLabel<V, E> cLabel = new PlanarAugmentationLabel<V,E>(c);
			nodeLabelsMap.put(c, cLabel);
			cLabel.addChild(p);
			labels.add(cLabel);

			if (debug)
				log.info("Created label " + cLabel);
		}

		//second pass
		//for each c-label found in the first pass
		//not iterating through the list since it will be changed later

		if (debug)
			log.info("second pass");
		for (PlanarAugmentationLabel<V, E> c : nodeLabelsMap.values()){
			//if deg(c) == 2 and c is adjacent to the block b with
			//degree 3 and b is adjacent to another c-label c'
			//with deg(c') == 2 and planar(c,c')

			//if it was already removed
			if (!labels.contains(c))
				continue;

			BCTreeNode cNode = c.getParent();
			if (deg.get(cNode) != 2)
				continue;

			//see if c is adjacent to a block of degree 3
			BCTreeNode block = null;

			for (BCTreeEdge bcEdge : bcTree.adjacentEdges(cNode)){
				BCTreeNode other = bcEdge.getOrigin() == cNode ? bcEdge.getDestination() : bcEdge.getOrigin();
				if (other.getType() == BCNodeType.B && deg.get(other) == 3){
					block = other;
					break;
				}
			}

			if (block == null)
				continue;

			if (debug)
				log.info("adjacent to a block of degree 3 " + block);

			//is b adjacent to another c-label
			PlanarAugmentationLabel<V,E> cPrim = null;

			for (BCTreeEdge bcEdge : bcTree.adjacentEdges(block)){
				BCTreeNode other = bcEdge.getOrigin() == block ? bcEdge.getDestination() : bcEdge.getOrigin();
				if (other != cNode && nodeLabelsMap.containsKey(other)){
					cPrim = nodeLabelsMap.get(other);
					//also check if the label was already removed from the list
					if (labels.contains(cPrim) && deg.get(other) == 2
							&& planar(c, cPrim, bcTree, graph))
						break;
					else
						cPrim = null;
				}
			}

			if (debug)
				log.info("c' " + cPrim );

			if (cPrim == null)
				continue;

			//b is a new b-label and the 2 children of c and c'
			//are now children of b
			//add b and remove c and c' from the list of labels
			PlanarAugmentationLabel<V, E> bLabel =
					new PlanarAugmentationLabel<V,E>(block);
			bLabel.addChild(c.getChildren().get(0));
			bLabel.addChild(cPrim.getChildren().get(0));
			labels.remove(c);
			labels.remove(cPrim);
			labels.add(bLabel);

			if (debug)
				log.info("created b label " + bLabel);
		}

		return labels;
	}

	/**
	 * Tests whether two bundles represented by labels l1 and l2 can be matched planar
	 * @param l1
	 * @param l2
	 * @return {@code true} if a planar match can be made, {@code false} otherwise
	 */
	@SuppressWarnings("unchecked")
	private boolean planar(PlanarAugmentationLabel<V, E> l1, PlanarAugmentationLabel<V, E> l2, BCTree<V,E> bcTree,  Graph<V,E> graph){

		if (debug)
			log.info("Checking if labels " + l1 + " and " + l2 + " can be matched planar");

		//if l1 and l2 are c labels
		//return planar(G+(l1,l2))
		if (l1.getParent().getType() == BCNodeType.C && l2.getParent().getType() == BCNodeType.C){
			if (debug)
				log.info("Two c labels");
			return checkPlanarity(graph, (V) l1.getParent().getContent(), (V) l2.getParent().getContent());
		}

		//let v1 be a b-label and c11 and c12 cut vertices
		//adjacent to 2 children of l1 in T(G)

		//at least one of them is a block
		PlanarAugmentationLabel<V, E> blockLabel = l1.getType() == BCNodeType.B ? l1 : l2;
		PlanarAugmentationLabel<V, E> otherLabel = blockLabel == l1 ? l2 : l1;

		if (debug){
			log.info(blockLabel + " is B label");
			log.info("Finding c11 and c12");
		}

		V c11 = null, c12 = null;
		for (Graph<V,E> pendant : blockLabel.getChildren()){
			BCTreeNode pendantNode = bcTree.getVertexByContent(pendant);
			for (BCTreeEdge bcEdge : bcTree.adjacentEdges(pendantNode)){
				BCTreeNode other = bcEdge.getOrigin() == pendantNode ? bcEdge.getDestination() : bcEdge.getOrigin();
				if (other.getType() == BCNodeType.C){
					if (c11 == null)
						c11 = (V) other.getContent();
					else
						c12 = (V) other.getContent();
					break;
				}
			}
		}

		if (debug){
			log.info("c11 " + c11);
			log.info("c12 " + c12);
		}

		//if l2 is a c-label
		if (otherLabel.getType() == BCNodeType.C){
			//if L(l2) == 1
			V cutVertex = (V) otherLabel.getParent();
			log.info("Other label of c type and size " + otherLabel.size());
			if (otherLabel.size() == 1){
				//return planar(G + (c11,l2) or planar(G + (c12,l2))
				return (checkPlanarity(graph, c11, cutVertex) ||
						checkPlanarity(graph, c12, cutVertex));
			}
			else{
				//return planar(G + (c11,l2) + (c12,l2))
				return checkPlanarity(graph, c11, cutVertex, c12, cutVertex);
			}
		}
		else{ //both l1 and l2 are b-labels
			//let c21 and c22be two cut vertices adjacent to two children of l2
			log.info("Both labels are blocks");

			V c21 = null, c22 = null;
			for (Graph<V,E> pendant : otherLabel.getChildren()){
				BCTreeNode pendantNode = bcTree.getVertexByContent(pendant);
				for (BCTreeEdge bcEdge : bcTree.adjacentEdges(pendantNode)){
					BCTreeNode other = bcEdge.getOrigin() == pendantNode ? bcEdge.getDestination() : bcEdge.getOrigin();
					if (other.getType() == BCNodeType.C){
						if (c21 == null)
							c21 = (V) other.getContent();
						else
							c22 = (V) other.getContent();
						break;
					}
				}
			}

			log.info("c21 " + c21);
			log.info("c22 " + c22);

			//return planar(G+(c11,c21) + (c12,c22)) or planar(G + (c11,c22) + c(12,c21))
			return (checkPlanarity(graph, c11,c21,c12,c22) ||
					checkPlanarity(graph, c11,c22,c12,c21));
		}

	}

	/**
	 * Check the planarity of graph after the two vertices v1 and v2 are connected
	 * @param graph
	 * @param v1
	 * @param v2
	 * @return {@code true} if the graph is planar, {@code false} otherwise
	 */
	@SuppressWarnings("unchecked")
	private boolean checkPlanarity(Graph<V,E> graph, V v1, V v2){

		boolean planar;

		//TODO use incremental planarity test once implemented

		E edge = Util.createEdge(v1, v2, graph.getEdges().get(0).getClass());
		graph.addEdge(edge);
		planar = planarityTest.isPlannar(graph);
		//removing the edge in any case, added it just to test the planarity
		graph.removeEdge(edge);

		return planar;
	}

	/**
	 * Check the planarity of graph after vertices are connected
	 * First two vertices form the first edge, next to the second edge etc.
	 * @param graph
	 * @param v1
	 * @param v2
	 * @return {@code true} if the graph is planar, {@code false} otherwise
	 */
	@SuppressWarnings("unchecked")
	private boolean checkPlanarity(Graph<V,E> graph, V...vertices){

		boolean planar;

		//TODO use incremental planarity test once implemented

		List<E> edges = new ArrayList<E>();

		for (int i = 0; i < vertices.length - 2; i += 2){
			V v1 = vertices[i];
			V v2 = vertices[i+1];
			E edge = Util.createEdge(v1, v2, graph.getEdges().get(0).getClass());
			graph.addEdge(edge);
			edges.add(edge);
		}

		planar = planarityTest.isPlannar(graph);

		//removing the edge in any case, added it just to test the planarity
		for (E edge : edges)
			graph.removeEdge(edge);

		return planar;
	}

	/**
	 * Checks condition con_cond for two bundles represented
	 * by labels l1 and l2
	 * @param l1
	 * @param l2
	 * @return {@code true} is condition is met, {@code false} otherwise
	 */
	private boolean conCond(PlanarAugmentationLabel<V,E> l1, PlanarAugmentationLabel<V,E> l2){

		if (debug)
			log.info("Checking con cond for labels " + l1 + " and " + l2);

		//P - compute the path {l1,l2} in T(G)
		List<BCTreeNode> P = GraphTraversal.nonrecursiveDFSPath(bcTree, l1.getParent(), l2.getParent()).getUniqueVertices();

		if (debug)
			log.info("P: " + P);

		//replace the degree of l1 by deg(l1) - L(l2) + 1
		//replace the degree of l2 by deg(l2)- L(l2) + 1

		//save for later
		int l1Degree = deg.get(l1.getParent());
		int l2Degree = deg.get(l2.getParent());

		deg.put(l1.getParent(), l1Degree - l2.size() + 1);
		deg.put(l2.getParent(), l2Degree - l2.size() + 1);

		//if P contains 2 bc nodes with degree at least 3 or 1 block
		//with degree at least 4, return true, else return false
		boolean ret = false;
		int nodesOfDegree3 = 0;
		int blocksOfDegree4 = 0;

		for (BCTreeNode node  : P)
			if (deg.get(node) == 3)
				nodesOfDegree3++;
			else if (node.getType() == BCNodeType.B && deg.get(node) == 4)
				blocksOfDegree4++;

		ret = nodesOfDegree3 == 2 || blocksOfDegree4 == 1;

		if (debug){
			log.info("nodes of degree 3: " + nodesOfDegree3);
			log.info("blocks of degree 4: " + blocksOfDegree4);
		}

		//changing back the degrees
		deg.put(l1.getParent(), l1Degree);
		deg.put(l2.getParent(), l2Degree);

		return ret;
	}

	/**
	 * Given a label l1, find a label, l2,  with which it can be matched
	 * so that planarity is not ruined
	 * @param l1
	 * @param labels
	 * @return A label with which {@code l1} can be matched
	 */
	private PlanarAugmentationLabel<V, E> matchLabels(PlanarAugmentationLabel<V, E> l1,
			List<PlanarAugmentationLabel<V, E>> labels){

		for (PlanarAugmentationLabel<V, E> l2 : labels)
			if (l2 == l1)
				continue;
			else if (conCond(l1, l2))
				return l2;

		return null;

	}

}


text:
#ifndef __INCLUDED_ARFF_PARSER_H__
#define __INCLUDED_ARFF_PARSER_H__
/**
 * @file arff_parser.h
 * @brief Contains class 'ArffParser'
 */

#include <string>

#include <arff_lexer.h>
#include <arff_data.h>

/**
 * @class ArffParser arff_parser.h
 * @brief Main class for parsing ARFF files
 */
class ArffParser {
public:
    /**
     * @brief Constructor
     * @param _file File to be parsed
     */
    ArffParser(const std::string& _file);

    /**
     * @brief Destructor
     */
    ~ArffParser();

    /**
     * @brief Main function for parsing the file
     * @return the 'ArffData' object after parsing the file
     *
     * Note that this pointer will still be owned by this class!
     */
    ArffData* parse();

private:
    /**
     * @brief Reads the 'relation' token
     */
    void _read_relation();

    /**
     * @brief Reads the attributes
     */
    void _read_attrs();

    /**
     * @brief Reads one attribute
     */
    void _read_attr();

    /**
     * @brief Reads the data
     */
    void _read_instances();

    /** lexer for generating tokens */
    ArffLexer* m_lexer;
    /** whether you have already parsed the file or not */
    bool m_parsed;
    /** the data parsed from the ARFF file */
    ArffData* m_data;
};

/* DO NOT WRITE ANYTHING BELOW THIS LINE!!! */
#endif // __INCLUDED_ARFF_PARSER_H__


text:
<?php
class Sample extends AppModel {

	public $belongsTo = array('Apple');

/**
 * afterFind
 *
 * @param array $results Results
 * @param bool $primary Primary
 * @return array
 */
	public function afterFind($results, $primary = false) {
		foreach ($results as &$result) {
			$apple = $this->Apple->find('first', array(
				'fields' => array(
					'Apple.id',
					'Apple.apple_id',
				),
				'contain' => array(
					'ParentApple' => array('fields' => array('id', 'name')),
				),
				'conditions' => array('Apple.id' => $result[$this->alias]['id']),
			));

			if ($apple) {
				$apple = $apple['Apple'] + $apple;
				unset($apple['Apple']);
			}
			$result[$this->alias]['Apple'] = $apple;
		}
		return $results;
	}
}


text:
const getDigitsFromValue = (value = '') => value.replace(/(-(?!\d))|[^0-9|-]/g, '') || ''

const padDigits = digits => {
  const desiredLength = 3
  const actualLength = digits.length

  if (actualLength >= desiredLength) {
    return digits
  }

  const amountToAdd = desiredLength - actualLength
  const padding = '0'.repeat(amountToAdd)

  return padding + digits
}

const removeLeadingZeros = number => number.replace(/^0+([0-9]+)/, '$1')

const addDecimalToNumber = (number, separator) => {
  const centsStartingPosition = number.length - 2
  const dollars = removeLeadingZeros(
    number.substring(0, centsStartingPosition)
  )
  const cents = number.substring(centsStartingPosition)
  return dollars + separator + cents
}

export const toCurrency = (value, separator = '.') => {
  const digits = getDigitsFromValue(value)
  const digitsWithPadding = padDigits(digits)
  return addDecimalToNumber(digitsWithPadding, separator)
}


text:
namespace net {

class FtpResponseInfo;
class FtpRequestInfo;
class LoadLog;

// Represents a single FTP transaction.
class FtpTransaction {
 public:
  // Stops any pending IO and destroys the transaction object.
  virtual ~FtpTransaction() {}

  // Starts the FTP transaction (i.e., sends the FTP request).
  //
  // Returns OK if the transaction could be started synchronously, which means
  // that the request was served from the cache (only supported for directory
  // listings).  ERR_IO_PENDING is returned to indicate that the
  // CompletionCallback will be notified once response info is available or if
  // an IO error occurs.  Any other return value indicates that the transaction
  // could not be started.
  //
  // Regardless of the return value, the caller is expected to keep the
  // request_info object alive until Destroy is called on the transaction.
  //
  // NOTE: The transaction is not responsible for deleting the callback object.
  //
  // Profiling information for the request is saved to |load_log| if non-NULL.
  virtual int Start(const FtpRequestInfo* request_info,
                    CompletionCallback* callback,
                    LoadLog* load_log) = 0;

  // Restarts the FTP transaction with authentication credentials.
  virtual int RestartWithAuth(const std::wstring& username,
                              const std::wstring& password,
                              CompletionCallback* callback) = 0;

  // Once response info is available for the transaction, response data may be
  // read by calling this method.
  //
  // Response data is copied into the given buffer and the number of bytes
  // copied is returned.  ERR_IO_PENDING is returned if response data is not
  // yet available.  The CompletionCallback is notified when the data copy
  // completes, and it is passed the number of bytes that were successfully
  // copied.  Or, if a read error occurs, the CompletionCallback is notified of
  // the error.  Any other negative return value indicates that the transaction
  // could not be read.
  //
  // NOTE: The transaction is not responsible for deleting the callback object.
  //
  virtual int Read(IOBuffer* buf,
                   int buf_len,
                   CompletionCallback* callback) = 0;

  // Returns the response info for this transaction or NULL if the response
  // info is not available.
  virtual const FtpResponseInfo* GetResponseInfo() const = 0;

  // Returns the load state for this transaction.
  virtual LoadState GetLoadState() const = 0;

  // Returns the upload progress in bytes.  If there is no upload data,
  // zero will be returned.
  virtual uint64 GetUploadProgress() const = 0;
};

}  // namespace net

#endif  // NET_FTP_FTP_TRANSACTION_H_


text:
/**
 * Created by brodriguez on 22/11/16.
 */
$(document).ready(function() {

    $( "#vencimiento" ).datepicker();
    $( "#ganancia" ).spinner();
    $( "#impuesto" ).spinner();

    if ($('#tieneimpuesto').is(':checked')){
        $('input:hidden[name="producto[tieneimpuesto]"]').val(1);
    } else {
        $('input:hidden[name="producto[tieneimpuesto]"]').val(0);
    }

    $("#tieneimpuesto").on('change', function(event){
        event.preventDefault();
        event.stopImmediatePropagation();
        if ($('#tieneimpuesto').is(':checked')){
            $( "#impuesto" ).attr('disabled',null);
            $( "#impuesto" ).attr('readonly',null);
            $('input:hidden[name="producto[tieneimpuesto]"]').val(1);
        } else {
            $( "#impuesto" ).attr('disabled','disabled');
            $( "#impuesto" ).attr('readonly','readonly');
            $('input:hidden[name="producto[tieneimpuesto]"]').val(0);
            $('#impuesto').val(0);
        }
        calcularMontoVenta();
    });

    $("#categoria").on('change', function(event){
        event.preventDefault();
        event.stopImmediatePropagation();
        var $select = $(this);
        var categoria = $select.val();
        $("#idcategoria").val(categoria);
    });

    $("#marca").on('change', function(event){
        event.preventDefault();
        event.stopImmediatePropagation();
        var $select = $(this);
        var marca = $select.val();
        $("#idmarca").val(marca);
    });

    $("input[type=radio][name=mayor]").on('change', function(event){
        event.preventDefault();
        event.stopImmediatePropagation();
        var $select = $(this);
        var mayor = $select.val();
        $("#unidadmedidaalmacen").val(mayor);
    });

    $("input[name='detal']:radio").on('change', function(event){
        event.preventDefault();
        event.stopImmediatePropagation();
        var $select = $(this);
        var detal = $select.val();
        $("#unidadmedidaventas").val(detal);
    });

    $("#fileupload").on('change', function(event){
        if (this.files && this.files[0]) {
            console.log("entre al  if");
            var filerdr = new FileReader();
            filerdr.onload = function(e) {
                $('#imageupload').attr('src', e.target.result);
            }
            filerdr.readAsDataURL(this.files[0]);
        } else {
            console.log("No entre al if");
            console.log(this);
        }
    });

    $("#preciocosto").on('change', function(event){
        event.preventDefault();
        event.stopImmediatePropagation();
        calcularMontoVenta();
    });

    $("#ganancia").on('change', function(event){
        event.preventDefault();
        event.stopImmediatePropagation();
        calcularMontoVenta();
    });

    $("#impuesto").on('change', function(event){
        event.preventDefault();
        event.stopImmediatePropagation();
        calcularMontoVenta();
    });

    function calcularMontoVenta() {
        var preciocosto = $('#preciocosto').val();
        var ganancia = $('#ganancia').val();
        var impuesto = $('#impuesto').val();
        var tieneimpuesto = $('#tieneimpuesto').val();
        var monto = preciocosto*(1+ganancia/100);
        if (tieneimpuesto = 1) {
            var montoventa = monto*(1+impuesto/100);
        } else {
            var montoventa = monto;
        }
        $('#preciounidad').val(montoventa);
    }
});


text:
package org.kie.workbench.common.forms.editor.client.handler;

import java.util.Arrays;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Event;
import javax.inject.Inject;

import com.google.gwt.user.client.ui.IsWidget;
import org.guvnor.common.services.project.client.context.WorkspaceProjectContext;
import org.jboss.errai.bus.client.api.messaging.Message;
import org.jboss.errai.common.client.api.Caller;
import org.jboss.errai.common.client.api.ErrorCallback;
import org.jboss.errai.ui.client.local.spi.TranslationService;
import org.kie.workbench.common.forms.editor.client.handler.formModel.FormModelsPresenter;
import org.kie.workbench.common.forms.editor.client.resources.i18n.FormEditorConstants;
import org.kie.workbench.common.forms.editor.client.type.FormDefinitionResourceType;
import org.kie.workbench.common.forms.editor.service.shared.FormEditorService;
import org.kie.workbench.common.profile.api.preferences.Profile;
import org.kie.workbench.common.services.shared.project.KieModuleService;
import org.kie.workbench.common.services.shared.validation.ValidationService;
import org.kie.workbench.common.widgets.client.handlers.DefaultNewResourceHandler;
import org.kie.workbench.common.widgets.client.handlers.NewResourcePresenter;
import org.kie.workbench.common.widgets.client.handlers.NewResourceSuccessEvent;
import org.uberfire.client.mvp.PlaceManager;
import org.uberfire.commons.data.Pair;
import org.uberfire.ext.editor.commons.client.validation.ValidatorWithReasonCallback;
import org.uberfire.ext.widgets.common.client.callbacks.HasBusyIndicatorDefaultErrorCallback;
import org.uberfire.ext.widgets.common.client.common.BusyIndicatorView;
import org.uberfire.workbench.events.NotificationEvent;
import org.uberfire.workbench.type.ResourceTypeDefinition;

@ApplicationScoped
public class NewFormDefinitionlHandler extends DefaultNewResourceHandler {

    private Caller<FormEditorService> modelerService;

    private FormDefinitionResourceType resourceType;

    private TranslationService translationService;

    private FormModelsPresenter formModelsPresenter;

    @Inject
    public NewFormDefinitionlHandler(final Caller<FormEditorService> modelerService,
                                     final FormDefinitionResourceType resourceType,
                                     final TranslationService translationService,
                                     final FormModelsPresenter formModelsPresenter,
                                     final WorkspaceProjectContext context,
                                     final Caller<KieModuleService> moduleService,
                                     final Caller<ValidationService> validationService,
                                     final PlaceManager placeManager,
                                     final Event<NotificationEvent> notificationEvent,
                                     final Event<NewResourceSuccessEvent> newResourceSuccessEvent,
                                     final BusyIndicatorView busyIndicatorView) {
        this.modelerService = modelerService;
        this.resourceType = resourceType;
        this.translationService = translationService;
        this.formModelsPresenter = formModelsPresenter;
        this.context = context;
        this.moduleService = moduleService;
        this.validationService = validationService;
        this.placeManager = placeManager;
        this.notificationEvent = notificationEvent;
        this.newResourceSuccessEvent = newResourceSuccessEvent;
        this.busyIndicatorView = busyIndicatorView;
    }

    @PostConstruct
    protected void setupExtensions() {
        extensions.add(Pair.newPair("", // not needed FormModelsPresenter describes the extension itself
                                    formModelsPresenter));
    }

    @Override
    public String getDescription() {
        return translationService.getTranslation(FormEditorConstants.NewFormDefinitionlHandlerForm);
    }

    @Override
    public IsWidget getIcon() {
        return resourceType.getIcon();
    }

    @Override
    public ResourceTypeDefinition getResourceType() {
        return resourceType;
    }

    @Override
    public List<Pair<String, ? extends IsWidget>> getExtensions() {
        formModelsPresenter.initialize(context.getActiveModule()
                                               .orElseThrow(() -> new IllegalStateException("Cannot get module root path without an active module."))
                                               .getRootPath());

        return super.getExtensions();
    }

    @Override
    public void validate(String baseFileName,
                         ValidatorWithReasonCallback callback) {

        boolean isValid = formModelsPresenter.isValid();

        if (!isValid) {
            callback.onFailure();
        } else {
            super.validate(baseFileName, callback);
        }
    }

    @Override
    public void create(final org.guvnor.common.services.project.model.Package pkg,
                       final String baseFileName,
                       final NewResourcePresenter presenter) {

        busyIndicatorView.showBusyIndicator(translationService.getTranslation(FormEditorConstants.NewFormDefinitionlHandlerSelectFormUse));

        modelerService.call(getSuccessCallback(presenter), getErrorCallback()).createForm(pkg.getPackageMainResourcesPath(),
                                                                                buildFileName(baseFileName, resourceType),
                                                                                formModelsPresenter.getFormModel());
    }

    protected ErrorCallback<Message> getErrorCallback() {
        return new HasBusyIndicatorDefaultErrorCallback(busyIndicatorView);
    }

    @Override
    public List<Profile> getProfiles() {
        return Arrays.asList(Profile.FULL);
    }
}


text:
//
//  ThirdLoginView.h
//  MiaowShow
//
//  Created by ALin on 16/6/13.
//  Copyright © 2016年 ALin. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef NS_ENUM(NSUInteger, LoginType) {
    LoginTypeSina,
    LoginTypeQQ,
    LoginTypeWechat
};

@interface ThirdLoginView : UIView
/** 点击按钮 */
@property (nonatomic, copy) void (^clickLogin)(LoginType type);
@end


text:
import java.util.Iterator;
import java.lang.NullPointerException;
import java.util.NoSuchElementException;
import java.lang.UnsupportedOperationException;

public class Deque<Item> implements Iterable<Item> {
    private int iNum; // size of the Deque
    private DecElement eHead; // first element
    private DecElement eTail; // last element

    // the identity element
    private class DecElement {
	private Item item;
	private DecElement next;
	private DecElement prev;

	public DecElement(Item initItem) {
	    next = null;
	    prev = null;
	    item = initItem;
	}
    }

    /**
     * construct an empty deque
     */
    public Deque() {
	iNum = 0;
    }

    /**
     * is the deque empty?
     *
     * @return boolean
     */
    public boolean isEmpty() {
	return iNum == 0;
    }

    /**
     *
     * @returnthe number of items on the deque
     */
    public int size() {
	return iNum;
    }

    /**
     * insert the item at the front
     *
     * @param item
     */
    public void addFirst(Item item) {
	if (item == null)
	    throw new java.lang.NullPointerException("No item passed.");
	DecElement eTemp;
	if(isEmpty()){
	    eHead = new DecElement(item);
	    eTail = eHead;
	}else{
        	eHead.next = new DecElement(item); // Create new firest
        	eTemp = eHead; // Save current first
        	eHead = eHead.next; // Set new eHead
        	eHead.prev = eTemp; // Finish init of the new eHead
	}
	iNum += 1; // Increment deque size
    }

    public void addLast(Item item) { // insert the item at the end
	if (item == null)
	    throw new java.lang.NullPointerException("No item passed.");
	DecElement eTemp;

	if(isEmpty()){
	    eHead = new DecElement(item);
	    eTail = eHead;
	}else{
        	eTail.prev = new DecElement(item); // Init new last element
        	eTemp = eTail;
        	eTail = eTail.prev;
        	eTail.next = eTemp;
	}
	iNum += 1; // Increment deque size
    }

    /**
     * delete and return the item at the front
     *
     * @return first item
     */
    public Item removeFirst() { //
	if (isEmpty())
	    throw new java.util.NoSuchElementException("No element!");
	Item iToReturn;
	iToReturn = eHead.item;
	if (iNum > 1) {
	    eHead = eHead.prev;
	    eHead.next = null;
	} else {
	    eHead = null;
	    eTail = null;
	}
	iNum -= 1;
	return iToReturn;
    }

    /**
     * delete and return the item at the end
     *
     * @return
     */
    public Item removeLast() {
	if (isEmpty())
	    throw new java.util.NoSuchElementException("No element!");

	Item iToReturn;
	iToReturn = eTail.item;
	if (iNum > 1) {
	    eTail = eTail.next;
	    eTail.prev = null;
	} else {
	    eHead = null;
	    eTail = null;
	}
	iNum -= 1;
	return iToReturn;
    }

    /**
     * Return an iterator to the deque that iterates through the items in FIFO
     * order.
     */
    public Iterator<Item> iterator() {
	return new ListIterator();
    }

    // an iterator, doesn't implement remove() since it's optional
    private class ListIterator implements Iterator<Item> {
	private DecElement current = eHead;

	public boolean hasNext() {
	    return current != null;
	}

	public void remove() {
	    throw new java.lang.UnsupportedOperationException(
		    "No implementation of remove!");
	}

	public Item next() {
	    if (!hasNext())
		throw new NoSuchElementException();
	    Item item = current.item;
	    current = current.prev;
	    return item;
	}
    }

    public static void main(String[] args){
	Deque<Integer> tDeq = new Deque<Integer>();
	int i;
	for(i = 0 ; i < 10 ; i++){
	    tDeq.addFirst(i);
	}

	for (int num : tDeq) {
	    StdOut.println(num);
	}
	StdOut.println("Hello world!");
    }
    // java.util.NoSuchElementException if the client calls the next() method in
    // the iterator and there are no more items to return
    // in iterator java.lang.UnsupportedOperationException
    // Throw a java.lang.NullPointerException if the client attempts to add a
    // null item; throw a java.util.NoSuchElementException
    // if the client attempts to remove an item from an empty deque; throw a
    // java.lang.UnsupportedOperationException
    // if the client calls the remove() method in the iterator; throw a
    // java.util.NoSuchElementException
    // if the client calls the next() method in the iterator and there are no
    // more items to return.

}


text:
/**
 * @file
 * @brief TODO documentation for general_test.c -- Bulychev Anton
 *
 * @date Apr 2, 2012
 * @author Bulychev Anton
 */

#include <embox/test.h>

#include <errno.h>

#include <kernel/thread.h>
#include <kernel/sched.h>
#include <kernel/sched/waitq.h>
#include <kernel/thread/waitq.h>

EMBOX_TEST_SUITE("Scheduler strategy general test");

TEST_CASE("sleep/wake") {
	struct waitq wq;

	waitq_init(&wq);
	test_assert_equal(WAITQ_WAIT_TIMEOUT(&wq, 0, 10), -ETIMEDOUT);
}


text:
package modbusone

import (
	"encoding/hex"
	"errors"
	"fmt"
	"sync/atomic"
	"time"
)

// RTUClient implements Client/Master side logic for RTU over a SerialContext to
// be used by a ProtocolHandler.
type RTUClient struct {
	com                  SerialContext
	packetReader         PacketReader
	SlaveID              byte
	serverProcessingTime time.Duration
	actions              chan rtuAction
}

// Client interface can both start and serve transactions.
type Client interface {
	ServerCloser
	RTUTransactionStarter
	DoTransaction(req PDU) error
}

// Asserts that RTUClient implements Client.
var _ Client = &RTUClient{}

// NewRTUClient create a new client communicating over SerialContext with the
// given slaveID as default.
func NewRTUClient(com SerialContext, slaveID byte) *RTUClient {
	pr, ok := com.(PacketReader)
	if !ok {
		pr = NewRTUPacketReader(com, true)
	}
	r := RTUClient{
		com:                  com,
		packetReader:         pr,
		SlaveID:              slaveID,
		serverProcessingTime: time.Second,
		actions:              make(chan rtuAction),
	}
	return &r
}

// SetServerProcessingTime sets the time to wait for a server response, the total
// wait time also includes the time needed for data transmission.
func (c *RTUClient) SetServerProcessingTime(t time.Duration) {
	c.serverProcessingTime = t
}

// GetTransactionTimeOut returns the total time to wait for a transaction
// (server response) to time out, given the expected length of RTU packets.
// This function is also used internally to calculate timeout.
func (c *RTUClient) GetTransactionTimeOut(reqLen, ansLen int) time.Duration {
	l := reqLen + ansLen
	return c.com.BytesDelay(l) + c.serverProcessingTime
}

type rtuAction struct {
	t       clientActionType
	data    RTU
	err     error
	errChan chan<- error
}

// ErrServerTimeOut is the time out error for StartTransaction.
var ErrServerTimeOut = errors.New("server timed out")

type clientActionType int

const (
	clientStart clientActionType = iota
	clientRead
	clientError
)

func (a clientActionType) String() string {
	switch a {
	case clientStart:
		return "start"
	case clientRead:
		return "read"
	case clientError:
		return "error"
	}
	return fmt.Sprintf("clientActionType %d", a)
}

// Serve serves RTUClient handlers.
func (c *RTUClient) Serve(handler ProtocolHandler) error {
	defer c.Close()
	go func() {
		// Reader loop that always ready to received data. This make sure that read
		// data is always new(ish), to dump data out that is received during an
		// unexpected time.
		for {
			rb := make([]byte, MaxRTUSize)
			n, err := c.packetReader.Read(rb)
			if err != nil {
				debugf("RTUClient read err:%v\n", err)
				c.actions <- rtuAction{t: clientError, err: err}
				c.Close()
				break
			}
			r := RTU(rb[:n])
			debugf("RTUClient read packet:%v\n", hex.EncodeToString(r))
			c.actions <- rtuAction{t: clientRead, data: r}
		}
	}()

	for {
		act := <-c.actions
		switch act.t {
		default:
			atomic.AddInt64(&c.com.Stats().OtherDrops, 1)
			debugf("RTUClient drop unexpected: %v", act)
			continue
		case clientError:
			return act.err
		case clientStart:
		}
		ap := act.data.fastGetPDU()
		afc := ap.GetFunctionCode()
		if afc.IsWriteToServer() {
			data, err := handler.OnRead(ap)
			if err != nil {
				act.errChan <- err
				continue
			}
			act.data = MakeRTU(act.data[0], ap.MakeWriteRequest(data))
			ap = act.data.fastGetPDU()
		}
		time.Sleep(c.com.MinDelay())
		_, err := c.com.Write(act.data)
		if err != nil {
			act.errChan <- err
			return err
		}
		if act.data[0] == 0 {
			time.Sleep(c.com.BytesDelay(len(act.data)))
			act.errChan <- nil // always success
			continue           // do not wait for read on multicast
		}

		timeOutChan := time.After(c.GetTransactionTimeOut(len(act.data), MaxRTUSize))

	READ_LOOP:
		for {
		SELECT:
			select {
			case <-timeOutChan:
				act.errChan <- ErrServerTimeOut
				break READ_LOOP
			case react := <-c.actions:
				switch react.t {
				default:
					err := fmt.Errorf("unexpected action:%s", react.t)
					act.errChan <- err
					return err
				case clientError:
					return react.err
				case clientRead:
					// test for read error
					if react.err != nil {
						return react.err
					}
				}
				if react.data[0] != act.data[0] {
					atomic.AddInt64(&c.com.Stats().IDDrops, 1)
					debugf("RTUClient unexpected slaveId:%v in %v\n", act.data[0], hex.EncodeToString(react.data))
					break SELECT
				}
				rp, err := react.data.GetPDU()
				if err != nil {
					if errors.Is(err, ErrorCrc) {
						atomic.AddInt64(&c.com.Stats().CrcErrors, 1)
					} else {
						atomic.AddInt64(&c.com.Stats().OtherErrors, 1)
					}
					act.errChan <- err
					break READ_LOOP
				}
				hasErr, fc := rp.GetFunctionCode().SeparateError()
				if hasErr && fc == afc {
					atomic.AddInt64(&c.com.Stats().OtherErrors, 1)
					handler.OnError(ap, rp)
					act.errChan <- fmt.Errorf("server reply with exception:%v", hex.EncodeToString(rp))
					break READ_LOOP
				}
				if !IsRequestReply(act.data.fastGetPDU(), rp) {
					atomic.AddInt64(&c.com.Stats().OtherErrors, 1)
					act.errChan <- fmt.Errorf("unexpected reply:%v", hex.EncodeToString(rp))
					break READ_LOOP
				}
				if afc.IsReadToServer() {
					// read from server, write here
					bs, err := rp.GetReplyValues()
					if err != nil {
						atomic.AddInt64(&c.com.Stats().OtherErrors, 1)
						act.errChan <- err
						break READ_LOOP
					}
					err = handler.OnWrite(ap, bs)
					if err != nil {
						atomic.AddInt64(&c.com.Stats().OtherErrors, 1)
					}
					act.errChan <- err // success if nil
					break READ_LOOP
				}
				act.errChan <- nil // success
				break READ_LOOP
			}
		}
	}
}

// Close closes the client and closes the connection.
func (c *RTUClient) Close() error {
	return c.com.Close()
}

// DoTransaction starts a transaction, and returns a channel that returns an error
// or nil, with the default slaveID.
//
// DoTransaction is blocking.
//
// For read from server, the PDU is sent as is (after been warped up in RTU)
// For write to server, the data part given will be ignored, and filled in by data from handler.
func (c *RTUClient) DoTransaction(req PDU) error {
	errChan := make(chan error)
	c.StartTransactionToServer(c.SlaveID, req, errChan)
	return <-errChan
}

// StartTransactionToServer starts a transaction, with a custom slaveID.
// errChan is required, an error is set is the transaction failed, or
// nil for success.
//
// StartTransactionToServer is not blocking.
//
// For read from server, the PDU is sent as is (after been warped up in RTU)
// For write to server, the data part given will be ignored, and filled in by data from handler.
func (c *RTUClient) StartTransactionToServer(slaveID byte, req PDU, errChan chan error) {
	c.actions <- rtuAction{t: clientStart, data: MakeRTU(slaveID, req), errChan: errChan}
}

// RTUTransactionStarter is an interface implemented by RTUClient.
type RTUTransactionStarter interface {
	StartTransactionToServer(slaveID byte, req PDU, errChan chan error)
}

// DoTransactions runs the reqs transactions in order.
// If any error is encountered, it returns early and reports the index number and
// error message.
func DoTransactions(c RTUTransactionStarter, slaveID byte, reqs []PDU) (int, error) {
	errChan := make(chan error)
	for i, r := range reqs {
		c.StartTransactionToServer(slaveID, r, errChan)
		err := <-errChan
		if err != nil {
			return i, err
		}
	}
	return len(reqs), nil
}

// MakePDURequestHeaders generates the list of PDU request headers by splitting quantity
// into allowed sizes.
// Returns an error if quantity is out of range.
func MakePDURequestHeaders(fc FunctionCode, address, quantity uint16, appendTO []PDU) ([]PDU, error) {
	return MakePDURequestHeadersSized(fc, address, quantity, fc.MaxPerPacket(), appendTO)
}

// MakePDURequestHeadersSized generates the list of PDU request headers by splitting quantity
// into sizes of maxPerPacket or less.
// Returns an error if quantity is out of range.
//
// You can use FunctionCode.MaxPerPacketSized to calculate one with the wanted byte length.
func MakePDURequestHeadersSized(fc FunctionCode, address, quantity uint16, maxPerPacket uint16, appendTO []PDU) ([]PDU, error) {
	if uint(address)+uint(quantity) > uint(fc.MaxRange()) {
		return nil, fmt.Errorf("quantity is out of range")
	}
	q := maxPerPacket
	for quantity > 0 {
		if quantity < maxPerPacket {
			q = quantity
		}
		pdu, err := fc.MakeRequestHeader(address, q)
		if err != nil {
			return nil, err
		}
		appendTO = append(appendTO, pdu)
		address += q
		quantity -= q
	}
	return appendTO, nil
}


text:
// @(#)System.java   1/2004
// Copyright (c) 1998-2004, Distributed Real-time Computing Lab (DRCL)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
// 3. Neither the name of "DRCL" nor the names of its contributors may be used
//    to endorse or promote products derived from this software without specific
//    prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

package drcl.ruv;

import java.util.*;
import drcl.comp.*;
import drcl.comp.tool.ComponentTester;

/**
 * The entry class of the DRCL RUntime Virtual (RUV) system.
 * It will set up a terminal along with a shell and several system "directories":
 *

 *
/.system: The System object itself.
 *
/.system/monitor: the system monitor ({@link SystemMonitor}).
 *
/.term: stores all the terminals and shells.
 *

 * One may specify the shell class, the terminal class and/or the initial script to execute.
 * By default, Dterm and ShellTcl will be used to start the system.
 * The complete usage is as follows:

 *
drcl.ruv.System ?-auenh? ?-s &ltshell_class&gt? ?-t &ltterminal_class&gt? ?&ltinit_script&gt?
 *      -a	use the RUV system as part of other programs (e.g. GUI), where "exit" or
 *          "quit" only terminates the terminal instead of the Java program.
 *      -u	uninteractive execution; no terminal is created.
 *      -e	end the Java program when there is no activity in the system; used with the "-u" option.
 *      -h	display help.
 *      -n	no terminal display.
 *

 */
public class System extends Component
{
	// dedicated ACARuntime for shells and terms
	static drcl.comp.ACARuntime RUNTIME = new ARuntime("ruv");

	static System system = null;
	static Shell backupShell = null; // for diagnosis when something goes wrong with user's shell
	boolean exit2quit = true; // command "exit" to quit?
	Component termDir = null; // directory that stores all terminals and shells
	SystemMonitor systemMonitor = null; // system monitor
	static Hashtable htRuntime; // monitoring runtimes for -e option

	/** Creates a new terminal in the RUV system. */
	public static void newTerminal()
	{	if (system != null) system._newTerminal();	}

	/** Creates a new terminal in the RUV system and executes the script in the terminal. */
	public static void newTerminal(String initScript_, String[] args_)
	{	if (system != null) system._newTerminal(initScript_, args_);	}

	/** Resets all the components in the RUV system. */
	public static void resetSystem()
	{
		if (system == null) return;
		Component[] cc_ = Component.Root.getAllComponents();
		for (int i=0; i<cc_.length; i++) {
			if (cc_[i] == system) continue;
			if (cc_[i] == system.termDir) continue;
			cc_[i].reset();
		}
	}

	/** Removes all the components, except system objects, in the RUV system. */
	public static void cleanUpSystem()
	{
		if (system == null) return;
		Component[] cc_ = Component.Root.getAllComponents();
		for (int i=0; i<cc_.length; i++) {
			if (cc_[i] == system) continue;
			if (cc_[i] == system.termDir) continue;
			cc_[i].reset();
			Component.Root.removeComponent(cc_[i]);
		}
	}

	public static void main(String[] args)
	{
		// -s Shell class
		// -t Term class
		// -w wish executable
		// -h help
		// -a use ruv as auxiliary in other programs (e.g. in GUI)
		// -u uninteractive, no terminal
		// -e end program if no activity in all runtimes
		// -d debug
		// -n no terminal display
		// init script

		String shellClass_ = null, termClass_ = null, initScript_ = null;
		boolean auxiliary_ = false; // true if called by other Java program
		boolean debug_ = false;
		boolean uninteractive_ = false;
		boolean end_ = false;
		boolean noTerminalDisplay_ = false;
		String[] scriptArgs_ = null;

		if (args != null) {
			// look for help first
			for (int i=0; i<args.length; i++) {
				if (args[i].startsWith("-") && args[i].indexOf("h") >0) {
					usage();
				}
			}

			for (int i=0; i<args.length; i++) {
				if (args[i].startsWith("-s")) shellClass_ = args[++i];
				else if (args[i].startsWith("-t")) termClass_ = args[++i];
				else if (args[i].startsWith("-")) {
					if (args[i].indexOf("a") > 0) auxiliary_ = true;
					if (args[i].indexOf("u") > 0) uninteractive_ = true;
					if (args[i].indexOf("e") > 0) end_ = true;
					if (args[i].indexOf("d") > 0) debug_ = true;
					if (args[i].indexOf("n") > 0) noTerminalDisplay_ = true;
					if (args[i].indexOf("h") > 0) { usage(); java.lang.System.exit(0); }
					if (args[i].indexOf("w") > 0)
						try {
							java.lang.Runtime.getRuntime().exec(args[++i]);
							return;
						}
						catch (Exception e_) {
							java.lang.System.out.println(e_.toString());
						}
				}
				else {
					initScript_ = args[i];
					scriptArgs_ = new String[args.length - i - 1];
					java.lang.System.arraycopy(args, i+1, scriptArgs_, 0, scriptArgs_.length);
					break;
				}
			}
		}

		if (system != null) {
			system.exit2quit = !auxiliary_;
			if (!uninteractive_)
				newTerminal(initScript_, scriptArgs_);
			else
				system.__execute(initScript_, scriptArgs_);
			return;
		}

		Shell shell_ = null;
		Term term_ = null;

		if (debug_) java.lang.System.out.println("Creating terminal...");
		if (uninteractive_) {
			term_ = new DummyTerm();
		}
		else {
			RUVOutputManager.activate();

			try {
				if (termClass_ != null)
					term_ = (Term)Class.forName(termClass_).newInstance();
			} catch (Exception e_) {
				e_.printStackTrace();
				drcl.Debug.error("RUV System", "Startup error: " + e_ + "\n");
				drcl.Debug.error(null, "Use Dterm instead.\n");
			}
			if (term_ == null) {
				// X: bug in Swing?
				try {
					term_ = new Dterm();
				}
				catch (Exception e2_) {
					try {
						term_ = new Dterm();
					}
					catch (Exception e3_) {
						e3_.printStackTrace();
						drcl.Debug.error("RUV System", "Cannot create Dterm: " + e3_ + "\n");
					}
				}
			}
		}

		if (debug_) java.lang.System.out.println("Creating shell...");

		// Try the shell class assigned by user
		if (shellClass_ != null)
			try {
				shell_ = (Shell)Class.forName(shellClass_).newInstance();
			} catch (Exception e_) {
				try {
					if (shellClass_.indexOf('.') < 0) {
						e_ = null;
						shell_ = (Shell)Class.forName("drcl.ruv." + shellClass_).newInstance();
					}
				}
				catch (Exception e2_) {
					e_ = e2_;
				}
				if (e_ != null) {
					drcl.Debug.error("RUV System", "Startup error: " + e_ + "\n");
					drcl.Debug.error(null, "Use ShellTcl instead.\n");
				}
			}

		// use ShellTcl
		if (shell_ == null && (shellClass_ == null || !shellClass_.equals("drcl.ruv.ShellTcl")))
			try {
				shell_ = new ShellTcl();
			}
			catch (Exception e_) {
				//e_.printStackTrace();
				drcl.Debug.error("RUV System",
								 (shellClass_ == null? "": "Even ")
								 + "ShellTcl cannot be initiated: " + e_ + ".");
			}

		// can't go on
		if (shell_ == null) java.lang.System.exit(1);
		shell_.setPrompt(shell_.getName().toUpperCase() + "0> ");
		if (!uninteractive_ && term_ != null) {
			term_.setPrompt(shell_.getPrompt());
			term_.setTerminalDisplayEnabled(!noTerminalDisplay_);
			term_.show(); // make term show as soon as possible
			term_.setTitle(shell_.getName().toUpperCase() + "0");
			term_.setID(shell_.getName().toLowerCase() + "0");
		}
		else if (term_ != null)
			term_.setID("uninteractive");

		if (debug_) java.lang.System.out.println("Creating RUV system components...");

		// /.term
		System termDir_ = new System(".term");
		Component.Root.addComponent(termDir_);
		termDir_.setRuntime(RUNTIME);
		Thread.currentThread().yield();

		if (uninteractive_)
			shell_.setID("uninteractive_" + shell_.getName().toLowerCase() + "_shell");
		else
			shell_.setID(shell_.getName().toLowerCase() + "0_shell");
		termDir_.addComponent(shell_);

		// connect shell_ and term_
		if (term_ != null) {
			termDir_.addComponent(term_);
			term_.port.connect(shell_.port);
			shell_.result.connectTo(term_.result);
		}

		// /.system, /.system/trace, /.system/rt
		System system_ = system = new System();
		system_.setID(".system");
		Component.Root.addComponent(system_);
		system_.setRuntime(RUNTIME);
		system_.exit2quit = !auxiliary_;
		system_.termDir = termDir_;
		if (term_ != null) term_.addExitListener(system_.termExitListener);
		RUVOutputManager.addOutput(term_);
		WrapperComponent javart_ = new WrapperComponent("rt");
		system_.addComponent(javart_);
		javart_.setObject(java.lang.Runtime.getRuntime());

		if (!uninteractive_) system_.background();

		if (debug_) java.lang.System.out.println("Setting up system monitor...");

		// /.system/monitor
		SystemMonitor monitor_ = system_.systemMonitor = new SystemMonitor("monitor");
		system_.addComponent(monitor_);
		monitor_.setTraceEnabled(true);
		monitor_.setGarbageDisplayEnabled(true);
		monitor_.setDebugEnabled(true);
		monitor_.setErrorNoticeEnabled(true);
		monitor_.setEventExportEnabled(true);
		monitor_.setRcvEnabled(true);

		if (initScript_ != null && initScript_.length() > 0) {
			if (debug_) java.lang.System.out.println("Run the script...");

			drcl.comp.Util.inject(ShellContract.createExecuteFileRequest(initScript_, scriptArgs_),
				shell_.port);
		}

		if (debug_) java.lang.System.out.println("RUV system is ready.");

		if (end_)
			// start a thread to probe system activities, quit the program if there isn't any
			new Thread() {
				public void run()
				{
					Thread current_ = Thread.currentThread();
					current_.setPriority(Thread.MIN_PRIORITY);
					htRuntime = new Hashtable();
					for (;;) {
						try {
							current_.sleep(1500);
						}
						catch (Exception e_) {
							e_.printStackTrace();
							java.lang.System.exit(0);
						}
						synchronized (htRuntime) { _scanSystem(Component.Root); }
						boolean alive_ = false;
						for (Enumeration e_ = htRuntime.keys(); e_.hasMoreElements(); ) {
							ACARuntime m_ = (ACARuntime)e_.nextElement();
							if (!m_.isIdle()) { alive_ = true; break; }
						}
						if (!alive_) {
							java.lang.System.exit(0);
						}
					}
				}
			}.start();
	}

	static void _scanSystem(Component root_)
	{
		htRuntime.clear();
		Vector v_ = new Vector(100, 100);
		v_.addElement(root_);
		while (v_.size() > 0) {
			root_ = (Component)v_.lastElement();
			v_.setSize(v_.size()-1);
			ACARuntime m_ = drcl.comp.Util.getRuntime(root_);
			if (m_ != null) htRuntime.put(m_, m_);
			Component[] cc_ = root_.getAllComponents();
			for (int j=0; j<cc_.length; j++)
				v_.addElement(cc_[j]);
		}
	}

	public System()
	{ super(); }

	public System(String id_)
	{ super(id_); }

	public String info()
	{
		if (htRuntime != null) {
			StringBuffer sb_ = new StringBuffer();
			synchronized (htRuntime) {
				for (Enumeration e_ = htRuntime.keys(); e_.hasMoreElements(); ) {
					ACARuntime m_ = (ACARuntime)e_.nextElement();
					if (!m_.isIdle())
						sb_.append(m_.diag() + "\n");
				}
			}
			if (sb_.length() == 0)
				return "All runtimes are idle.\n";
			else
				return sb_.toString();
		}
		else
			return "No info is available.";
	}

	// avoid accidentally changing this
	/** Overrides {@link Component#setRuntime(ACARuntime)} to prevent changing the runtime by accident. */
	protected void setRuntime(ACARuntime m_)
	{ if (m_ == RUNTIME) super.setRuntime(m_); }

	static Shell getBackupShell()
	{ return backupShell; }

	static void usage()
	{
		java.lang.System.out.println("System [-ubh] [-s shell_class] [-t term_class] [init script]");
		java.lang.System.out.println("Options:");
		java.lang.System.out.println("    -u: use the RUV system as part of other programs (e.g. GUI).");
		java.lang.System.out.println("    -b: execute a script uninteractively.");
		java.lang.System.out.println("    -e: end the program when simulation is stopped .");
		java.lang.System.out.println("    -h: display help.");
		java.lang.System.exit(1);
	}

	void background()
	{
		//Thread thread_ = new Thread() {
		//	// create things in background
		//	public void run()
		//	{
				try {
					synchronized (System.this) {
						if (backupShell == null) {
							backupShell = new ShellTcl("backup");
							if (termDir != null)
								termDir.addComponent(backupShell);
						}
					}
				}
				catch (Exception e_) {
					e_.printStackTrace();
				}
		//	}
		//};
		//thread_.setPriority(Thread.MIN_PRIORITY);
		//thread_.start();
	}

	/** Creates a new terminal in the RUV system.
	 */
	public void _newTerminal()
	{ _newTerminal(null, null); }

	/** Creates a new terminal in the RUV system and executes the script in the terminal.
	 */
	public void _newTerminal(String initScript_, String[] args_)
	{
		try {
			Term term_ = new Dterm();
			Shell shell_ = new ShellTcl();
			int i = 0;
			for (; termDir.containsComponent("tcl" + i + "_shell"); i++);
			term_.setID("tcl" + i);
			shell_.setID("tcl" + i + "_shell");
			addTerminal(term_, shell_, initScript_, args_);
		}
		catch (Exception e_) {
			e_.printStackTrace();
		}
	}

	public void addTerminal(Term terminal_, Shell shell_, String initScript_, String[] args_)
	{
		termDir.addComponent(shell_);
		if (terminal_ != null) {
			terminal_.addExitListener(termExitListener);
			termDir.addComponent(terminal_);
			terminal_.port.connect(shell_.port);
			shell_.result.connectTo(terminal_.result);
			shell_.setPrompt(terminal_.getID().toUpperCase() + "> ");
			terminal_.setTitle(terminal_.getID().toUpperCase());
			terminal_.setPrompt(shell_.getPrompt());
			terminal_.show();
			RUVOutputManager.addOutput(terminal_);
		}

		if (initScript_ != null && initScript_.length() > 0)
			drcl.comp.Util.inject( ShellContract.createExecuteFileRequest(initScript_, args_), shell_.port);
	}

	// execute the script in background, create a shell if necessary
	void __execute(String initScript_, String[] args_)
	{
		try {
			Shell shell_ = (Shell)termDir.getComponent(".background");
			if (shell_ == null) shell_ = new ShellTcl(".background");
			addTerminal(null, shell_, initScript_, args_);
		}
		catch (Exception e_) {
			e_.printStackTrace();
		}
	}

	void showThreads()
	{
	}

	TermExitListener termExitListener =  new TermExitListener() {
		public void termExit(Term which_, String exitOrQuit_)
		{
			termDir.removeComponent(which_);
			//java.lang.System.out.println("System.termExit(): '" + exitOrQuit_ + "'");
			RUVOutputManager.removeOutput(which_);
			if (!exit2quit) return;
			if (exitOrQuit_.equals(Shell.COMMAND_QUIT)) java.lang.System.exit(0);

			Component[] cc_ = termDir.getAllComponents();
			for (int i=0; i<cc_.length; i++) {
				Component c_ = cc_[i];
				if (c_ instanceof Term) {
					// XX: remove the corresponding shell
					return;
				}
			}
			java.lang.System.exit(0);
		}
	};

	public static Term getTerminal(Shell shell_)
	{
		Port[] pp_ = shell_.port.getPeers();
		for (int i=0; i<pp_.length; i++)
			if (pp_[i].host instanceof Term)
				return (Term)pp_[i].host;
		return null;
	}
}