text:
package org.cf.resequencer.patch;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringEscapeUtils;
import org.cf.resequencer.Console;
import org.cf.resequencer.sequence.ResourceItem;

import com.memetix.mst.detect.Detect;
import com.memetix.mst.language.Language;
import com.memetix.mst.translate.Translate;

/**
 *
 * @author Caleb Fenton
 */
public class SmaliHinter {
    public static long HintsAdded;

    public static boolean ShouldTranslate;
    private static int TranslateBatchSize = 25;

    static private String[] LineArray;

    public static void enableTranslations() {
        // Microsoft Bing API key
        // the developers use this key: 0B4B2CAA973775DBE72569A29C1A08DA55C88441
        // lolololol but we wont use it because we're nice
        String key = "";
        // key = "0B4B2CAA973775DBE72569A29C1A08DA55C88441";
        Translate.setKey(key);
        Detect.setKey(key);

        ShouldTranslate = true;
    }

    /**
     *
     * @param sf
     */
    public static void generateHints(SmaliFile sf) {
        generateHints(sf, null);
    }

    /**
     *
     * @param sf
     * @param appRes
     */
    public static void generateHints(SmaliFile sf, List<ResourceItem> appRes) {
        File f = new File(sf.FullFilePath);
        Console.debug("Hinting " + sf.FileName + " (" + f.length() + " bytes)");

        LineArray = sf.FileLines.split("[\r\n]");

        if (appRes != null) {
            hintResourceStrings(sf, appRes);
        }

        hintArrayData(sf);
        hintHexLiterals(sf);
        hintClassInitVals(sf);
        hintDebugInfo(sf);

        if (ShouldTranslate) {
            translateStrings(sf);
        }
    }

    private static void hintDebugInfo(SmaliFile sf) {
        Pattern p = Pattern.compile("(?m)^[\\t ]*\\.source ");
        Matcher m = p.matcher(sf.FileLines);

        if (!m.find()) {
            // no .source directive. let's add one.
            String thisClass;
            String superClass;
            String interfaceClass = "";

            p = Pattern.compile("(?m)^[\\t ]*\\.implements L(\\S+?);\\s*");
            m = p.matcher(sf.FileLines);
            if (m.find()) {
                interfaceClass = m.group(1).replace("/", ".");
            }

            // .*? to account for public, private, static, final etc.
            p = Pattern.compile("(?m)^[\\t ]*\\.class .*?L(\\S+?);\\s*");
            m = p.matcher(sf.FileLines);
            m.find();
            thisClass = m.group(1).substring(m.group(1).lastIndexOf("/") + 1);

            p = Pattern.compile("(?m)^[\\t ]*\\.super L(\\S+?);\\s*");
            m = p.matcher(sf.FileLines);
            m.find();
            superClass = m.group(1).replace("/", ".");

            StringBuilder insert = new StringBuilder();
            insert.append(".source \"")
                    .append(thisClass)
                    .append("_sup-")
                    .append(superClass);

            if (!interfaceClass.isEmpty()) {
                insert.append("_impl-").append(interfaceClass);
            }
            insert.append("\"\n\n");

            HintsAdded++;
            sf.addInsert(m.end(), insert.toString());
        }

        p = Pattern.compile("(?m)^[\\t ]*.line \\d+");
        m = p.matcher(sf.FileLines);

        if (!m.find()) {
            // no .line directives. let's add some.

            /*
             * Add .line directive in the following places: - before any invoke-* - before every const - before every
             * if-* - before every check-cast, new-instance - before every iget*, iput* - before every return
             */

            p = Pattern.compile("(?m)^[\\t ]*(invoke|const|if|check-cast|new-instance|iget|iput|return)");
            m = p.matcher(sf.FileLines);

            int line = 1;
            StringBuilder insert;
            while (m.find()) {
                insert = new StringBuilder("    .line ");
                insert.append(line);
                insert.append('\n');
                HintsAdded++;
                sf.addInsert(m.start(), insert.toString());

                line++;
            }
        }
    }

    private static void hintClassInitVals(SmaliFile sf) {

    }

    private static void hintResourceStrings(SmaliFile sf, List<ResourceItem> appRes) {

        Pattern p = Pattern.compile("(?im)^[ ]*const(/high16)? [vp]\\d+, 0x(7f[0-9a-f]{1,6})");
        Matcher m = p.matcher(sf.FileLines);

        while (m.find()) {
            Long resID = Long.parseLong(m.group(2), 16);

            StringBuilder insert = new StringBuilder("    # res type=");
            if (!appRes.isEmpty()) {
                ResourceItem resItem = findResItemByID(appRes, resID);

                if (resItem != null) {
                    insert.append(resItem.Type);
                    insert.append(" name=");
                    insert.append(resItem.Name);

                    if (resItem.Type.equals("string")) {
                        insert.append(" val=\"");
                        insert.append(resItem.Value);
                        insert.append('"');
                    }
                } else {
                    insert.append("possibly not resource / unknown res ID");
                }
            } else {
                insert.append("error parsing resources");
            }

            insert.append('\n');

            HintsAdded++;

            String finalInsert = insert.toString().replaceAll("[\\p{Cntrl}&&[^\\n]]", "?");
            sf.addInsert(m.start(), finalInsert);
        }
    }

    private static ResourceItem findResItemByID(List<ResourceItem> appRes, long resID) {
        for (ResourceItem resItem : appRes) {
            if (resItem.ID == resID) {
                return resItem;
            }
        }

        return null;
    }

    private static void hintArrayData(SmaliFile sf) {
        /*
         * # str value="VT" :array_1 .array-data 0x2 0x56t 0x0t 0x54t 0x0t .end array-data
         */

        Pattern p = Pattern
                        .compile("(?im)^[ ]*:array_[0-9a-f]+\\s+\\.array-data 0x([0-9a-f]+)\\s+((0x[0-9a-f]+t\\s+)+)\\s+\\.end array-data");

        // without looping through each line, sometimes there is a stackoverflow
        // because too many results are found
        int posOffset = 0;
        for (String line : LineArray) {
            Matcher m = p.matcher(line);

            while (m.find()) {
                int wordSize = Integer.parseInt(m.group(1), 16);

                // from chunky to smoooth
                String[] hexVals = m.group(2).replaceAll("0x", "").split("t\\s*");
                int wordCount = hexVals.length / wordSize;
                StringBuilder insert = new StringBuilder("    # str value=\"");
                // baksmali seems to always put this stuff in little endian
                for (int i = 0; i < wordCount; i++) {
                    StringBuilder nextVal = new StringBuilder("");
                    for (int j = wordSize - 1; j >= 0; j--) {
                        nextVal.append(hexVals[(i * wordSize) + j]);
                    }

                    long longVal = 0;
                    try {
                        longVal = Long.parseLong(nextVal.toString(), 16);
                    } catch (NumberFormatException e) {
                        longVal = 0;
                        Console.warn("Array data too big to parse: " + nextVal + " found while hinting "
                                        + sf.FullFilePath);
                    }

                    // insert += String.valueOf((char)longVal);
                    insert.append((char) longVal);
                }

                insert.append('\n');

                HintsAdded++;
                String finalInsert = insert.toString().replaceAll("[\\p{Cntrl}&&[^\\n]]", "");
                sf.addInsert(posOffset + m.start(), finalInsert);
            }
        }
    }

    private static void hintHexLiterals(SmaliFile sf) {
        /*
         * # base10=58 char=':' const/16 v3, 0x3a
         */

        Pattern p = Pattern.compile("(?im)^.*?, (-)?0x([0-9a-f]{2,})[l]?$");

        int posOffset = 0;
        for (String line : LineArray) {
            Matcher m = p.matcher(line);

            while (m.find()) {
                // 1 = possibly negative, 2 = number without 0x
                StringBuilder strVal = new StringBuilder(m.group(2).toLowerCase());
                if (m.group(1) != null) {
                    strVal.append(m.group(1)).append(strVal);
                }

                // do not add base 10 hint for resource ids
                if (strVal.toString().startsWith("7f") && (strVal.length() == 8)) {
                    continue;
                }

                long longVal = Long.parseLong(strVal.toString(), 16);

                // sorry, you should just learn hex
                if ((longVal > -16) && (longVal < 16)) {
                    continue;
                }

                // String insert = "    # base10=" + longVal;
                StringBuilder insert = new StringBuilder("    # base10=");
                insert.append(longVal);

                // printable character range
                if ((longVal >= 0x20) && (longVal <= 0xFFFC)) {
                    insert.append(" char='");
                    insert.append((char) longVal);
                    insert.append('\'');
                }

                HintsAdded++;
                sf.addInsert(posOffset + m.start(), insert.toString() + "\n");
            }

            posOffset += line.length() + 1;
        }
    }

    private static void translateStrings(SmaliFile sf) {
        /*
         * # trans="Initializing..." lang=Japanese const-string v1, "\u521d\u671f\u5316\u4e2d\u3067\u3059..."
         */

        Pattern p = Pattern.compile("(?im)^[ \\t]*const-string [vp]\\d+, \\\"(.*?)\\\"$");

        List<String> foundStrings = new ArrayList<String>();
        List<String> foundStringsOrig = new ArrayList<String>();
        List<Integer> foundPos = new ArrayList<Integer>();

        int posOffset = 0;
        for (String line : LineArray) {
            Matcher m = p.matcher(line);

            while (m.find()) {
                // group0 = const-string v1, "\u521d\u671f\u5316\u4e2d\u3067\u3059..."
                // group1 = \u521d\u671f\u5316\u4e2d\u3067\u3059...

                String strVal = StringEscapeUtils.unescapeJava(m.group(1).trim());

                // don't attempt to translate small strings
                String cleanStrVal = removeNonLetters(strVal);
                if (cleanStrVal.length() <= 3) {
                    continue;
                }

                // for now, only translate strings with non-english letters
                boolean hasNonLatinChar = false;
                for (int i = 0; i < cleanStrVal.length(); i++) {
                    if (Character.UnicodeBlock.of(cleanStrVal.charAt(i)) != Character.UnicodeBlock.BASIC_LATIN) {
                        hasNonLatinChar = true;
                        break;
                    }
                }

                if (!hasNonLatinChar) {
                    continue;
                }

                // System.out.println(" trans: " + m.group(1));

                foundStrings.add(strVal);
                foundStringsOrig.add(m.group(1).trim());
                foundPos.add(posOffset + m.start());
            }

            posOffset += line.length() + 1;
        }

        if (foundStrings.isEmpty()) {
            return;
        }

        System.out.println("Translating strings in " + sf);

        // We ASSUME every string in the file is of the same language
        // Get the language here so we can put it in all the comments later
        System.out.println("  Detecting language ...");
        Language detectedLang = Language.AUTO_DETECT;
        int tries = 0;
        System.out.println("testing replace: " + removeNonLetters("This Is .. A TEST!"));

        while (tries < foundStrings.size()) {
            try {
                detectedLang = Detect.execute(foundStrings.get(tries));
                System.out.println("looking at  " + foundStrings.get(tries));
                System.out.println("detected lang  " + detectedLang);
                System.out.println("autodetect val?= " + Language.AUTO_DETECT);
                if (detectedLang == null) {
                    tries++;
                    continue;
                }
                break;
            } catch (Exception ex) {
                Console.warn("Problem detecting language: " + ex + " -- retrying with another string..");
                tries++;
            }
        }

        System.out.println(detectedLang);
        System.out.println(Language.AUTO_DETECT);
        if (detectedLang.equals(Language.AUTO_DETECT)) {
            Console.warn("Unable to detect language. Skipping.");
            return;
        }

        if (detectedLang.equals(Language.ENGLISH)) {
            System.out.println("  Appears to be english. Skipping.");
            return;
        }

        System.out.println("  Running translation of " + foundStrings.size() + " items ...");

        // Translate all strings in bulk
        // But anything >25ish starts to time out or something
        for (int i = 0; i < foundStrings.size(); i += TranslateBatchSize) {
            int remaining = 20;
            if ((foundStrings.size() - i) < 20) {
                remaining = foundStrings.size() - i;
            }

            String[] toTranslate = new String[remaining];
            for (int j = 0; j < remaining; j++) {
                toTranslate[j] = foundStrings.get(i + j);
            }

            String[] translations = null;
            tries = 0;
            while (tries < 1) {
                try {
                    translations = Translate.execute(toTranslate, detectedLang, Language.ENGLISH);
                    break;
                } catch (Exception ex) {
                    Console.warn("Problem getting translation:\n" + ex + " - retrying.");
                    tries++;
                }
            }

            if (translations == null) {
                Console.warn("Unable to get translations. Skipping this batch.");
                continue;
            }

            for (int j = 0; j < remaining; j++) {
                String strVal = foundStrings.get(i + j);
                Integer pos = foundPos.get(i + j);

                StringBuilder insert = new StringBuilder();

                // System.out.println(foundStringsOrig.get(i+j) + " = " + translations[j]);

                // If original string was unicode escaped, show the actual symbols in comments
                insert.append("    #");
                if (foundStringsOrig.get(i + j).matches(".*?(\\\\u[a-fA-f0-9]{4}?).*?")) {
                    insert.append(" orig=\"").append(strVal).append('"');
                }
                try {
                    insert.append(" lang=").append(detectedLang.getName(Language.ENGLISH));
                } catch (Exception ex) {
                    Console.warn("  Odd, I can't figure out what language this is: " + detectedLang);
                }

                insert.append('\n').append("    # trans=\"").append(translations[j]).append('"');

                HintsAdded++;
                sf.addInsert(pos, insert + "\n");
            }
        }
    }

    private static String removeNonLetters(String line) {
        // remove all non-letters (e.g. numbers, puncutation)
        // but keep spaces, underscores and hyphens
        return line.replaceAll("[^\\p{L}\\-_ ]", "");
    }
}


text:
/*
$Revision: 1.2 $
$Date: 2007-09-08 18:28:03 $

*/

package org.rti.webgenome.webui.taglib;

import java.io.IOException;
import java.io.Writer;
import java.util.Map;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import org.rti.webgenome.analysis.SimpleUserConfigurableProperty;
import org.rti.webgenome.analysis.UserConfigurableProperty;
import org.rti.webgenome.analysis.UserConfigurablePropertyWithOptions;
import org.rti.webgenome.util.SystemUtils;

/**
 * Creates an HTML input element suitable for inputting
 * user configurable parameter values.
 * @author dhall
 *
 */
public final class UserConfigurablePropertyInputTag extends TagSupport {

	/** Serlialized version ID. */
	private static final long serialVersionUID =
		SystemUtils.getLongApplicationProperty("serial.version.uid");

	/** Name of a bean of type UserConfigurableProperty. */
	private String name = null;

	/**
	 * Prefix prepended to input name so that downstream actions
	 * can determine which query parameters denote user
	 * configurable properties.
	 */
	private String prefix = "";

	/**
	 * Set name of a bean of type
	 * UserConfigurableProperty.
	 * @param name Bean name
	 */
	public void setName(final String name) {
		this.name = name;
	}

	/**
	 * Set prefix prepended to input name so that downstream actions
	 * can determine which query parameters denote user
	 * configurable properties.
	 * @param prefix Prefix
	 */
	public void setPrefix(final String prefix) {
		this.prefix = prefix;
	}

	/**
	 * Do after start tag parsed.
	 * @throws JspException if anything goes wrong.
	 * @return Return value
	 */
	@Override
	public int doStartTag() throws JspException {

		// Get bean
		if (this.name == null) {
			throw new JspException("Name of bean missing");
		}
		Object bean = pageContext.findAttribute(this.name);
		if (bean == null) {
			throw new JspException("Cannot find bean named '"
					+ this.name + "' in any scope");
		}
		if (!(bean instanceof UserConfigurableProperty)) {
			throw new JspException("Bean '" + this.name
					+ "' is not type UserConfigurableProperty");
		}
		UserConfigurableProperty prop = (UserConfigurableProperty) bean;

		// Create input
		Writer out = pageContext.getOut();
		try {
			String propName = this.prefix + prop.getName();
			if (prop instanceof SimpleUserConfigurableProperty) {
				out.write("<input type=\"text\" name=\""
						+ propName + "\" value=\""
						+ prop.getCurrentValue() + "\">");
			} else if (prop instanceof UserConfigurablePropertyWithOptions) {
				out.write("<select name=\"" + propName + "\">");
				Map<String, String> opMap = (
						(UserConfigurablePropertyWithOptions) prop)
						.getOptions();
				for (String key : opMap.keySet()) {
					String value = opMap.get(key);
					out.write("<option value=\"" + key + "\"");
					if (key.equals(prop.getCurrentValue())) {
						out.write(" selected");
					}
					out.write(">" + value + "</option>");
				}
				out.write("</select>");
			}
		} catch (IOException e) {
			throw new JspException("Error writing to page");
		}

		return TagSupport.SKIP_BODY;
	}
}

redpajama_set_name: RedPajamaGithub


text:
'use strict';

var async = require('async');
var util = require('util');
var events = require('events');
var fork = require('child_process').fork;

var logError = require('./util.js').logError;

function Child(file, data) {
  Child.id = Child.id || 0;

  this.id = Child.id;
  Child.id += 1;

  this.process = null;

  this.suicide = false;
  this.processing = false;

  this.data = data;
  this.file = file;

  this.createNewProcess();
}

util.inherits(Child, events.EventEmitter);

/**
 * Fork the current process, to shield the father (the current process) from crash
 */
Child.prototype.createNewProcess = function createNewProcess() {
  this.process = fork(this.file);

  var self = this;
  this.process.on('error', function(err) {
    logError(err);
    self.emit('stop', self, false);
  });

  this.process.on('message', function(data) {
    if(data.err) {
      data.err = new Error(data.err);
      data.err.stack = data.errStack;

      delete data.errStack;
    }

    if(data.type === 'state') {
      self.processing = data.processing;
      self.emit('state', self);
      return;
    }

    self.emit('message', data);
  });

  this.process.on('exit', function() {
    if(self.suicide) {
      return self.emit('stop', self, true);
    }

    console.log("Child process crash! Restarting it!");

    self.createNewProcess();
    self.start();
  });
};

Child.prototype.start = function start() {
  this.processing = true;
  this.process.send(this.data);
};

Child.prototype.stop = function stop() {
  this.suicide = true;
  this.process.kill('SIGTERM');
};

function Childs(nb, file, data) {
  this.childs = {};

  var self = this;
  for(var i = 0; i < nb; i += 1) {
    var child = new Child(file, data);

    child.on('message', function(data) {
      self.emit('message', data);
    });

    child.on('state', function() {
      var processingChilds = Object.keys(self.childs).filter(function(childId) {
        return self.childs[childId].processing;
      });

      if(processingChilds.length === 0) {
        self.stop();
      }
    });

    this.childs[child.id] = child;
  }
}

util.inherits(Childs, events.EventEmitter);

Childs.prototype.start = function start() {
  var self = this;

  Object.keys(this.childs).forEach(function(id) {
    self.childs[id].start();
  });

  self.emit('start');
};

Childs.prototype.stop = function stop() {
  var self = this;

  Object.keys(this.childs).forEach(function(childId) {
    self.childs[childId].stop();
  });

  self.emit('stop', false);
};

Childs.prototype.kill = function kill(cb) {
  var self = this;
  async.each(Object.keys(this.childs), function(childId, cb) {
    self.childs[childId].once('stop', function() {
      return cb();
    });

    self.childs[childId].stop();
  }, function() {
    self.emit('stop', true);
    cb();
  });
};

module.exports = Childs;


text:
package net.java.sipmack.softphone.listeners;

import net.java.sipmack.sip.InterlocutorUI;

public interface InterlocutorListener {

    public void interlocutorAdded(InterlocutorUI interlocutorUI);

    public void interlocutorRemoved(InterlocutorUI interlocutorUI);

}


text:
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows;
using InRule.Repository;

namespace InRuleLabs.AuthoringExtensions.GenerateSDKCode.Features.Rendering
{
    public class CodeTypeDeclarationEx
    {
        public HashSet<string> UsedNames = new HashSet<string>();
        public CodeTypeDeclarationEx ParentClass { get; set; }
        public CodeTypeDeclaration InnerDeclaration { get; set; }
        public List<CodeTypeDeclarationEx> ChildClasses = new List<CodeTypeDeclarationEx>();
        public bool IsDefFactory { get; set; }
        private CodeTypeDeclarationEx(CodeTypeDeclarationEx parentClass)
        {
            ParentClass = parentClass;
        }

        public CodeTypeDeclarationEx AddChildClass(object sourceDef, string name)
        {
            UsedNames.Add(name);
            var ret = new CodeTypeDeclarationEx(this);
            var innerTypeDeclaration = ret.SetInnerTypeDeclaration(this, sourceDef, name);

            var firstFactoryMember = this.ChildClasses.FirstOrDefault(c=>c.IsDefFactory);
            if (firstFactoryMember != null)
            {
                // Push the factory members to the end of the file
                var index = this.InnerDeclaration.Members.IndexOf(firstFactoryMember.InnerDeclaration);
                this.InnerDeclaration.Members.Insert(index, innerTypeDeclaration);
            }
            else
            {
                this.InnerDeclaration.Members.Add(innerTypeDeclaration);
            }
            ChildClasses.Add(ret);
            return ret;
        }

        private CodeTypeDeclaration SetInnerTypeDeclaration(CodeTypeDeclarationEx parent, object sourceDef, string name)
        {
            string typeName = name;
            if (sourceDef != null)
            {
                var defaultTypeName = sourceDef.GetType().Name + "_" + name;
                if (parent != null)
                {
                    // This adds it to the parent used names list
                    typeName = parent.GetSafeName(defaultTypeName, true);
                }
            }

            // This is the local used names list
            UsedNames.Add(typeName);
            var codeTypeDeclaration = CreateCodeTypeDeclarationInternal(typeName);
            codeTypeDeclaration.IsClass = true;
            codeTypeDeclaration.TypeAttributes = TypeAttributes.Public;
            this.InnerDeclaration = codeTypeDeclaration;
            return codeTypeDeclaration;
        }

        private static CodeTypeDeclaration CreateCodeTypeDeclarationInternal(string name)
        {
            return new CodeTypeDeclaration(name);
        }
        private string GetSafeName(string defaultName, bool addToUsedNamesList)
        {

            defaultName = defaultName.Replace("@", "");
            defaultName = defaultName.Replace(".", "_");
            defaultName = defaultName.Replace("+", "_");
            var typeName = defaultName;

            if (this.HasTypeName(defaultName))
            {
                int count = 0;
                typeName = defaultName + "_" + count;
                while (HasTypeName(typeName))
                {
                    count ++;
                    typeName = defaultName + "_" + count;
                }
            }

            if (addToUsedNamesList)
            {
                UsedNames.Add(typeName);
            }
            return typeName;
        }

        private bool HasTypeName(string name)
        {
            if (UsedNames.Contains(name)) return true;
            //if (this.GetMemberTypes().Any(t => t.Name == typeName))
            //{
            //    return true;
            //}
            //if (this.GetMemberMethods().Any(t => t.Name == typeName))
            //{
            //    return true;
            //}
            if (this.ParentClass != null)
            {
                return this.ParentClass.HasTypeName(name);
            }
            return false;
        }

        public string Name { get { return this.InnerDeclaration.Name; } }
        public IEnumerable<CodeTypeMember> GetMembers()
        {
            foreach (CodeTypeMember member in this.InnerDeclaration.Members)
            {
                yield return member;
            }
        }
        public CodeMemberMethodEx AddFactoryMethod(CodeTypeReferenceEx returnType, string methodName, out CodeMethodVariableReferenceEx returnVariable)
        {
            var method = new CodeMemberMethodEx(this);
            returnVariable = new CodeMethodVariableReferenceEx(method, method.AddMethodVariable("newDef", returnType, returnType.ReferencedType.CallCodeConstructor()));
            method.Name = methodName;
            method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
            method.ReturnType = returnType;
            method.IsSharedFactoryMethod = true;
            this.AddMethod(method);

            return method;
        }
        public void AddMethod(CodeMemberMethodEx method)
        {
            UsedNames.Add(method.Name);
            this.InnerDeclaration.Members.Add(method);
        }

        public bool ContainsMethod(string methodName)
        {
            return GetMembers().OfType<CodeMemberMethodEx>().Any(m => m.Name == methodName);
        }
        public bool ContainsChildClass(string className)
        {
            return GetMembers().OfType<CodeTypeDeclarationEx>().Any(m => m.Name == className);
        }
        public bool ContainsSharedFactoryMethod(string methodName, params CodeDefPropertyDescriptor[] properties)
        {
            if (GetMembers().OfType<CodeMemberMethodEx>().Any(m => m.Name == methodName && m.MatchesPropertyAssignments(properties)))
            {
                return true;
            }

            if (properties.Length > 0)
            {
                var matchByOverload = GetMembers().OfType<CodeMemberMethodEx>().Where(m => m.Name == methodName && m.MatchesPropertyAssignmentOverloads(properties)).FirstOrDefault();
                if(matchByOverload != null)
                {
                    if (MessageBox.Show("Warning: Duplicate Factory Method Overloads", "Method Overload Collision", MessageBoxButton.YesNo) == MessageBoxResult.No)
                    {
                        throw new Exception();
                    }
                }
            }
            return false;
        }

        public CodeMemberMethodEx AddCreateMethod(object sourceDef, bool justUseCreateForName = false)
        {
            var createMethod = new CodeMemberMethodEx(this);
            if (justUseCreateForName)
            {
                createMethod.Name = "Create";
            }
            else
            {
                var methodSuffix = sourceDef.GetType().Name;
                if (sourceDef is RuleRepositoryDefBase)
                {
                    var name = methodSuffix +"_" + ((RuleRepositoryDefBase) sourceDef).Name;
                    methodSuffix = name;
                }
                // Used name is captured below
                createMethod.Name = GetSafeName("Create_" + methodSuffix, false);
            }

            createMethod.Attributes = MemberAttributes.Public | MemberAttributes.Static;
            createMethod.ReturnType = sourceDef.GetType().ToCodeTypeReference();
            this.InnerDeclaration.Members.Add(createMethod);
            UsedNames.Add(createMethod.Name);

            return createMethod;
        }

        public static CodeTypeDeclarationEx CreateRoot(object sourceRuleAppDef)
        {
            string name = sourceRuleAppDef.GetType().Name;
            if (sourceRuleAppDef.IsInstanceOf<RuleApplicationDef>())
            {
                name = "RuleAppGen_" + ((RuleApplicationDef) sourceRuleAppDef).Name;
            }
            var ret = new CodeTypeDeclarationEx(null);
            ret.SetInnerTypeDeclaration(null, sourceRuleAppDef, name);
            return ret;
        }

        public CodeTypeDeclarationEx GetDefFactory()
        {
            if (this.ParentClass != null)
            {
                return this.ParentClass.GetDefFactory();
            }

            var defFactory = this.ChildClasses.FirstOrDefault(c => c.IsDefFactory);
            if (defFactory == null)
            {
                defFactory = this.AddChildClass(null, "DefFactory");
                defFactory.IsDefFactory = true;
            }
            return defFactory;
        }
    }
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<GeocodeResponse>
 <status>OK</status>
 <result>
  <type>locality</type>
  <type>political</type>
  <formatted_address>Perchtoldsdorf, Austria</formatted_address>
  <address_component>
   <long_name>Perchtoldsdorf</long_name>
   <short_name>Perchtoldsdorf</short_name>
   <type>locality</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Gemeinde Perchtoldsdorf</long_name>
   <short_name>Gemeinde Perchtoldsdorf</short_name>
   <type>administrative_area_level_3</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Mödling District</long_name>
   <short_name>Mödling District</short_name>
   <type>administrative_area_level_2</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Lower Austria</long_name>
   <short_name>Lower Austria</short_name>
   <type>administrative_area_level_1</type>
   <type>political</type>
  </address_component>
  <address_component>
   <long_name>Austria</long_name>
   <short_name>AT</short_name>
   <type>country</type>
   <type>political</type>
  </address_component>
  <geometry>
   <location>
    <lat>48.1205386</lat>
    <lng>16.2692452</lng>
   </location>
   <location_type>APPROXIMATE</location_type>
   <viewport>
    <southwest>
     <lat>48.1001099</lat>
     <lng>16.2184600</lng>
    </southwest>
    <northeast>
     <lat>48.1338600</lat>
     <lng>16.2994799</lng>
    </northeast>
   </viewport>
   <bounds>
    <southwest>
     <lat>48.1001099</lat>
     <lng>16.2184600</lng>
    </southwest>
    <northeast>
     <lat>48.1338600</lat>
     <lng>16.2994799</lng>
    </northeast>
   </bounds>
  </geometry>
  <place_id>ChIJexdiy_ulbUcRwDTmLVeXAAQ</place_id>
 </result>
</GeocodeResponse>


text:
package org.fseek.thedeath.os.linux;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Simon Wimmesberger
 */
public class LinuxUserDirectoryConfig implements LinuxUserDirectory{
    private static final HashMap<String, String> XDG_USER_MAPPINGS;
    private static HashMap<String, File> userDirs;

    static{
        XDG_USER_MAPPINGS = new HashMap<>();
        XDG_USER_MAPPINGS.put("XDG_DESKTOP_DIR", DESKTOP_DIR_KEY);
        XDG_USER_MAPPINGS.put("XDG_DOWNLOAD_DIR", DOWNLOAD_DIR_KEY);
        XDG_USER_MAPPINGS.put("XDG_TEMPLATES_DIR", TEMPLATES_DIR_KEY);
        XDG_USER_MAPPINGS.put("XDG_PUBLICSHARE_DIR", PUBLICSHARE_DIR_KEY);
        XDG_USER_MAPPINGS.put("XDG_DOCUMENTS_DIR", DOCUMENTS_DIR_KEY);
        XDG_USER_MAPPINGS.put("XDG_MUSIC_DIR", MUSIC_DIR_KEY);
        XDG_USER_MAPPINGS.put("XDG_PICTURES_DIR", PICTURES_DIR_KEY);
        XDG_USER_MAPPINGS.put("XDG_VIDEOS_DIR", VIDEOS_DIR_KEY);
    }

    @Override
    public File getUserDirectory(String key) {
        return getUserDirectoryImpl(key);
    }

    protected File getUserDirectoryImpl(String key)
    {
        HashMap<String, File> dirStore = getUserDirectoryStore();
        if(dirStore == null){
            return null;
        }
        if(dirStore.containsKey(key) == false){
            return null;
        }
        return dirStore.get(key);
    }

    protected static HashMap<String, File> getUserDirectoryStore(){
        try{
            if(userDirs == null){
                userDirs = getUserDirectoriesImpl();
            }
            if(userDirs == null){
                return null;
            }
            return userDirs;
        }catch(UnsupportedOperationException ex){
            return null;
        }
    }

    public File[] getUserDirectories(){
        HashMap<String, File> dirStore = getUserDirectoryStore();
        if(dirStore == null){
            return null;
        }
        return dirStore.values().toArray(new File[0]);
    }

    /**
     * Checks ~/.config/user-dirs.dirs for the paths to the user directory
     * @return
     */
    protected static HashMap<String, File> getUserDirectoriesImpl(){
        File userDir = new File(System.getProperty("user.home"));
        String userPath = userDir.toString();
        File f = new File(userDir, ".config/user-dirs.dirs");
        if(f.exists() == false){
            throw new UnsupportedOperationException("User-dirs not supported");
        }
        try(BufferedReader br = new BufferedReader(new FileReader(f))){
            HashMap<String, File> linuxStore = new HashMap<>();
            while(true){
                String line = br.readLine();
                if(line == null)break;
                if(line.startsWith("#"))continue;
                Pattern pattern = Pattern.compile("(?<KEY>[a-zA-Z_]+)=\"(?<VALUE>.+)\"");
                Matcher matcher = pattern.matcher(line);
                boolean find = matcher.find();
                if(find == false)continue;
                String key = matcher.group("KEY");
                String value = matcher.group("VALUE");
                value = value.replace("$HOME", userPath);
                String keyStoreKey = XDG_USER_MAPPINGS.get(key);
                if(keyStoreKey != null){
                    linuxStore.put(keyStoreKey, new File(value));
                }
            }
            return linuxStore;
        } catch (IOException ex) {
            return null;
        }
    }
}


text:
module Byebug
  class DisplayTestCase < TestCase
    def setup
      @example = -> do
        d = 0
        byebug
        d = d + 3
        d = d + 6
      end

      super
    end

    def test_shows_expressions
      enter 'display d + 1'
      debug_proc(@example)
      check_output_includes '1: d + 1 = 1'
    end

    def test_works_when_using_a_shortcut
      enter 'disp d + 1'
      debug_proc(@example)
      check_output_includes '1: d + 1 = 1'
    end

    def test_saves_displayed_expressions
      enter 'display d + 1'
      debug_proc(@example) { assert_equal [[true, 'd + 1']], state.display }
    end

    def test_displays_all_expressions_available
      enter 'display d', 'display d + 1', 'display'
      debug_proc(@example)
      check_output_includes '1: d = 0', '2: d + 1 = 1'
    end
  end
end


text:
// Copyright 2013-2022, University of Colorado Boulder

/**
 * An elliptical arc (a continuous sub-part of an ellipse).
 *
 * Additional helpful notes:
 * - http://www.w3.org/TR/SVG/implnote.html#PathElementImplementationNotes
 * - http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-ellipse
 *   (note: context.ellipse was removed from the Canvas spec)
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */

import Bounds2 from '../../../dot/js/Bounds2.js';
import Matrix3 from '../../../dot/js/Matrix3.js';
import Ray2 from '../../../dot/js/Ray2.js';
import Transform3 from '../../../dot/js/Transform3.js';
import Utils from '../../../dot/js/Utils.js';
import Vector2 from '../../../dot/js/Vector2.js';
import Enumeration from '../../../phet-core/js/Enumeration.js';
import EnumerationValue from '../../../phet-core/js/EnumerationValue.js';
import { Arc, BoundsIntersection, kite, Line, Overlap, RayIntersection, Segment, SegmentIntersection, svgNumber } from '../imports.js';

// constants
const toDegrees = Utils.toDegrees;

type SerializedEllipticalArc = {
  type: 'EllipticalArc';
  centerX: number;
  centerY: number;
  radiusX: number;
  radiusY: number;
  rotation: number;
  startAngle: number;
  endAngle: number;
  anticlockwise: boolean;
};

export default class EllipticalArc extends Segment {

  private _center: Vector2;
  private _radiusX: number;
  private _radiusY: number;
  private _rotation: number;
  private _startAngle: number;
  private _endAngle: number;
  private _anticlockwise: boolean;

  // Lazily-computed derived information
  private _unitTransform!: Transform3 | null; // Mapping between our ellipse and a unit circle
  private _start!: Vector2 | null;
  private _end!: Vector2 | null;
  private _startTangent!: Vector2 | null;
  private _endTangent!: Vector2 | null;
  private _actualEndAngle!: number | null; // End angle in relation to our start angle (can get remapped)
  private _isFullPerimeter!: boolean | null; // Whether it's a full ellipse (and not just an arc)
  private _angleDifference!: number | null;
  private _unitArcSegment!: Arc | null; // Corresponding circular arc for our unit transform.
  private _bounds!: Bounds2 | null;
  private _svgPathFragment!: string | null;

  private possibleExtremaAngles?: number[];

  /**
   * If the startAngle/endAngle difference is ~2pi, this will be a full ellipse
   *
   * @param center - Center of the ellipse
   * @param radiusX - Semi-major radius
   * @param radiusY - Semi-minor radius
   * @param rotation - Rotation of the semi-major axis
   * @param startAngle - Angle (radians) of the start of the arc
   * @param endAngle - Angle (radians) of the end of the arc
   * @param anticlockwise - Decides which direction the arc takes around the center
   */
  public constructor( center: Vector2, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise: boolean ) {
    super();

    this._center = center;
    this._radiusX = radiusX;
    this._radiusY = radiusY;
    this._rotation = rotation;
    this._startAngle = startAngle;
    this._endAngle = endAngle;
    this._anticlockwise = anticlockwise;

    this.invalidate();
  }

  /**
   * Sets the center of the EllipticalArc.
   */
  public setCenter( center: Vector2 ): this {
    assert && assert( center.isFinite(), `EllipticalArc center should be finite: ${center.toString()}` );

    if ( !this._center.equals( center ) ) {
      this._center = center;
      this.invalidate();
    }
    return this; // allow chaining
  }

  public set center( value: Vector2 ) { this.setCenter( value ); }

  public get center(): Vector2 { return this.getCenter(); }

  /**
   * Returns the center of this EllipticalArc.
   */
  public getCenter(): Vector2 {
    return this._center;
  }

  /**
   * Sets the semi-major radius of the EllipticalArc.
   */
  public setRadiusX( radiusX: number ): this {
    assert && assert( isFinite( radiusX ), `EllipticalArc radiusX should be a finite number: ${radiusX}` );

    if ( this._radiusX !== radiusX ) {
      this._radiusX = radiusX;
      this.invalidate();
    }
    return this; // allow chaining
  }

  public set radiusX( value: number ) { this.setRadiusX( value ); }

  public get radiusX(): number { return this.getRadiusX(); }

  /**
   * Returns the semi-major radius of this EllipticalArc.
   */
  public getRadiusX(): number {
    return this._radiusX;
  }

  /**
   * Sets the semi-minor radius of the EllipticalArc.
   */
  public setRadiusY( radiusY: number ): this {
    assert && assert( isFinite( radiusY ), `EllipticalArc radiusY should be a finite number: ${radiusY}` );

    if ( this._radiusY !== radiusY ) {
      this._radiusY = radiusY;
      this.invalidate();
    }
    return this; // allow chaining
  }

  public set radiusY( value: number ) { this.setRadiusY( value ); }

  public get radiusY(): number { return this.getRadiusY(); }

  /**
   * Returns the semi-minor radius of this EllipticalArc.
   */
  public getRadiusY(): number {
    return this._radiusY;
  }

  /**
   * Sets the rotation of the EllipticalArc.
   */
  public setRotation( rotation: number ): this {
    assert && assert( isFinite( rotation ), `EllipticalArc rotation should be a finite number: ${rotation}` );

    if ( this._rotation !== rotation ) {
      this._rotation = rotation;
      this.invalidate();
    }
    return this; // allow chaining
  }

  public set rotation( value: number ) { this.setRotation( value ); }

  public get rotation(): number { return this.getRotation(); }

  /**
   * Returns the rotation of this EllipticalArc.
   */
  public getRotation(): number {
    return this._rotation;
  }

  /**
   * Sets the startAngle of the EllipticalArc.
   */
  public setStartAngle( startAngle: number ): this {
    assert && assert( isFinite( startAngle ), `EllipticalArc startAngle should be a finite number: ${startAngle}` );

    if ( this._startAngle !== startAngle ) {
      this._startAngle = startAngle;
      this.invalidate();
    }
    return this; // allow chaining
  }

  public set startAngle( value: number ) { this.setStartAngle( value ); }

  public get startAngle(): number { return this.getStartAngle(); }

  /**
   * Returns the startAngle of this EllipticalArc.
   */
  public getStartAngle(): number {
    return this._startAngle;
  }

  /**
   * Sets the endAngle of the EllipticalArc.
   */
  public setEndAngle( endAngle: number ): this {
    assert && assert( isFinite( endAngle ), `EllipticalArc endAngle should be a finite number: ${endAngle}` );

    if ( this._endAngle !== endAngle ) {
      this._endAngle = endAngle;
      this.invalidate();
    }
    return this; // allow chaining
  }

  public set endAngle( value: number ) { this.setEndAngle( value ); }

  public get endAngle(): number { return this.getEndAngle(); }

  /**
   * Returns the endAngle of this EllipticalArc.
   */
  public getEndAngle(): number {
    return this._endAngle;
  }

  /**
   * Sets the anticlockwise of the EllipticalArc.
   */
  public setAnticlockwise( anticlockwise: boolean ): this {
    if ( this._anticlockwise !== anticlockwise ) {
      this._anticlockwise = anticlockwise;
      this.invalidate();
    }
    return this; // allow chaining
  }

  public set anticlockwise( value: boolean ) { this.setAnticlockwise( value ); }

  public get anticlockwise(): boolean { return this.getAnticlockwise(); }

  /**
   * Returns the anticlockwise of this EllipticalArc.
   */
  public getAnticlockwise(): boolean {
    return this._anticlockwise;
  }

  /**
   * Returns the position parametrically, with 0 <= t <= 1.
   *
   * NOTE: positionAt( 0 ) will return the start of the segment, and positionAt( 1 ) will return the end of the
   * segment.
   *
   * This method is part of the Segment API. See Segment.js's constructor for more API documentation.
   */
  public positionAt( t: number ): Vector2 {
    assert && assert( t >= 0, 'positionAt t should be non-negative' );
    assert && assert( t <= 1, 'positionAt t should be no greater than 1' );

    return this.positionAtAngle( this.angleAt( t ) );
  }

  /**
   * Returns the non-normalized tangent (dx/dt, dy/dt) of this segment at the parametric value of t, with 0 <= t <= 1.
   *
   * NOTE: tangentAt( 0 ) will return the tangent at the start of the segment, and tangentAt( 1 ) will return the
   * tangent at the end of the segment.
   *
   * This method is part of the Segment API. See Segment.js's constructor for more API documentation.
   */
  public tangentAt( t: number ): Vector2 {
    assert && assert( t >= 0, 'tangentAt t should be non-negative' );
    assert && assert( t <= 1, 'tangentAt t should be no greater than 1' );

    return this.tangentAtAngle( this.angleAt( t ) );
  }

  /**
   * Returns the signed curvature of the segment at the parametric value t, where 0 <= t <= 1.
   *
   * The curvature will be positive for visual clockwise / mathematical counterclockwise curves, negative for opposite
   * curvature, and 0 for no curvature.
   *
   * NOTE: curvatureAt( 0 ) will return the curvature at the start of the segment, and curvatureAt( 1 ) will return
   * the curvature at the end of the segment.
   *
   * This method is part of the Segment API. See Segment.js's constructor for more API documentation.
   */
  public curvatureAt( t: number ): number {
    assert && assert( t >= 0, 'curvatureAt t should be non-negative' );
    assert && assert( t <= 1, 'curvatureAt t should be no greater than 1' );

    // see http://mathworld.wolfram.com/Ellipse.html (59)
    const angle = this.angleAt( t );
    const aq = this._radiusX * Math.sin( angle );
    const bq = this._radiusY * Math.cos( angle );
    const denominator = Math.pow( bq * bq + aq * aq, 3 / 2 );
    return ( this._anticlockwise ? -1 : 1 ) * this._radiusX * this._radiusY / denominator;
  }

  /**
   * Returns an array with up to 2 sub-segments, split at the parametric t value. Together (in order) they should make
   * up the same shape as the current segment.
   *
   * This method is part of the Segment API. See Segment.js's constructor for more API documentation.
   */
  public subdivided( t: number ): EllipticalArc[] {
    assert && assert( t >= 0, 'subdivided t should be non-negative' );
    assert && assert( t <= 1, 'subdivided t should be no greater than 1' );

    // If t is 0 or 1, we only need to return 1 segment
    if ( t === 0 || t === 1 ) {
      return [ this ];
    }

    // TODO: verify that we don't need to switch anticlockwise here, or subtract 2pi off any angles
    const angle0 = this.angleAt( 0 );
    const angleT = this.angleAt( t );
    const angle1 = this.angleAt( 1 );
    return [
      new EllipticalArc( this._center, this._radiusX, this._radiusY, this._rotation, angle0, angleT, this._anticlockwise ),
      new EllipticalArc( this._center, this._radiusX, this._radiusY, this._rotation, angleT, angle1, this._anticlockwise )
    ];
  }

  /**
   * Clears cached information, should be called when any of the 'constructor arguments' are mutated.
   */
  public invalidate(): void {

    assert && assert( this._center instanceof Vector2, 'Arc center should be a Vector2' );
    assert && assert( this._center.isFinite(), 'Arc center should be finite (not NaN or infinite)' );
    assert && assert( typeof this._radiusX === 'number', `Arc radiusX should be a number: ${this._radiusX}` );
    assert && assert( isFinite( this._radiusX ), `Arc radiusX should be a finite number: ${this._radiusX}` );
    assert && assert( typeof this._radiusY === 'number', `Arc radiusY should be a number: ${this._radiusY}` );
    assert && assert( isFinite( this._radiusY ), `Arc radiusY should be a finite number: ${this._radiusY}` );
    assert && assert( typeof this._rotation === 'number', `Arc rotation should be a number: ${this._rotation}` );
    assert && assert( isFinite( this._rotation ), `Arc rotation should be a finite number: ${this._rotation}` );
    assert && assert( typeof this._startAngle === 'number', `Arc startAngle should be a number: ${this._startAngle}` );
    assert && assert( isFinite( this._startAngle ), `Arc startAngle should be a finite number: ${this._startAngle}` );
    assert && assert( typeof this._endAngle === 'number', `Arc endAngle should be a number: ${this._endAngle}` );
    assert && assert( isFinite( this._endAngle ), `Arc endAngle should be a finite number: ${this._endAngle}` );
    assert && assert( typeof this._anticlockwise === 'boolean', `Arc anticlockwise should be a boolean: ${this._anticlockwise}` );

    this._unitTransform = null;
    this._start = null;
    this._end = null;
    this._startTangent = null;
    this._endTangent = null;
    this._actualEndAngle = null;
    this._isFullPerimeter = null;
    this._angleDifference = null;
    this._unitArcSegment = null;
    this._bounds = null;
    this._svgPathFragment = null;

    // remapping of negative radii
    if ( this._radiusX < 0 ) {
      // support this case since we might actually need to handle it inside of strokes?
      this._radiusX = -this._radiusX;
      this._startAngle = Math.PI - this._startAngle;
      this._endAngle = Math.PI - this._endAngle;
      this._anticlockwise = !this._anticlockwise;
    }
    if ( this._radiusY < 0 ) {
      // support this case since we might actually need to handle it inside of strokes?
      this._radiusY = -this._radiusY;
      this._startAngle = -this._startAngle;
      this._endAngle = -this._endAngle;
      this._anticlockwise = !this._anticlockwise;
    }
    if ( this._radiusX < this._radiusY ) {
      // swap radiusX and radiusY internally for consistent Canvas / SVG output
      this._rotation += Math.PI / 2;
      this._startAngle -= Math.PI / 2;
      this._endAngle -= Math.PI / 2;

      // swap radiusX and radiusY
      const tmpR = this._radiusX;
      this._radiusX = this._radiusY;
      this._radiusY = tmpR;
    }

    if ( this._radiusX < this._radiusY ) {
      // TODO: check this
      throw new Error( 'Not verified to work if radiusX < radiusY' );
    }

    // constraints shared with Arc
    assert && assert( !( ( !this._anticlockwise && this._endAngle - this._startAngle <= -Math.PI * 2 ) ||
                         ( this._anticlockwise && this._startAngle - this._endAngle <= -Math.PI * 2 ) ),
      'Not handling elliptical arcs with start/end angles that show differences in-between browser handling' );
    assert && assert( !( ( !this._anticlockwise && this._endAngle - this._startAngle > Math.PI * 2 ) ||
                         ( this._anticlockwise && this._startAngle - this._endAngle > Math.PI * 2 ) ),
      'Not handling elliptical arcs with start/end angles that show differences in-between browser handling' );

    this.invalidationEmitter.emit();
  }

  /**
   * Computes a transform that maps a unit circle into this ellipse's location.
   *
   * Helpful, since we can get the parametric position of our unit circle (at t), and then transform it with this
   * transform to get the ellipse's parametric position (at t).
   */
  public getUnitTransform(): Transform3 {
    if ( this._unitTransform === null ) {
      this._unitTransform = EllipticalArc.computeUnitTransform( this._center, this._radiusX, this._radiusY, this._rotation );
    }
    return this._unitTransform;
  }

  public get unitTransform(): Transform3 { return this.getUnitTransform(); }

  /**
   * Gets the start point of this ellipticalArc
   */
  public getStart(): Vector2 {
    if ( this._start === null ) {
      this._start = this.positionAtAngle( this._startAngle );
    }
    return this._start;
  }

  public get start(): Vector2 { return this.getStart(); }

  /**
   * Gets the end point of this ellipticalArc
   */
  public getEnd(): Vector2 {
    if ( this._end === null ) {
      this._end = this.positionAtAngle( this._endAngle );
    }
    return this._end;
  }

  public get end(): Vector2 { return this.getEnd(); }

  /**
   * Gets the tangent vector (normalized) to this ellipticalArc at the start, pointing in the direction of motion (from start to end)
   */
  public getStartTangent(): Vector2 {
    if ( this._startTangent === null ) {
      this._startTangent = this.tangentAtAngle( this._startAngle );
    }
    return this._startTangent;
  }

  public get startTangent(): Vector2 { return this.getStartTangent(); }

  /**
   * Gets the tangent vector (normalized) to this ellipticalArc at the end point, pointing in the direction of motion (from start to end)
   */
  public getEndTangent(): Vector2 {
    if ( this._endTangent === null ) {
      this._endTangent = this.tangentAtAngle( this._endAngle );
    }
    return this._endTangent;
  }

  public get endTangent(): Vector2 { return this.getEndTangent(); }

  /**
   * Gets the end angle in radians
   */
  public getActualEndAngle(): number {
    if ( this._actualEndAngle === null ) {
      this._actualEndAngle = Arc.computeActualEndAngle( this._startAngle, this._endAngle, this._anticlockwise );
    }
    return this._actualEndAngle;
  }

  public get actualEndAngle(): number { return this.getActualEndAngle(); }

  /**
   * Returns a boolean value that indicates if the arc wraps up by more than two Pi
   */
  public getIsFullPerimeter(): boolean {
    if ( this._isFullPerimeter === null ) {
      this._isFullPerimeter = ( !this._anticlockwise && this._endAngle - this._startAngle >= Math.PI * 2 ) || ( this._anticlockwise && this._startAngle - this._endAngle >= Math.PI * 2 );
    }
    return this._isFullPerimeter;
  }

  public get isFullPerimeter(): boolean { return this.getIsFullPerimeter(); }

  /**
   * Returns an angle difference that represents how "much" of the circle our arc covers
   *
   * The answer is always greater or equal to zero
   * The answer can exceed two Pi
   */
  public getAngleDifference(): number {
    if ( this._angleDifference === null ) {
      // compute an angle difference that represents how "much" of the circle our arc covers
      this._angleDifference = this._anticlockwise ? this._startAngle - this._endAngle : this._endAngle - this._startAngle;
      if ( this._angleDifference < 0 ) {
        this._angleDifference += Math.PI * 2;
      }
      assert && assert( this._angleDifference >= 0 ); // now it should always be zero or positive
    }
    return this._angleDifference;
  }

  public get angleDifference(): number { return this.getAngleDifference(); }

  /**
   * A unit arg segment that we can map to our ellipse. useful for hit testing and such.
   */
  public getUnitArcSegment(): Arc {
    if ( this._unitArcSegment === null ) {
      this._unitArcSegment = new Arc( Vector2.ZERO, 1, this._startAngle, this._endAngle, this._anticlockwise );
    }
    return this._unitArcSegment;
  }

  public get unitArcSegment(): Arc { return this.getUnitArcSegment(); }

  /**
   * Returns the bounds of this segment.
   */
  public getBounds(): Bounds2 {
    if ( this._bounds === null ) {
      this._bounds = Bounds2.NOTHING.withPoint( this.getStart() )
        .withPoint( this.getEnd() );

      // if the angles are different, check extrema points
      if ( this._startAngle !== this._endAngle ) {
        // solve the mapping from the unit circle, find locations where a coordinate of the gradient is zero.
        // we find one extrema point for both x and y, since the other two are just rotated by pi from them.
        const xAngle = Math.atan( -( this._radiusY / this._radiusX ) * Math.tan( this._rotation ) );
        const yAngle = Math.atan( ( this._radiusY / this._radiusX ) / Math.tan( this._rotation ) );

        // check all of the extrema points
        this.possibleExtremaAngles = [
          xAngle,
          xAngle + Math.PI,
          yAngle,
          yAngle + Math.PI
        ];

        _.each( this.possibleExtremaAngles, this.includeBoundsAtAngle.bind( this ) );
      }
    }
    return this._bounds;
  }

  public get bounds(): Bounds2 { return this.getBounds(); }

  /**
   * Returns a list of non-degenerate segments that are equivalent to this segment. Generally gets rid (or simplifies)
   * invalid or repeated segments.
   */
  public getNondegenerateSegments(): Segment[] {
    if ( this._radiusX <= 0 || this._radiusY <= 0 || this._startAngle === this._endAngle ) {
      return [];
    }
    else if ( this._radiusX === this._radiusY ) {
      // reduce to an Arc
      const startAngle = this._startAngle + this._rotation;
      let endAngle = this._endAngle + this._rotation;

      // preserve full circles
      if ( Math.abs( this._endAngle - this._startAngle ) === Math.PI * 2 ) {
        endAngle = this._anticlockwise ? startAngle - Math.PI * 2 : startAngle + Math.PI * 2;
      }
      return [ new Arc( this._center, this._radiusX, startAngle, endAngle, this._anticlockwise ) ];
    }
    else {
      return [ this ];
    }
  }

  /**
   * Attempts to expand the private _bounds bounding box to include a point at a specific angle, making sure that
   * angle is actually included in the arc. This will presumably be called at angles that are at critical points,
   * where the arc should have maximum/minimum x/y values.
   */
  private includeBoundsAtAngle( angle: number ): void {
    if ( this.unitArcSegment.containsAngle( angle ) ) {
      // the boundary point is in the arc
      this._bounds = this._bounds!.withPoint( this.positionAtAngle( angle ) );
    }
  }

  /**
   * Maps a contained angle to between [startAngle,actualEndAngle), even if the end angle is lower.
   *
   * TODO: remove duplication with Arc
   */
  public mapAngle( angle: number ): number {
    if ( Math.abs( Utils.moduloBetweenDown( angle - this._startAngle, -Math.PI, Math.PI ) ) < 1e-8 ) {
      return this._startAngle;
    }
    if ( Math.abs( Utils.moduloBetweenDown( angle - this.getActualEndAngle(), -Math.PI, Math.PI ) ) < 1e-8 ) {
      return this.getActualEndAngle();
    }
    // consider an assert that we contain that angle?
    return ( this._startAngle > this.getActualEndAngle() ) ?
           Utils.moduloBetweenUp( angle, this._startAngle - 2 * Math.PI, this._startAngle ) :
           Utils.moduloBetweenDown( angle, this._startAngle, this._startAngle + 2 * Math.PI );
  }

  /**
   * Returns the parametrized value t for a given angle. The value t should range from 0 to 1 (inclusive).
   *
   * TODO: remove duplication with Arc
   */
  public tAtAngle( angle: number ): number {
    return ( this.mapAngle( angle ) - this._startAngle ) / ( this.getActualEndAngle() - this._startAngle );
  }

  /**
   * Returns the angle for the parametrized t value. The t value should range from 0 to 1 (inclusive).
   */
  public angleAt( t: number ): number {
    return this._startAngle + ( this.getActualEndAngle() - this._startAngle ) * t;
  }

  /**
   * Returns the position of this arc at angle.
   */
  public positionAtAngle( angle: number ): Vector2 {
    return this.getUnitTransform().transformPosition2( Vector2.createPolar( 1, angle ) );
  }

  /**
   * Returns the normalized tangent of this arc.
   * The tangent points outward (inward) of this arc for clockwise (anticlockwise) direction.
   */
  public tangentAtAngle( angle: number ): Vector2 {
    const normal = this.getUnitTransform().transformNormal2( Vector2.createPolar( 1, angle ) );

    return this._anticlockwise ? normal.perpendicular : normal.perpendicular.negated();
  }

  /**
   * Returns an array of straight lines that will draw an offset on the logical left (right) side for reverse false (true)
   * It discretizes the elliptical arc in 32 segments and returns an offset curve as a list of lineTos/
   *
   * @param r - distance
   * @param reverse
   */
  public offsetTo( r: number, reverse: boolean ): Line[] {
    // how many segments to create (possibly make this more adaptive?)
    const quantity = 32;

    const points = [];
    const result = [];
    for ( let i = 0; i < quantity; i++ ) {
      let ratio = i / ( quantity - 1 );
      if ( reverse ) {
        ratio = 1 - ratio;
      }
      const angle = this.angleAt( ratio );

      points.push( this.positionAtAngle( angle ).plus( this.tangentAtAngle( angle ).perpendicular.normalized().times( r ) ) );
      if ( i > 0 ) {
        result.push( new Line( points[ i - 1 ], points[ i ] ) );
      }
    }

    return result;
  }

  /**
   * Returns a string containing the SVG path. assumes that the start point is already provided,
   * so anything that calls this needs to put the M calls first.
   */
  public getSVGPathFragment(): string {
    let oldPathFragment;
    if ( assert ) {
      oldPathFragment = this._svgPathFragment;
      this._svgPathFragment = null;
    }
    if ( !this._svgPathFragment ) {
      // see http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands for more info
      // rx ry x-axis-rotation large-arc-flag sweep-flag x y
      const epsilon = 0.01; // allow some leeway to render things as 'almost circles'
      const sweepFlag = this._anticlockwise ? '0' : '1';
      let largeArcFlag;
      const degreesRotation = toDegrees( this._rotation ); // bleh, degrees?
      if ( this.getAngleDifference() < Math.PI * 2 - epsilon ) {
        largeArcFlag = this.getAngleDifference() < Math.PI ? '0' : '1';
        this._svgPathFragment = `A ${svgNumber( this._radiusX )} ${svgNumber( this._radiusY )} ${degreesRotation
        } ${largeArcFlag} ${sweepFlag} ${svgNumber( this.getEnd().x )} ${svgNumber( this.getEnd().y )}`;
      }
      else {
        // ellipse (or almost-ellipse) case needs to be handled differently
        // since SVG will not be able to draw (or know how to draw) the correct circle if we just have a start and end, we need to split it into two circular arcs

        // get the angle that is between and opposite of both of the points
        const splitOppositeAngle = ( this._startAngle + this._endAngle ) / 2; // this _should_ work for the modular case?
        const splitPoint = this.positionAtAngle( splitOppositeAngle );

        largeArcFlag = '0'; // since we split it in 2, it's always the small arc

        const firstArc = `A ${svgNumber( this._radiusX )} ${svgNumber( this._radiusY )} ${
          degreesRotation} ${largeArcFlag} ${sweepFlag} ${
          svgNumber( splitPoint.x )} ${svgNumber( splitPoint.y )}`;
        const secondArc = `A ${svgNumber( this._radiusX )} ${svgNumber( this._radiusY )} ${
          degreesRotation} ${largeArcFlag} ${sweepFlag} ${
          svgNumber( this.getEnd().x )} ${svgNumber( this.getEnd().y )}`;

        this._svgPathFragment = `${firstArc} ${secondArc}`;
      }
    }
    if ( assert ) {
      if ( oldPathFragment ) {
        assert( oldPathFragment === this._svgPathFragment, 'Quadratic line segment changed without invalidate()' );
      }
    }
    return this._svgPathFragment;
  }

  /**
   * Returns an array of straight lines  that will draw an offset on the logical left side.
   */
  public strokeLeft( lineWidth: number ): Line[] {
    return this.offsetTo( -lineWidth / 2, false );
  }

  /**
   * Returns an array of straight lines that will draw an offset curve on the logical right side.
   */
  public strokeRight( lineWidth: number ): Line[] {
    return this.offsetTo( lineWidth / 2, true );
  }

  /**
   * Returns a list of t values where dx/dt or dy/dt is 0 where 0 < t < 1. subdividing on these will result in monotonic segments
   * Does not include t=0 and t=1.
   */
  public getInteriorExtremaTs(): number[] {
    const result: number[] = [];
    _.each( this.possibleExtremaAngles, ( angle: number ) => {
      if ( this.unitArcSegment.containsAngle( angle ) ) {
        const t = this.tAtAngle( angle );
        const epsilon = 0.0000000001; // TODO: general kite epsilon?
        if ( t > epsilon && t < 1 - epsilon ) {
          result.push( t );
        }
      }
    } );
    return result.sort(); // modifies original, which is OK
  }

  /**
   * Hit-tests this segment with the ray. An array of all intersections of the ray with this segment will be returned.
   * For details, see the documentation in Segment.js
   */
  public intersection( ray: Ray2 ): RayIntersection[] {
    // be lazy. transform it into the space of a non-elliptical arc.
    const unitTransform = this.getUnitTransform();
    const rayInUnitCircleSpace = unitTransform.inverseRay2( ray );
    const hits = this.getUnitArcSegment().intersection( rayInUnitCircleSpace );

    return _.map( hits, hit => {
      const transformedPoint = unitTransform.transformPosition2( hit.point );
      const distance = ray.position.distance( transformedPoint );
      const normal = unitTransform.inverseNormal2( hit.normal );
      return new RayIntersection( distance, transformedPoint, normal, hit.wind, hit.t );
    } );
  }

  /**
   * Returns the resultant winding number of this ray intersecting this arc.
   */
  public windingIntersection( ray: Ray2 ): number {
    // be lazy. transform it into the space of a non-elliptical arc.
    const rayInUnitCircleSpace = this.getUnitTransform().inverseRay2( ray );
    return this.getUnitArcSegment().windingIntersection( rayInUnitCircleSpace );
  }

  /**
   * Draws this arc to the 2D Canvas context, assuming the context's current location is already at the start point
   */
  public writeToContext( context: CanvasRenderingContext2D ): void {
    if ( context.ellipse ) {
      context.ellipse( this._center.x, this._center.y, this._radiusX, this._radiusY, this._rotation, this._startAngle, this._endAngle, this._anticlockwise );
    }
    else {
      // fake the ellipse call by using transforms
      this.getUnitTransform().getMatrix().canvasAppendTransform( context );
      context.arc( 0, 0, 1, this._startAngle, this._endAngle, this._anticlockwise );
      this.getUnitTransform().getInverse().canvasAppendTransform( context );
    }
  }

  /**
   * Returns this elliptical arc transformed by a matrix
   */
  public transformed( matrix: Matrix3 ): EllipticalArc {
    const transformedSemiMajorAxis = matrix.timesVector2( Vector2.createPolar( this._radiusX, this._rotation ) ).minus( matrix.timesVector2( Vector2.ZERO ) );
    const transformedSemiMinorAxis = matrix.timesVector2( Vector2.createPolar( this._radiusY, this._rotation + Math.PI / 2 ) ).minus( matrix.timesVector2( Vector2.ZERO ) );
    const rotation = transformedSemiMajorAxis.angle;
    const radiusX = transformedSemiMajorAxis.magnitude;
    const radiusY = transformedSemiMinorAxis.magnitude;

    const reflected = matrix.getDeterminant() < 0;

    // reverse the 'clockwiseness' if our transform includes a reflection
    // TODO: check reflections. swapping angle signs should fix clockwiseness
    const anticlockwise = reflected ? !this._anticlockwise : this._anticlockwise;
    const startAngle = reflected ? -this._startAngle : this._startAngle;
    let endAngle = reflected ? -this._endAngle : this._endAngle;

    if ( Math.abs( this._endAngle - this._startAngle ) === Math.PI * 2 ) {
      endAngle = anticlockwise ? startAngle - Math.PI * 2 : startAngle + Math.PI * 2;
    }

    return new EllipticalArc( matrix.timesVector2( this._center ), radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise );
  }

  /**
   * Returns the contribution to the signed area computed using Green's Theorem, with P=-y/2 and Q=x/2.
   *
   * NOTE: This is this segment's contribution to the line integral (-y/2 dx + x/2 dy).
   */
  public getSignedAreaFragment(): number {
    const t0 = this._startAngle;
    const t1 = this.getActualEndAngle();

    const sin0 = Math.sin( t0 );
    const sin1 = Math.sin( t1 );
    const cos0 = Math.cos( t0 );
    const cos1 = Math.cos( t1 );

    // Derived via Mathematica (curve-area.nb)
    return 0.5 * ( this._radiusX * this._radiusY * ( t1 - t0 ) +
                   Math.cos( this._rotation ) * ( this._radiusX * this._center.y * ( cos0 - cos1 ) +
                   this._radiusY * this._center.x * ( sin1 - sin0 ) ) +
                   Math.sin( this._rotation ) * ( this._radiusX * this._center.x * ( cos1 - cos0 ) +
                   this._radiusY * this._center.y * ( sin1 - sin0 ) ) );
  }

  /**
   * Returns a reversed copy of this segment (mapping the parametrization from [0,1] => [1,0]).
   */
  public reversed(): EllipticalArc {
    return new EllipticalArc( this._center, this._radiusX, this._radiusY, this._rotation, this._endAngle, this._startAngle, !this._anticlockwise );
  }

  /**
   * Returns an object form that can be turned back into a segment with the corresponding deserialize method.
   */
  public serialize(): SerializedEllipticalArc {
    return {
      type: 'EllipticalArc',
      centerX: this._center.x,
      centerY: this._center.y,
      radiusX: this._radiusX,
      radiusY: this._radiusY,
      rotation: this._rotation,
      startAngle: this._startAngle,
      endAngle: this._endAngle,
      anticlockwise: this._anticlockwise
    };
  }

  /**
   * Determine whether two lines overlap over a continuous section, and if so finds the a,b pair such that
   * p( t ) === q( a * t + b ).
   *
   * @param segment
   * @param [epsilon] - Will return overlaps only if no two corresponding points differ by this amount or more
   *                             in one component.
   * @returns - The solution, if there is one (and only one)
   */
  public getOverlaps( segment: Segment, epsilon = 1e-6 ): Overlap[] | null {
    if ( segment instanceof EllipticalArc ) {
      return EllipticalArc.getOverlaps( this, segment );
    }

    return null;
  }

  /**
   * Returns an EllipticalArc from the serialized representation.
   */
  public static override deserialize( obj: SerializedEllipticalArc ): EllipticalArc {
    assert && assert( obj.type === 'EllipticalArc' );

    return new EllipticalArc( new Vector2( obj.centerX, obj.centerY ), obj.radiusX, obj.radiusY, obj.rotation, obj.startAngle, obj.endAngle, obj.anticlockwise );
  }

  /**
   * Returns what type of overlap is possible based on the center/radii/rotation. We ignore the start/end angles and
   * anticlockwise information, and determine if the FULL ellipses overlap.
   */
  public static getOverlapType( a: EllipticalArc, b: EllipticalArc, epsilon = 1e-10 ): EllipticalArcOverlapType {

    // Different centers can't overlap continuously
    if ( a._center.distance( b._center ) < epsilon ) {

      const matchingRadii = Math.abs( a._radiusX - b._radiusX ) < epsilon && Math.abs( a._radiusY - b._radiusY ) < epsilon;
      const oppositeRadii = Math.abs( a._radiusX - b._radiusY ) < epsilon && Math.abs( a._radiusY - b._radiusX ) < epsilon;

      if ( matchingRadii ) {
        // Difference between rotations should be an approximate multiple of pi. We add pi/2 before modulo, so the
        // result of that should be ~pi/2 (don't need to check both endpoints)
        if ( Math.abs( Utils.moduloBetweenDown( a._rotation - b._rotation + Math.PI / 2, 0, Math.PI ) - Math.PI / 2 ) < epsilon ) {
          return EllipticalArcOverlapType.MATCHING_OVERLAP;
        }
      }
      if ( oppositeRadii ) {
        // Difference between rotations should be an approximate multiple of pi (with pi/2 added).
        if ( Math.abs( Utils.moduloBetweenDown( a._rotation - b._rotation, 0, Math.PI ) - Math.PI / 2 ) < epsilon ) {
          return EllipticalArcOverlapType.OPPOSITE_OVERLAP;
        }
      }
    }

    return EllipticalArcOverlapType.NONE;
  }

  /**
   * Determine whether two elliptical arcs overlap over continuous sections, and if so finds the a,b pairs such that
   * p( t ) === q( a * t + b ).
   *
   * @returns - Any overlaps (from 0 to 2)
   */
  public static getOverlaps( a: EllipticalArc, b: EllipticalArc ): Overlap[] {

    const overlapType = EllipticalArc.getOverlapType( a, b );

    if ( overlapType === EllipticalArcOverlapType.NONE ) {
      return [];
    }
    else {
      return Arc.getAngularOverlaps( a._startAngle + a._rotation, a.getActualEndAngle() + a._rotation,
        b._startAngle + b._rotation, b.getActualEndAngle() + b._rotation );
    }
  }

  /**
   * Returns any (finite) intersection between the two elliptical arc segments.
   */
  public static override intersect( a: EllipticalArc, b: EllipticalArc, epsilon = 1e-10 ): SegmentIntersection[] {

    const overlapType = EllipticalArc.getOverlapType( a, b, epsilon );

    if ( overlapType === EllipticalArcOverlapType.NONE ) {
      return BoundsIntersection.intersect( a, b );
    }
    else {
      // If we effectively have the same ellipse, just different sections of it. The only finite intersections could be
      // at the endpoints, so we'll inspect those.

      const results = [];
      const aStart = a.positionAt( 0 );
      const aEnd = a.positionAt( 1 );
      const bStart = b.positionAt( 0 );
      const bEnd = b.positionAt( 1 );

      if ( aStart.equalsEpsilon( bStart, epsilon ) ) {
        results.push( new SegmentIntersection( aStart.average( bStart ), 0, 0 ) );
      }
      if ( aStart.equalsEpsilon( bEnd, epsilon ) ) {
        results.push( new SegmentIntersection( aStart.average( bEnd ), 0, 1 ) );
      }
      if ( aEnd.equalsEpsilon( bStart, epsilon ) ) {
        results.push( new SegmentIntersection( aEnd.average( bStart ), 1, 0 ) );
      }
      if ( aEnd.equalsEpsilon( bEnd, epsilon ) ) {
        results.push( new SegmentIntersection( aEnd.average( bEnd ), 1, 1 ) );
      }

      return results;
    }
  }

  /**
   * Transforms the unit circle into our ellipse.
   *
   * adapted from http://www.w3.org/TR/SVG/implnote.html#PathElementImplementationNotes
   */
  public static computeUnitTransform( center: Vector2, radiusX: number, radiusY: number, rotation: number ): Transform3 {
    return new Transform3( Matrix3.translation( center.x, center.y ) // TODO: convert to Matrix3.translation( this._center) when available
      .timesMatrix( Matrix3.rotation2( rotation ) )
      .timesMatrix( Matrix3.scaling( radiusX, radiusY ) ) );
  }
}

export class EllipticalArcOverlapType extends EnumerationValue {
  // radiusX of one equals radiusX of the other, with equivalent centers and rotations to work
  public static MATCHING_OVERLAP = new EllipticalArcOverlapType();

  // radiusX of one equals radiusY of the other, with equivalent centers and rotations to work
  public static OPPOSITE_OVERLAP = new EllipticalArcOverlapType();

  // no overlap
  public static NONE = new EllipticalArcOverlapType();

  public static enumeration = new Enumeration( EllipticalArcOverlapType );
}

kite.register( 'EllipticalArc', EllipticalArc );


text:
package com.lithium.ldn.starql.parsers;

import static org.junit.Assert.assertEquals;

import org.codehaus.jparsec.error.ParserException;
import org.junit.Assert;
import org.junit.Test;

import com.lithium.ldn.starql.models.QlPageConstraints;

public class JparsecPageConstraintsTest extends JparsecTest {

	@Test
	public final void test_pageConstraints() {
		try {
			String word = "";
			QlPageConstraints pageConstraint = inst.pageConstraintParser().parse(word);
			assertEquals(-1, pageConstraint.getLimit());
			assertEquals(-1, pageConstraint.getOffset());
		} catch (ParserException e) {
			Assert.fail("PageConstraints can be blank");
		}
	}

	@Test
	public final void test_pageConstraints1() {
		assertEquals(defaultLimit,
				inst.pageConstraintParser().parse("LIMIT 10"));
	}

	@Test
	public final void test_pageConstraints2() {
		assertEquals(defaultOffset,
				inst.pageConstraintParser().parse("OFFSET 100"));
	}

	@Test
	public final void test_pageConstraints3() {
		assertEquals(defaultPage,
				inst.pageConstraintParser().parse("LIMIT 10 OFFSET 100"));
	}

	@Test
	public final void test_pageConstraints4() {
		assertEquals(defaultPage,
				inst.pageConstraintParser().parse("limit 10 offset 100"));
	}

	@Test
	public final void test_pageConstraints5() {
		assertEquals(defaultLimitAndCursor,
				inst.pageConstraintParser().parse(String.format("LIMIT 10 CURSOR '%1$s'", CURSOR)));
	}

	@Test
	public final void test_pageConstraints6() {
		assertEquals(defaultLimitAndCursor,
				inst.pageConstraintParser().parse(String.format("limit 10 cursor '%1$s'", CURSOR)));
	}

	@Test
	public final void test_pageConstraints7() {
		assertEquals(defaultCursor,
				inst.pageConstraintParser().parse(String.format("CURSOR '%1$s'", CURSOR)));
	}

	@Test
	public final void test_pageConstraints8() {
		assertEquals(defaultCursor,
				inst.pageConstraintParser().parse(String.format("cursor '%1$s'", CURSOR)));
	}
}


text:
0.8.1 / 2013-10-24
------------------
* copy failed to return an error to the callback if a file doesn't exist (ulikoehler #38, #39)

0.8.0 / 2013-10-14
------------------
* `filter` implemented on `copy()` and `copySync()`. (Srirangan / #36)

0.7.1 / 2013-10-12
------------------
* `copySync()` implemented (Srirangan / #33)
* updated to the latest `jsonfile` version `1.1.0` which gives `options` params for the JSON methods. Closes #32

0.7.0 / 2013-10-07
------------------
* update readme conventions
* `copy()` now works if destination directory does not exist. Closes #29

0.6.4 / 2013-09-05
------------------
* changed `homepage` field in package.json to remove NPM warning

0.6.3 / 2013-06-28
------------------
* changed JSON spacing default from `4` to `2` to follow Node conventions
* updated `jsonfile` dep
* updated `rimraf` dep

0.6.2 / 2013-06-28
------------------
* added .npmignore, #25

0.6.1 / 2013-05-14
------------------
* modified for `strict` mode, closes #24
* added `outputJson()/outputJsonSync()`, closes #23

0.6.0 / 2013-03-18
------------------
* removed node 0.6 support
* added node 0.10 support
* upgraded to latest `ncp` and `rimraf`.
* optional `graceful-fs` support. Closes #17

0.5.0 / 2013-02-03
------------------
* Removed `readTextFile`.
* Renamed `readJSONFile` to `readJSON` and `readJson`, same with write.
* Restructured documentation a bit. Added roadmap.

0.4.0 / 2013-01-28
------------------
* Set default spaces in `jsonfile` from 4 to 2.
* Updated `testutil` deps for tests.
* Renamed `touch()` to `createFile()`
* Added `outputFile()` and `outputFileSync()`
* Changed creation of testing diretories so the /tmp dir is not littered.
* Added `readTextFile()` and `readTextFileSync()`.

0.3.2 / 2012-11-01
------------------
* Added `touch()` and `touchSync()` methods.

0.3.1 / 2012-10-11
------------------
* Fixed some stray globals.

0.3.0 / 2012-10-09
------------------
* Removed all CoffeeScript from tests.
* Renamed `mkdir` to `mkdirs`/`mkdirp`.

0.2.1 / 2012-09-11
------------------
* Updated `rimraf` dep.

0.2.0 / 2012-09-10
------------------
* Rewrote module into JavaScript. (Must still rewrite tests into JavaScript)
* Added all methods of [jsonfile][https://github.com/jprichardson/node-jsonfile]
* Added Travis-CI.

0.1.3 / 2012-08-13
------------------
* Added method `readJSONFile`.

0.1.2 / 2012-06-15
------------------
* Bug fix: `deleteSync()` didn't exist.
* Verified Node v0.8 compatibility.

0.1.1 / 2012-06-15
------------------
* Fixed bug in `remove()`/`delete()` that wouldn't execute the function if a callback wasn't passed.

0.1.0 / 2012-05-31
------------------
* Renamed `copyFile()` to `copy()`. `copy()` can now copy directories (recursively) too.
* Renamed `rmrf()` to `remove()`.
* `remove()` aliased with `delete()`.
* Added `mkdirp` capabilities. Named: `mkdir()`. Hides Node.js native `mkdir()`.
* Instead of exporting the native `fs` module with new functions, I now copy over the native methods to a new object and export that instead.

0.0.4 / 2012-03-14
------------------
* Removed CoffeeScript dependency

0.0.3 / 2012-01-11
------------------
* Added methods rmrf and rmrfSync
* Moved tests from Jasmine to Mocha


text:
namespace Testura.Code.Models.References;

/// <summary>
/// Represent the member reference on another reference.
/// </summary>
public class MemberReference : VariableReference
{
    /// <summary>
    /// Initializes a new instance of the <see cref="MemberReference"/> class.
    /// </summary>
    /// <param name="name">Name of the member.</param>
    public MemberReference(string name)
        : base(name)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="MemberReference"/> class.
    /// </summary>
    /// <param name="name">Name of the member reference.</param>
    /// <param name="memberReference">Member to reference on the member.</param>
    public MemberReference(string name, MemberReference memberReference)
        : this(name)
    {
        Member = memberReference;
    }
}


text:
import React, { Component, PropTypes } from 'react';
import { Editor } from 'remotedev-monitor-components';
import stringify from 'javascript-stringify';

export default class RawTab extends Component {
  constructor(props) {
    super(props);
    this.stringifyData(props);
  }

  shouldComponentUpdate(nextProps) {
    return nextProps.data !== this.value;
  }

  componentWillUpdate(nextProps) {
    this.stringifyData(nextProps);
  }

  stringifyData(props) {
    this.value = stringify(props.data, null, 2);
  }

  render() {
    return (
      <Editor theme="night" value={this.value} />
    );
  }
}


text:
  <meta charset="utf-8">
  <title>Mocha Tests</title>
  <link href="https://unpkg.com/mocha@5.2.0/mocha.css" rel="stylesheet" />


text:
package com.b2international.commons;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;

/**
 * Single-class implementation of Marcel Sauer's TokenReplacer, using utility
 * methods from Guava.
 *

 * Actualized documentation follows:
 *

 * Toky is a token replacer for Strings. It will replace the found token with a
 * provided static value or a dynamically generated value created by a
 * {@link Function}. Toky itself IS NOT THREAD SAFE, so access to a
 * single instance in a multi-threaded environment should be synchronized by the
 * client.
 *

 *
 *

 * Simplest use case, only static values:
 *

 *
 *

 * TokenReplacer toky = new TokenReplacer().register("number", "123");
 * toky.substitute("i can count to {number}");
 *

 *
 *

 * We can also use a {@link Function} to dynamically get the
 * value:
 *

 *
 *

 * toky = new TokenReplacer().register("number", new Function<String[], String>() {
 * 	@Override
 * 	public String apply(String[] input) {
 * 		return "123";
 * 	}
 * });
 *

 *

 * Here we use a generator and pass the arguments "a,b,c" to it, they
 * will be applied via {@link Function#apply(Object) Function#apply(String[])}.
 * This feature makes handling tokens pretty powerful because you can write very
 * dynamic generators.
 *

 *
 *

 * toky.substitute("i can count to {number(a,b,c)}");
 *

 *
 * If you prefer to use index based tokens, you can also use this:
 *
 *

 * toky.register(new String[] { "one", "two", "three" });
 * toky.substitute("abc {0} {1} {2} def")); // will produce "abc one two three def"
 *

 *
 *

 * Of course you can replace all default delimiters with your preferred
 * ones, just make sure start and end are different.
 *

 *
 *

 * toky.withTokenStart("*"); // default is '{'
 * toky.withTokenEnd("#"); // default is '}'
 * toky.withArgumentDelimiter(";"); // default is ','
 * toky.withArgumentStart("["); // default is '('
 * toky.withArgumentEnd("]"); // default is ')'
 *

 *
 *

 * By default, Toky will throw IllegalStateExceptions if there was no matching
 * value or generator found for a token. you can enable generating
 * exceptions by calling:
 *

 *
 *

 * toky.doNotIgnoreMissingValues(); // which is the DEFAULT
 *

 *
 *

 * This will turn error reporting for missing values OFF:
 *

 *
 *

 * toky.ignoreMissingValues();
 *

 *
 *

 * You can also enable/disable generator caching. If you enable caching
 * once a generator for a token returned a value this value will be used for all
 * subsequent tokens with the same name otherwise the generator will be called
 * once for every token.

 *

 *
 * e.g. {counter}{counter}{counter}

 *

 *
 * With a registered generator will result in 3 calls to the generator
 * (resulting in poorer performance), so if you know your generator will always
 * return the same value, enable caching.
 *

 *
 *

 * toky.enableGeneratorCaching();
 * toky.disableGeneratorCaching();
 *

 *
 * @see {@link https://github.com/niesfisch/tokenreplacer}
 *
 * @author Marcel Sauer (msauer)
 */
public class TokenReplacer {

	private static class LiteralFunction implements Function<String[], String> {

		private final String value;

		private LiteralFunction(String value) {
			this.value = value;
		}

		@Override
		public String apply(String[] input) {
			return value;
		}
	}

	private static final String[] EMPTY_STRING_ARRAY = new String[] {};

	private static final char DEFAULT_TOKEN_START = '{';
	private static final char DEFAULT_TOKEN_END = '}';
	private static final char DEFAULT_ARGS_SEPARATOR = ',';
	private static final char DEFAULT_ARGS_START = '(';
	private static final char DEFAULT_ARGS_END = ')';

	protected char tokenStart = DEFAULT_TOKEN_START;
	protected char tokenEnd = DEFAULT_TOKEN_END;

	protected char argsStart = DEFAULT_ARGS_START;
	protected char argsEnd = DEFAULT_ARGS_END;
	protected char argsSep = DEFAULT_ARGS_SEPARATOR;

	protected boolean ignoreMissingValues = false;
	protected boolean generatorCachingEnabled = false;

	protected final Map<String, Function<String[], String>> tokens = Maps.newHashMap();

	protected enum State {
		READING_INPUT,
		TOKEN_STARTED,
		READING_TOKEN,
		TOKEN_ARGS_STARTED,
		READING_TOKEN_ARGS,
		TOKEN_ARGS_END
	}

	/**
	 * Replaces all tokens in the specified input with one of the following:
	 *
	 *

	 *
the provided static values set via {@link #register(String, String)}
	 *
the generator registered via {@link #register(String, Generator)}
	 *

	 *
	 * @param toSubstitute
	 *            the string that contains the tokens, will be returned as-is in
	 *            case of {@code null} or empty string
	 *
	 * @return the result after replacing all tokens with the proper values
	 *
	 * @throws IllegalArgumentException
	 *             if a parse error occurs while processing the input string
	 */
	public String substitute(String toSubstitute) {

		if (toSubstitute == null || toSubstitute.isEmpty()) {
			return toSubstitute;
		}

		final StringBuilder tokenBuilder = new StringBuilder();
		final StringBuilder argsBuilder = new StringBuilder();
		final StringBuilder resultBuilder = new StringBuilder();

		final Map<String, String> generatorCache = new HashMap<String, String>();

		State state = State.READING_INPUT;

		for (int i = 0; i < toSubstitute.length(); ++i) {

			final char c = toSubstitute.charAt(i);

			switch (state) {

				case READING_INPUT:
					if (isTokenStart(c)) {
						state = State.TOKEN_STARTED;
						tokenBuilder.setLength(0);
					} else {
						resultBuilder.append(c);
					}

					break;

				case TOKEN_STARTED:

					if (isStdInput(c)) {
						state = State.READING_TOKEN;
						tokenBuilder.append(c);
					} else {
						error(toSubstitute);
					}

					break;

				case READING_TOKEN:

					if (isStdInput(c)) {
						tokenBuilder.append(c);
					} else if (isArgStart(c)) {
						state = State.TOKEN_ARGS_STARTED;
						argsBuilder.setLength(0);
					} else if (isTokenEnd(c)) {
						state = State.READING_INPUT;
						resultBuilder.append(
								evalToken(tokenBuilder.toString(), argsBuilder.toString(), generatorCache));
					} else {
						error(toSubstitute);
					}

					break;

				case TOKEN_ARGS_STARTED:

					if (isArgEnd(c)) {
						state = State.TOKEN_ARGS_END;
					} else if (isStdInput(c)) {
						state = State.READING_TOKEN_ARGS;
						argsBuilder.append(c);
					} else {
						error(toSubstitute);
					}

					break;

				case READING_TOKEN_ARGS:

					if (isArgEnd(c)) {
						state = State.TOKEN_ARGS_END;
					} else if (isStdInput(c)) {
						argsBuilder.append(c);
					} else {
						error(toSubstitute);
					}

					break;

				case TOKEN_ARGS_END:

					if (isTokenEnd(c)) {
						state = State.READING_INPUT;
						resultBuilder.append(
								evalToken(tokenBuilder.toString(), argsBuilder.toString(), generatorCache));
					} else {
						error(toSubstitute);
					}

					break;
			}
		}

		if (!isFinalStateReached(state)) {
			error(toSubstitute);
		}

		return resultBuilder.toString();
	}

	private void error(String toSubstitute) {
		throw new IllegalArgumentException("Couldn't parse string '" + toSubstitute + "'.");
	}

	private boolean isFinalStateReached(State state) {
		return state == State.READING_INPUT;
	}

	protected boolean isArgStart(char c) {
		return argsStart == c;
	}

	protected boolean isArgEnd(char c) {
		return argsEnd == c;
	}

	protected boolean isTokenStart(char c) {
		return tokenStart == c;
	}

	protected boolean isTokenEnd(char c) {
		return tokenEnd == c;
	}

	protected boolean isStdInput(char c) {
		boolean isIdentifier = isTokenStart(c) || isTokenEnd(c) || isArgStart(c) || isArgEnd(c);
		return (!isIdentifier);
	}

	protected String[] extractArgs(final String tokenName, final String args) {

		if (args.isEmpty()) {
			return EMPTY_STRING_ARRAY;
		}

		checkArgumentsAreValid(tokenName, args);

		String[] argsResult = Iterables.toArray(Splitter.on(argsSep).trimResults().split(args), String.class);
		return argsResult;
	}

	protected void checkArgumentsAreValid(final String tokenName, final String args) {

		if (args.startsWith(",") || args.endsWith(",")) {

			throw new IllegalArgumentException(
					String.format("Invalid argument list '%s' for token '%s'.", args, tokenName));
		}
	}

	protected String evalToken(final String token, final String args, final Map<String, String> generatorCache) {

		final String[] argsResult = extractArgs(token, args);

		if (!this.tokens.containsKey(token)) {

			if (this.ignoreMissingValues) {
				return tokenWithPossibleArguments(token, args);
			} else {
				throw new IllegalArgumentException(
						String.format("No value registered for token '%s'.", token));
			}
		}

		return getGeneratorValue(token, argsResult, generatorCache);
	}

	private String getGeneratorValue(final String tokenName, final String[] args, final Map<String, String> generatorCache) {

		if (this.generatorCachingEnabled && generatorCache.containsKey(tokenName)) {
			return generatorCache.get(tokenName);
		}

		final Function<String[], String> generator = this.tokens.get(tokenName);
		final String value = generator.apply(args);

		if (this.generatorCachingEnabled) {
			generatorCache.put(tokenName, value);
		}

		return value;
	}

	private String tokenWithPossibleArguments(final String token, final String args) {

		if (args.length() > 0) {
			return this.tokenStart + token.toString() + this.argsStart + args + this.argsEnd + this.tokenEnd;
		} else {
			return this.tokenStart + token.toString() + this.tokenEnd;
		}
	}

	public TokenReplacer register(final String token, final String value) {

		checkNotNull(token);
		checkState(!token.isEmpty(), "token is empty.");
		checkNotNull(value);

		return register(token, new LiteralFunction(value));
	}

	public TokenReplacer register(String token, Function<String[], String> generator) {

		checkNotNull(token);
		checkNotNull(generator);

		tokens.put(token, generator);
		return this;
	}

	public TokenReplacer withTokenStart(char tokenStart) {
		this.tokenStart = tokenStart;
		return this;
	}

	public TokenReplacer withTokenEnd(char tokenEnd) {
		this.tokenEnd = tokenEnd;
		return this;
	}

	public TokenReplacer withArgumentDelimiter(char argsSep) {
		this.argsSep = argsSep;
		return this;
	}

	public TokenReplacer withArgumentStart(char argsStart) {
		this.argsStart = argsStart;
		return this;
	}

	public TokenReplacer withArgumentEnd(char argsEnd) {
		this.argsEnd = argsEnd;
		return this;
	}

	public TokenReplacer doNotIgnoreMissingValues() {
		this.ignoreMissingValues = false;
		return this;
	}

	public TokenReplacer ignoreMissingValues() {
		this.ignoreMissingValues = true;
		return this;
	}

	public TokenReplacer enableGeneratorCaching() {
		this.generatorCachingEnabled = true;
		return this;
	}

	public TokenReplacer disableGeneratorCaching() {
		this.generatorCachingEnabled = false;
		return this;
	}

	public TokenReplacer register(String[] replacements) {

		checkNotNull(replacements);

		int i = 0;

		for (String replacement : replacements) {
			this.register(String.valueOf(i), replacement);
			i++;
		}

		return this;
	}
}


text:
<!--settings(
title=Node.Cs Installation
description=Node.Cs Installation.
)-->

<!--include(shared/breadcrumb.php)-->

## {Title}

First and most important: If you use these libraries, please give me some feedback to improve them with the
disqus form at the end of the page or with this site contact form. Without your support i'll follow only my
selfish development needs!

Note that when installing the various packages from nuget command prompt you should specify the -Pre option,
since everything is in alpha at this time. At the same time, for the very same reason, when installing from
the visual interface, you should allow to show the prereleases.

### Prerequisites

* .Net Framework 4.5 or more
* Nuget Package Manager installed on Visual Studio
* Visual Studio 2012 or more, all version (Express/Pro/Wetheaver)
* The Node.Cs Project Template from downloadble [here]({This}Node.Cs.Extension.zip)

A Mono port is on the way!

### Available packages

Everything available for nuget (now in pre-release, when the documention will be more or less completed i'll publish them as "official")

* [Node.Cs.Cmd](http://www.nuget.org/packages/Node.Cs.Cmd/): The command line runner for the Node.Cs server
* [Node.Cs.Commons](http://www.nuget.org/packages/Node.Cs.Commons/): The minimum interfaces and classes to develop plugins and web sites
* [Node.Cs.Lib](http://www.nuget.org/packages/Node.Cs.Lib/): The core functionalities
* [Node.Cs.Razor](http://www.nuget.org/packages/Node.Cs.Razor/): The razor engine, compatible with the Ms one.
* [Node.Cs.EntityFramework](http://www.nuget.org/packages/Node.Cs.EntityFramework/): EntityFramework plugin, contains an authorization provider.
* [Node.Cs.Admin](http://www.nuget.org/packages/Node.Cs.Admin/): Administration interfaces and performances.

### Node.Cs Project Template

#### Structure

The basic project is a standard .Net class library, based on framework 4.5 or greater.

It's pretty simple, can be created directly with the specific Node.Cs template [here]({This}Node.Cs.Extension.vsix)
It follows more or less the MVC file structure (to be compatible with the MVC 4 nuget packages)

* App_Bin: The application binaries, configurable
* App_Data: The application data (mdf/ldf/...) directory

* Views: The cshtml files as in standard Ms MVC projects
* Content: Bare content files like css and jpg
* Scripts: All javascripts

* node.config: The configuration file
* GlobalNodeCs.cs: The global.asax equivalent for node cs.

* Controllers: The package for the controllers
* Models: containing the view models

#### The compilation and debugging process

After the "standard" class library compilation,

* The Node.Cs.Cmd.exe, that is the true server executable is copied inside the App_Bin directory.
* All dlls inside the project target folder (e.g. MyProject/bin/Release) are copied inside the App_Bin.

To debug, the site is run calling the Node.Cs.Cmd.exe:

	MyProject/App_Bin/Node.Cs.Cmd.exe -config MyProject/node.config

This will be the default run configuration.

During the debugging only the dlls specified inside the configuration will be loaded despite what is set inside the project references.

#### Syntax highlight for cshtml/razor

To allow the usage of syntax highlight inside Razor, inside the project template is present a web.config file, and exists all ther references
to the .Net standard razor dlls. This is used ONLY to cheat the Visual Stuido parser and keep smooth the development of the various chstml
files "the standard way".

#### Files needed for the deployment

* The App_Bin diretory
* The App_Data directory if is used the default EntityFramewir
* Content,Views and Scripts directories
* node.config

The idea is that into the AfterBuild step all the binaries will be copied into the App_Bin directory. With the Node.Cs template all these task are accomplied inside the .csproj file directly.

#### The content furhter explained

If you want to follow the easy way just install the Node.Cs.Extension from the extensions library,
create a new Node.Cs.Project, enable the Nuget Packages Restore and rebuild all.

Please note that the default project template will include the Razor module and is able to handle
out of the box, the standard handling of controllers and views like with .Net MVC.

The content of the freshly created project will be:

* App_Web: The directory containing the files visible from the web server
* Views: The MVC views
	* Home: The views relative to the HomeController
		* index.cshtml: A simple view to check that the whole system works correctly
* App_Data: The directory containing the .mdf/.ldf database files
* App_Bin: The directory containing the dlls needed to run the application and the web server
* node.config: The configuration file for the application, already configured for the actual configuration.
* web.config: A stripped down version of the standard IIS web config. This is needed only to allow the syntax higlight for the cshtml views
* GlobalNodeCs.cs: The equivalent for node.cs of the Global.asax in IIS
* Controllers: The controllers directory
	* HomeController.cs: The "Home" controller, containing the action handler for the previously described index.cshtml

## Licensing

Copyright (C) 2013-2014 Kendar.org

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

## Download

See [kendar.org](http://www.kendar.org/dotnet/nodecs "Kendar.org") for the latest changes.