text:
import cv2
import numpy as np
import os
import pickle
import random
import config

from multiprocessing.pool import ThreadPool

import logbook
logger = logbook.Logger(__name__)

SIFT = cv2.xfeatures2d.SIFT_create(contrastThreshold=config.SIFT_CONTRAST_THRESHOLD, edgeThreshold=config.SIFT_EDGE_THRESHOLD, sigma=config.SIFT_SIGMA)
FLANN = cv2.FlannBasedMatcher(config.FLANN_INDEX_PARAMS, config.FLANN_SEARCH_PARAMS)
BF = cv2.BFMatcher(normType=cv2.NORM_HAMMING)

class Match(object):
    def __init__(self, nissl_level, matches, H, mask, result, result2, dist):
        self.nissl_level = nissl_level
        self.matches = matches
        self.H = H
        self.mask = mask
        self.result = result
        self.result2 = result2

        self.dist = dist

        self.matches_count = len(matches)
        self.inlier_count = mask.sum()
        self.inlier_ratio = int(self.inlier_count / self.matches_count * 100)

        self.homography_det = abs(np.linalg.det(H))

        self.svd = np.linalg.svd(self.H, compute_uv=False)
        self.svd_ratio = int(self.svd[0] / self.svd[-1])

    def comparison_key(self):
        return self.inlier_count
        #return -((1/self.inlier_ratio) * (self.svd_ratio) * self.homography_det * self.dist)

    # ['Plate', 'Match Count', 'Inlier Count', 'I/M', 'SVD', 'Det H']
    def to_string_array(self):
        return np.array([
            "Plate #" + str(self.nissl_level),
            str(self.matches_count),
            str(self.inlier_count),
            str(self.inlier_ratio),
            str(self.svd_ratio),
            str(self.homography_det),
            str((1/self.inlier_ratio) * (self.svd_ratio) * self.homography_det * self.dist)
            ])

def warp(im, points, disp_min, disp_max, disp_len = None, disp_angle = None):
    h, w = im.shape[:2]

    # Include the corners
    src_pts = np.array([[0, 0], [w, 0], [0, h], [w, h]])
    dst_pts = np.array([[0, 0], [w, 0], [0, h], [w, h]])

    for i in range(points):
        rand_x = random.uniform(0, w)
        rand_y = random.uniform(0, h)
        p = np.array([rand_x, rand_y])
        if disp_len is None:
            rand_len = random.uniform(disp_min, disp_max)
        else:
            rand_len = disp_len

        if disp_angle is None:
            rand_angle = np.deg2rad(random.uniform(0, 360))
        else:
            rand_angle = disp_angle

        p2_x = rand_x + np.cos(rand_angle) * rand_len
        p2_y = rand_y + np.sin(rand_angle) * rand_len
        p2 = np.array([p2_x, p2_y])

        if src_pts is None:
            src_pts = np.array([p])
        else:
            temp = np.vstack((src_pts, p))
            src_pts = temp

        if dst_pts is None:
            dst_pts = np.array([p2])
        else:
            temp = np.vstack((dst_pts, p2))
            dst_pts = temp

    from skimage.transform import warp, PiecewiseAffineTransform
    tform = PiecewiseAffineTransform()
    tform.estimate(src_pts, dst_pts)
    warped_im = warp(im, tform)

    # Convert to OpenCV
    from skimage import img_as_ubyte
    warped_im = img_as_ubyte(warped_im)
    return warped_im

def im_read(filename, flags=cv2.IMREAD_COLOR):
    im = cv2.imread(filename, flags)

    if flags == cv2.IMREAD_COLOR:
        # Convert from BGR to RGB for some reason
        im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)

    return im

def im_write(filename, im):
    if len(im.shape) == 3:
        # Not grayscale
        # Convert back to the original BGR
        im = cv2.cvtColor(im, cv2.COLOR_RGB2BGR)

    cv2.imwrite(filename, im)

def nissl_load(nissl_level, color_flags=cv2.IMREAD_COLOR):
    filename = config.NISSL_PREFIX + str(nissl_level).zfill(config.NISSL_DIGITS) + config.NISSL_EXT
    path = os.path.join(config.NISSL_DIR, filename)

    if not os.path.exists(path):
        logger.error("Tried to load plate {0} but it wasn't found in path {1}", nissl_level, path)
        return None

    return im_read(path, color_flags)

def nissl_load_sift(nissl_level):
    filename = config.NISSL_PREFIX + str(nissl_level).zfill(config.NISSL_DIGITS) + ".sift"
    path = os.path.join(config.NISSL_DIR, filename)

    if not os.path.exists(path):
        logger.info("Creating SIFT for plate {0}", nissl_level)
        nissl = nissl_load(nissl_level, cv2.IMREAD_GRAYSCALE)
        if nissl is None:
            return None

        kp, des = extract_sift(nissl)
        temp = pickle_sift(kp, des)
        pickle.dump(temp, open(path, "wb"))
        return kp, des

    else:
        raw_sift = pickle.load(open(path, "rb"))
        kp, des = unpickle_sift(raw_sift)
        return kp, des

def match(im1, kp1, des1, im2, kp2, des2):
    if config.MATCH_WITH_FLANN:
        matches = FLANN.knnMatch(des1, des2, k=2)
    else:
        matches = BF.knnMatch(des1, des2, k=2)

    # Apply Ratio Test
    good_matches = [m[0] for m in matches if len(m) == 2 and m[0].distance < m[1].distance * config.DISTANCE_RATIO]

    if len(good_matches) < config.MIN_MATCH_COUNT:
        logger.debug("Matches lower than threshold. {0} < {1}", len(good_matches), config.MIN_MATCH_COUNT)
        return None

    # For homography calculation
    src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches])
    dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches])

    # Obtain the homography matrix using RANSAC
    H, mask = cv2.findHomography(src_pts, dst_pts, method=cv2.RANSAC, ransacReprojThreshold=config.RANSAC_REPROJ_TRESHHOLD, maxIters=config.RANSAC_MAX_ITERS, confidence=config.RANSAC_CONFIDENCE)

    # Check homography validity
    if H is None or len(H.shape) != 2:
        logger.debug("Couldn't get homography")
        return None

    # This mask contains the inliers
    matchesMask = mask.ravel().tolist()

    # Calculate the homography determinant
    det = np.linalg.det(H)
    logger.debug("Homography determinant = {0:f}", det)

    # If it's too low for comfort, don't consider the match
    # Or too high
    #if abs(det) < 0.01 or abs(det) > 5:
    #    return None

    # Apply the perspective transformation to the source image corners
    h, w = im1.shape[:2]
    corners = np.float32([[0, 0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)

    # Attempt to transform corners based on homography
    try:
        transformedCorners = cv2.perspectiveTransform(corners, H)
    except:
        logger.debug("Couldn't transform corners")
        return None

    # Only accept corners that remain convex after being transformed
    isConvex = cv2.isContourConvex(transformedCorners)
    if not isConvex:
        return None

    # Get the 7 Hu invariant moments
    original_moments = cv2.HuMoments(cv2.moments(corners)).flatten()
    transformed_moments = cv2.HuMoments(cv2.moments(transformedCorners)).flatten()

    # Find the Euclidean distance between the moments
    hu_distance = np.linalg.norm(original_moments - transformed_moments)
    logger.debug("[Hu Moment Distance] = {0}", hu_distance)

    # Ignore moments that are too large
    #if hu_distance > config.HU_DISTANCE_THRESHOLD:
    #    return None

    # Draw a polygon on the second image joining the transformed corners
    im2 = cv2.polylines(im2, [np.int32(transformedCorners)], True, config.MATCH_RECT_COLOR, 2, cv2.LINE_AA)

    # Prepare drawing parameters for drawing lines between matches
    #drawParameters = dict(matchColor=None, singlePointColor=None, matchesMask=None, flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)
    drawParameters = dict(matchColor=None, singlePointColor=None, matchesMask=matchesMask, flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)

    # Draw the lines between the 2 images connecting matches
    im_matches = cv2.drawMatches(im1, kp1, im2, kp2, good_matches, None, **drawParameters)

    # Warp the first image onto the second image
    im_warp = cv2.warpPerspective(im1, H, (im2.shape[1],im2.shape[0]))

    # Find the pixels which are visible in the warped image
    overlay_mask = (im_warp != 0)

    # Create a copy of the second image
    im_overlay = im2

    # Overlay the warped image on top of the 2nd image
    # If the mask is grayscale the overlay will only be applied to the red channel
    if len(overlay_mask.shape) == 3: # Overlay colors
        im_overlay[overlay_mask] = im_warp[overlay_mask]
    else:
        im_overlay[overlay_mask, 0] = im_warp[overlay_mask]

    return Match(None, good_matches, H, mask, im_matches, im_overlay, hu_distance)

def match_fast(kp1, des1, kp2, des2):
    if config.MATCH_WITH_FLANN:
        matches = FLANN.knnMatch(des1, des2, k=2)
    else:
        matches = BF.knnMatch(des1, des2, k=2)

    # Apply Ratio Test
    good_matches = [m[0] for m in matches if len(m) == 2 and m[0].distance < m[1].distance * config.DISTANCE_RATIO]

    # For homography calculation
    src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches])
    dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches])

    # Obtain the homography matrix using RANSAC
    H, mask = cv2.findHomography(src_pts, dst_pts, method=cv2.RANSAC, ransacReprojThreshold=config.RANSAC_REPROJ_TRESHHOLD, maxIters=config.RANSAC_MAX_ITERS, confidence=config.RANSAC_CONFIDENCE)

    return good_matches

def match_region_nissl(im_region, nissl_level):
    kp1, des1 = extract_sift(im_region)

    kp2, des2 = nissl_load_sift(nissl_level)
    im_nissl = nissl_load(nissl_level)

    m = match(im_region, kp1, des1, im_nissl, kp2, des2)
    if m is None:
        return None
    else:
        m.nissl_level = nissl_level
        logger.debug("Match accepted")
        return m

def match_sift_nissl(im_region, kp1, des1, nissl_level):
    logger.debug("=============== Matching {0}", nissl_level)
    kp2, des2 = nissl_load_sift(nissl_level)
    im_nissl = nissl_load(nissl_level)

    m = match(im_region, kp1, des1, im_nissl, kp2, des2)

    if m is None:
        return None
    else:
        m.nissl_level = nissl_level
        return m

def extract_sift(im):
    if im.dtype != np.uint8:
            im = (im * 255).astype(np.uint8)

    if len(im.shape) == 3:
        im = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY)

    # Use multithreading to split the affine detection work
    pool = ThreadPool(processes = cv2.getNumberOfCPUs())

    #kp, des = affine_detect(SIFT, im, pool=pool)
    kp, des = SIFT.detectAndCompute(im, None)

    pool.close()
    pool.join()

    return kp, des

def affine_skew(tilt, phi, img, mask=None):
    '''
    affine_skew(tilt, phi, img, mask=None) -> skew_img, skew_mask, Ai
    Ai - is an affine transform matrix from skew_img to img
    '''
    h, w = img.shape[:2]
    if mask is None:
        mask = np.zeros((h, w), np.uint8)
        mask[:] = 255
    A = np.float32([[1, 0, 0], [0, 1, 0]])
    if phi != 0.0:
        phi = np.deg2rad(phi)
        s, c = np.sin(phi), np.cos(phi)
        A = np.float32([[c,-s], [ s, c]])
        corners = [[0, 0], [w, 0], [w, h], [0, h]]
        tcorners = np.int32( np.dot(corners, A.T) )
        x, y, w, h = cv2.boundingRect(tcorners.reshape(1,-1,2))
        A = np.hstack([A, [[-x], [-y]]])
        img = cv2.warpAffine(img, A, (w, h), flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_REPLICATE)
    if tilt != 1.0:
        s = 0.8*np.sqrt(tilt*tilt-1)
        img = cv2.GaussianBlur(img, (0, 0), sigmaX=s, sigmaY=0.01)
        img = cv2.resize(img, (0, 0), fx=1.0/tilt, fy=1.0, interpolation=cv2.INTER_NEAREST)
        A[0] /= tilt
    if phi != 0.0 or tilt != 1.0:
        h, w = img.shape[:2]
        mask = cv2.warpAffine(mask, A, (w, h), flags=cv2.INTER_NEAREST)
    Ai = cv2.invertAffineTransform(A)
    return img, mask, Ai

def affine_detect(detector, img, mask=None, pool=None):
    '''
    affine_detect(detector, img, mask=None, pool=None) -> keypoints, descrs
    Apply a set of affine transormations to the image, detect keypoints and
    reproject them into initial image coordinates.
    See http://www.ipol.im/pub/algo/my_affine_sift/ for the details.
    ThreadPool object may be passed to speedup the computation.
    '''
    params = [(1.0, 0.0)]
    for t in 2**(0.5*np.arange(1,6)):
        for phi in np.arange(0, 180, 72.0 / t):
            params.append((t, phi))

    def f(p):
        t, phi = p
        timg, tmask, Ai = affine_skew(t, phi, img)
        keypoints, descrs = detector.detectAndCompute(timg, tmask)
        for kp in keypoints:
            x, y = kp.pt
            kp.pt = tuple( np.dot(Ai, (x, y, 1)) )
        if descrs is None:
            descrs = []
        return keypoints, descrs

    keypoints, descrs = [], []
    if pool is None:
        ires = map(f, params)
    else:
        ires = pool.map(f, params)

    for i, (k, d) in enumerate(ires):
        #logger.debug('affine sampling: %d / %d\r' % (i+1, len(params)))
        keypoints.extend(k)
        descrs.extend(d)

    return keypoints, np.array(descrs)

# https://isotope11.com/blog/storing-surf-sift-orb-keypoints-using-opencv-in-python
def pickle_sift(keypoints, descriptors):
    i = 0
    temp_array = []
    for point in keypoints:
        if i >= len(descriptors):
            break
        temp = (point.pt, point.size, point.angle, point.response, point.octave,
        point.class_id, descriptors[i])
        i += 1
        temp_array.append(temp)
    return temp_array

def unpickle_sift(array):
    keypoints = []
    descriptors = []
    for point in array:
        temp_feature = cv2.KeyPoint(x=point[0][0],y=point[0][1],_size=point[1], _angle=point[2], _response=point[3], _octave=point[4], _class_id=point[5])
        temp_descriptor = point[6]
        keypoints.append(temp_feature)
        descriptors.append(temp_descriptor)
    return keypoints, np.array(descriptors)


text:
layout: page
title: Blog
description: "News and updates related to Start Bootstrap and articles showcasing content and ideas related to the Bootstrap framework"

meta-title: "Blog"
meta-description: "Start Bootstrap's official blog and article library. A great place to find Bootstrap tips and the latest updates to Start Bootstrap!"

redirect_from:
  - /articles/
  - /articles/index.html
  - /articles/page2/
  - /articles/page3/
  - /articles/page4/
---

      {% for post in paginator.posts %}

              {% if post.preview-image %}

              {% else %}

              {% endif %}

                {{ post.title }}

{{ post.date | date: "%b %-d, %Y" }}

{{ post.excerpt | strip_html | truncatewords: 30 }}

              Read Post →

      {% endfor %}

      {% if paginator.total_pages > 1 %}

            {% if paginator.previous_page %}

            {% else %}

            {% endif %}

            {% for page in (1..paginator.total_pages) %}
            {% if page == paginator.page %}

              {{ page }}

            {% elsif page == 1 %}

                {{ page }}

            {% else %}

                {{ page }}

            {% endif %}
            {% endfor %}

            {% if paginator.page_trail %}
            {% for trail in paginator.page_trail %}

              {{ trail.num }}

            {% endfor %}
            {% endif %}

            {% if paginator.next_page %}

            {% else %}

            {% endif %}

      {% endif %}

redpajama_set_name: RedPajamaGithub


text:
<?php

namespace Zimbra\Mail\Request;

use Zimbra\Mail\Struct\DocumentSpec;

/**
 * SaveDocument request class
 * Save Document
 * One mechanism for Creating and updating a Document is:
 *   - Use FileUploadServlet to upload the document
 *   - Call SaveDocumentRequest using the upload-id returned from FileUploadServlet.
 * A Document represents a file.
 * A file can be created by uploading to FileUploadServlet.
 * Or it can refer to an attachment of an existing message.
 *
 * Documents are versioned.
 * The server maintains the metadata of each version, such as by who and when the version was edited, and the fragment.
 *
 * @package    Zimbra
 * @subpackage Mail
 * @category   Request
 * @author     Nguyen Van Nguyen - nguyennv1981@gmail.com
 * @copyright  Copyright © 2013 by Nguyen Van Nguyen.
 */
class SaveDocument extends Base
{
    /**
     * Constructor method for SaveDocument
     * @param  DocumentSpec $doc
     * @return self
     */
    public function __construct(DocumentSpec $doc)
    {
        parent::__construct();
        $this->setChild('doc', $doc);
    }

    /**
     * Gets document specification
     *
     * @return DocumentSpec
     */
    public function getDoc()
    {
        return $this->getChild('doc');
    }

    /**
     * Sets document specification
     *
     * @param  DocumentSpec $doc
     * @return self
     */
    public function setDoc(DocumentSpec $doc)
    {
        return $this->setChild('doc', $doc);
    }
}


text:
package com.zwitserloot.ivyplusplus.ssh;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.taskdefs.Redirector;
import org.apache.tools.ant.types.Path;

public class SshSubsystem {
	public static void unpack(File loc) throws IOException {
		loc.mkdirs();
		File f = new File(loc, "HASH");
		String existingHash = null;
		if (f.exists()) existingHash = fetchHash(f);

		JarUnpacker.unpack(loc, existingHash);
	}

	private static String fetchHash(File f) throws IOException {
		try (InputStream in = new FileInputStream(f)) {
			return new BufferedReader(new InputStreamReader(in, "UTF-8")).readLine();
		}
	}

	private static final class DummyInputStream extends InputStream {
		@Override public int read() throws IOException {
			return -1;
		}

		@Override public int read(byte[] b) throws IOException {
			return -1;
		}

		@Override public int read(byte[] b, int off, int len) throws IOException {
			return -1;
		}
	}

	private static final class CmdHandlerStream extends OutputStream {
		private final StringBuilder line = new StringBuilder();
		private final Project p;
		private final Task t;

		CmdHandlerStream(Project p, Task t) {
			this.p = p;
			this.t = t;
		}

		@Override public void write(int b) throws IOException {
			if (b == '\n') {
				if (line.length() > 0 && line.charAt(line.length() - 1) == '\r') line.setLength(line.length() - 1);
				String txt = line.toString();
				line.setLength(0);
				if (txt.startsWith("T:")) {
					p.log(t, txt.substring(2), Project.MSG_ERR);
				} else if (txt.startsWith("V:")) {
					p.log(t, txt.substring(2), Project.MSG_VERBOSE);
				} else if (txt.startsWith("C:")) {
					p.log(t, txt.substring(2), Project.MSG_INFO);
				} else if (txt.trim().length() > 0) {
					p.log(t, txt, Project.MSG_INFO);
				}
			} else {
				line.append((char) b);
			}
		}
	}

	public static void call(File loc, final Project p, final Task t, String classSpec, Object... args) {
		final Java task = new Java() {
			@Override protected void setupRedirector() {
				this.redirector = new Redirector(this) {
					private CmdHandlerStream out, err;
					private InputStream in;

					@Override public void createStreams() {
						out = new CmdHandlerStream(p, t);
						err = new CmdHandlerStream(p, t);
						in = new DummyInputStream();
					}
					@Override public OutputStream getOutputStream() {
						return out;
					}
					@Override public OutputStream getErrorStream() {
						return err;
					}
					@Override public InputStream getInputStream() {
						return in;
					}
					@Override public void complete() throws IOException {
						out.write('\n');
						err.write('\n');
					}
				};
				super.setupRedirector();
			}
		};
		task.setProject(p);
		task.setFork(true);
		task.setTaskName("ssh");
		task.createJvmarg().setValue("-Dorg.slf4j.simpleLogger.defaultLogLevel=warn");
		Path cp = task.createClasspath();
		cp.add(new Path(p, new File(loc, "classes").getAbsolutePath()));
		for (File jar : new File(loc, "lib").listFiles()) {
			if (jar.isFile() && jar.getName().endsWith(".jar")) cp.add(new Path(p, new File(new File(loc, "lib"), jar.getName()).getAbsolutePath()));
		}
		for (Object a : args) {
			if (a instanceof File) task.createArg().setValue(((File) a).getAbsolutePath());
			else task.createArg().setValue(a.toString());
		}
		task.setClassname(classSpec);
		task.execute();
	}
}


text:
namespace VM
{
    namespace ClassDefinition
    {
        JavaClassFile ClassFileParser::parseClass(std::string filePath)
        {
            // ---- Checking Magicbyte ----
            char *data = new char[sizeof(u4)];
            this->inputStream->read(data, sizeof(u4));
            if (*((int *) data) != ClassDefinition::CAFEBABE_MAGIC)
            {
                delete[] data;
                throw -1;
            }
            // ---- Reading minor and major version ----
            this->classFile.minor_version = this->readU2();
            this->classFile.major_version = this->readU2();

            // ---- Reading ConstantPool size ----
            this->classFile.constant_pool_count = this->readU2();
            // ---- Reading all data from the Constant Pool ----

            return this->classFile;
        }

        ClassFileParser::~ClassFileParser()
        {
            if(this->inputStream != nullptr)
            {
                delete(this->inputStream);
            }
        }

        const char* ClassFileParser::UnknownConstantException::what() const throw()
        {
            return "UnkownConstantPoolTag: " + this->value;
        }

        u2 ClassFileParser::readU2()
        {
            char* data = new char[sizeof(u2)];
            this->inputStream->read(data, sizeof(u2));
            Utils::swapEndianess(reinterpret_cast<void*>(*data), sizeof(u2));
            u2 converted = static_cast<u2>(*data);
            delete[] data;
            return converted;
        }

        JavaClassFile ClassFileParser::getClassFile()
        {
            return ClassDefinition::JavaClassFile();
        }

        void ClassFileParser::init(std::string filePath)
        {
            this->classFile = JavaClassFile();
            this->inputStream = new std::ifstream();
            this->inputStream->open(filePath, std::ios::in | std::ios::binary);
        }

        std::size_t ClassFileParser::sizeofConstantInfo(u1 type)
        {
            std::size_t size = 0;

            switch(type)
            {
                case ConstantPool::ConstantPoolTag::CLASS:
                    size = sizeof(ConstantPool::ConstantClassInfo);
                    break;
                case ConstantPool::ConstantPoolTag::METHOD_REF:
                case ConstantPool::ConstantPoolTag::FIELD_REF:
                case ConstantPool::INTERFACE_METHOD_REF:
                    size = sizeof(ConstantPool::ConstantXRefInfo);
                    break;
                case ConstantPool::STRING:
                    size = sizeof(ConstantPool::ConstantStringInfo);
                    break;
                case ConstantPool::INTEGER:
                case ConstantPool::FLOAT:
                    size = sizeof(ConstantPool::ConstantNumericFourByteInfo);
                    break;
                case ConstantPool::LONG:
                case ConstantPool::DOUBLE:
                    size = sizeof(ConstantPool::ConstantNumericEightByteInfo);
                    break;
                case ConstantPool::NAME_AND_TYPE:
                    size = sizeof(ConstantPool::ConstantNameAndTypeInfo);
                    break;
                case ConstantPool::UTF_8:
                    size = this->readU2() + sizeof(u2);
                    break;
                case ConstantPool::METHOD_HANDLE:
                    size = sizeof(ConstantPool::ConstantMethodHandleInfo);
                    break;
                case ConstantPool::METHOD_TYPE:
                    size = sizeof(ConstantPool::ConstantMethodTypeInfo);
                    break;
                case ConstantPool::INVOKE_DYNAMIC:
                    size = sizeof(ConstantPool::ConstantInvokeDynamicInfo);
                    break;
                default:
                    throw UnknownConstantException(type);
            }

            return size;
        }

    }
}


text:
title: How to invert keys and values of an object in JavaScript
tags:
    - JavaScript
    - ES6
    - one-line
    - js
    - Object
layout: note
---

In this Article we will go through how to invert keys and values of an object only using single line of code in JavaScript.
This is a one-line JavaScript code snippet that uses one of the most popular ES6 features => `Arrow Function`.

Let's define this short function:

```js {.wrap}
const invert = obj => Object.keys(obj).reduce((res, k) => Object.assign(res, {[obj[k]]: k}), {});
```

### Or

```js {.wrap}
const invert = obj => Object.fromEntries(Object.entries(obj).map(([k, v]) => [v, k]));
```

### Example

```js {.wrap}
invert({ a: '1', b: '2', c: '3' });     // { 1: 'a', 2: 'b', 3: 'c' }
```


text:
<?php

namespace XiangminWang\OAuth2\Client\Provider;

use League\OAuth2\Client\Entity\User;
use League\OAuth2\Client\Token\AccessToken;

class Weibo extends \League\OAuth2\Client\Provider\AbstractProvider
{
    public $responseType = 'json';
    public $domain = 'https://api.weibo.com/oauth2';
    public $apiDomain = 'https://api.weibo.com/2';
    public $site = 'http://weibo.com/';

    public function urlAuthorize()
    {
        return $this->domain.'/authorize';
    }

    public function urlAccessToken()
    {
        return $this->domain.'/access_token';
    }

    public function urlUserDetails(\League\OAuth2\Client\Token\AccessToken $token)
    {
        return $this->apiDomain.'/users/show.json?access_token='.$token->accessToken.'&uid='.$token->uid;
    }

    public function userDetails($response, \League\OAuth2\Client\Token\AccessToken $token)
    {
        $user = new User;

        $user->uid = $response->id;
        $user->nickname = isset($response->name) ? $response->name : $response->domain;
        $user->name = isset($response->screen_name) ? $response->screen_name : null;
        $user->location = isset($response->location) ? $response->location : null;
        $user->imageUrl = isset($response->avatar_large) ? $response->avatar_large : null;
        $user->description = isset($response->description) ? $response->description : null;
        $user->urls = [
            'profile' => $this->site . (isset($response->profile_url) ? $response->profile_url : $response->id),
            'site' => isset($response->url) && $response->url ? $response->url : null,
        ];

        return $user;
    }

    public function userUid($response, \League\OAuth2\Client\Token\AccessToken $token)
    {
        return $response->id;
    }
}


text:
module.exports = {
  testPathIgnorePatterns: ['<rootDir>/e2e/'],
  setupFiles: ['<rootDir>/_jestsetup.js'],
  moduleNameMapper: {
    '\\.css$': '<rootDir>/__mocks__/styleMock.js',
  },
  testURL: 'http://localhost/',
  coverageDirectory: './coverage/',
  collectCoverage: true,
};


text:
require 'test_helper'

class ReclamoDecoratorTest < Draper::TestCase
end


text:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated 25/09/2018 14:47:07 by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
    <class name="com.lades.sihv.model.SisRespCardio" table="sisRespCardio" catalog="bd_sihv" optimistic-lock="version">
        <composite-id name="id" class="com.lades.sihv.model.SisRespCardioId">
            <key-property name="pkSisRespCardio" type="int">
                <column name="PK_sisRespCardio" />
            </key-property>
            <key-property name="vetConsultationPkVetConsultation" type="int">
                <column name="vetConsultation_PK_vetConsultation" />
            </key-property>
        </composite-id>
        <many-to-one name="vetConsultation" class="com.lades.sihv.model.VetConsultation" update="false" insert="false" fetch="select">
            <column name="vetConsultation_PK_vetConsultation" not-null="true" />
        </many-to-one>
        <property name="tosse" type="string">
            <column name="tosse" length="7" not-null="true" />
        </property>
        <property name="tosseProdutiva" type="string">
            <column name="tosseProdutiva" length="30" />
        </property>
        <property name="tosseEvolu" type="string">
            <column name="tosseEvolu" length="254" />
        </property>
        <property name="espirro" type="string">
            <column name="espirro" length="7" not-null="true" />
        </property>
        <property name="espirroEvolu" type="string">
            <column name="espirroEvolu" length="254" />
        </property>
        <property name="secrecaoNasal" type="string">
            <column name="secrecaoNasal" length="7" not-null="true" />
        </property>
        <property name="secreNasalUniBilateral" type="string">
            <column name="secreNasalUniBilateral" length="57" />
        </property>
        <property name="secreNasalTipo" type="string">
            <column name="secreNasalTipo" length="100" />
        </property>
        <property name="secreNasalEvolu" type="string">
            <column name="secreNasalEvolu" length="254" />
        </property>
        <property name="dispneiaTaquipneia" type="string">
            <column name="dispneiaTaquipneia" length="7" not-null="true" />
        </property>
        <property name="dispnTaquipEvolu" type="string">
            <column name="dispnTaquipEvolu" length="254" />
        </property>
        <property name="cianose" type="string">
            <column name="cianose" length="7" not-null="true" />
        </property>
        <property name="cianoseEvolu" type="string">
            <column name="cianoseEvolu" length="254" />
        </property>
        <property name="cansacoFacil" type="string">
            <column name="cansacoFacil" length="7" not-null="true" />
        </property>
        <property name="cansaFacilEvolu" type="string">
            <column name="cansaFacilEvolu" length="254" />
        </property>
        <property name="sincope" type="string">
            <column name="sincope" length="7" not-null="true" />
        </property>
        <property name="sincopeEvolu" type="string">
            <column name="sincopeEvolu" length="254" />
        </property>
        <property name="emagrecimento" type="string">
            <column name="emagrecimento" length="7" not-null="true" />
        </property>
        <property name="emagrecEvolu" type="string">
            <column name="emagrecEvolu" length="254" />
        </property>
        <property name="sistemaAfetado" type="string">
            <column name="sistemaAfetado" length="7" not-null="true" />
        </property>
    </class>
</hibernate-mapping>


text:
/**
 * Renders a IconLink(<svg> wrapped in a <a> tag, enforcing the usage of the
 * href and title attributes with a default target of _blank. Also uses the className to set
 * the icon hover and active color.
 */
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { COLORS } from '../../containers/App/theme';
import { CTAAnalytics } from '../../utils/analytics';

export const StyledA = styled.a`
  .icon {
    fill: ${COLORS.blueGrey.hex};
    cursor: pointer;
    margin: 0 1em;

    transition: fill 0.25s ease-in-out, width 0.25s ease-in-out, height 0.25s ease-in-out;

    @media only screen and (max-width: 450px) {
      width: 2em;
      height: 2em;
    }
  }

  .linkedin:visited,
  .linkedin:hover,
  .linkedin:active {
    fill: #0077b5;
  }

  .github:visited,
  .github:hover,
  .github:active {
    fill: #6cc644;
  }

  .twitter:visited,
  .twitter:hover,
  .twitter:active {
    fill: #1da1f2;
  }
`;

const IconLink = ({ svg, href, title }) => (
  <StyledA
    href={href}
    title={title}
    target="_blank"
    rel="noreferrer noopener"
    onClick={() => CTAAnalytics({ category: 'Icon Link', title })}
  >
    {svg}
  </StyledA>
);

IconLink.propTypes = {
  svg: PropTypes.object.isRequired,
  href: PropTypes.string.isRequired,
  title: PropTypes.string.isRequired,
};

export default IconLink;


text:
import sys
from typing import Any, Callable, Dict, Iterable, Optional, TypeVar
import urllib.parse

from azure.core.exceptions import (
    ClientAuthenticationError,
    HttpResponseError,
    ResourceExistsError,
    ResourceNotFoundError,
    ResourceNotModifiedError,
    map_error,
)
from azure.core.paging import ItemPaged
from azure.core.pipeline import PipelineResponse
from azure.core.pipeline.transport import HttpResponse
from azure.core.rest import HttpRequest
from azure.core.tracing.decorator import distributed_trace
from azure.core.utils import case_insensitive_dict
from azure.mgmt.core.exceptions import ARMErrorFormat

from .. import models as _models
from .._serialization import Serializer
from .._vendor import _convert_request, _format_url_section

if sys.version_info >= (3, 8):
    from typing import Literal  # pylint: disable=no-name-in-module, ungrouped-imports
else:
    from typing_extensions import Literal  # type: ignore  # pylint: disable=ungrouped-imports
T = TypeVar("T")
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]

_SERIALIZER = Serializer()
_SERIALIZER.client_side_validation = False

def build_create_request(
    resource_group_name: str,
    search_service_name: str,
    name: str,
    subscription_id: str,
    *,
    client_request_id: Optional[str] = None,
    **kwargs: Any
) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version = kwargs.pop("api_version", _params.pop("api-version", "2020-03-13"))  # type: Literal["2020-03-13"]
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop(
        "template_url",
        "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Search/searchServices/{searchServiceName}/createQueryKey/{name}",
    )  # pylint: disable=line-too-long
    path_format_arguments = {
        "resourceGroupName": _SERIALIZER.url("resource_group_name", resource_group_name, "str"),
        "searchServiceName": _SERIALIZER.url("search_service_name", search_service_name, "str"),
        "name": _SERIALIZER.url("name", name, "str"),
        "subscriptionId": _SERIALIZER.url("subscription_id", subscription_id, "str"),
    }

    _url = _format_url_section(_url, **path_format_arguments)

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    if client_request_id is not None:
        _headers["x-ms-client-request-id"] = _SERIALIZER.header("client_request_id", client_request_id, "str")
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs)

def build_list_by_search_service_request(
    resource_group_name: str,
    search_service_name: str,
    subscription_id: str,
    *,
    client_request_id: Optional[str] = None,
    **kwargs: Any
) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version = kwargs.pop("api_version", _params.pop("api-version", "2020-03-13"))  # type: Literal["2020-03-13"]
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop(
        "template_url",
        "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Search/searchServices/{searchServiceName}/listQueryKeys",
    )  # pylint: disable=line-too-long
    path_format_arguments = {
        "resourceGroupName": _SERIALIZER.url("resource_group_name", resource_group_name, "str"),
        "searchServiceName": _SERIALIZER.url("search_service_name", search_service_name, "str"),
        "subscriptionId": _SERIALIZER.url("subscription_id", subscription_id, "str"),
    }

    _url = _format_url_section(_url, **path_format_arguments)

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    if client_request_id is not None:
        _headers["x-ms-client-request-id"] = _SERIALIZER.header("client_request_id", client_request_id, "str")
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs)

def build_delete_request(
    resource_group_name: str,
    search_service_name: str,
    key: str,
    subscription_id: str,
    *,
    client_request_id: Optional[str] = None,
    **kwargs: Any
) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version = kwargs.pop("api_version", _params.pop("api-version", "2020-03-13"))  # type: Literal["2020-03-13"]
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop(
        "template_url",
        "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Search/searchServices/{searchServiceName}/deleteQueryKey/{key}",
    )  # pylint: disable=line-too-long
    path_format_arguments = {
        "resourceGroupName": _SERIALIZER.url("resource_group_name", resource_group_name, "str"),
        "searchServiceName": _SERIALIZER.url("search_service_name", search_service_name, "str"),
        "key": _SERIALIZER.url("key", key, "str"),
        "subscriptionId": _SERIALIZER.url("subscription_id", subscription_id, "str"),
    }

    _url = _format_url_section(_url, **path_format_arguments)

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    if client_request_id is not None:
        _headers["x-ms-client-request-id"] = _SERIALIZER.header("client_request_id", client_request_id, "str")
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="DELETE", url=_url, params=_params, headers=_headers, **kwargs)

class QueryKeysOperations:
    """
    .. warning::
        **DO NOT** instantiate this class directly.

        Instead, you should access the following operations through
        :class:`~azure.mgmt.search.SearchManagementClient`'s
        :attr:`query_keys` attribute.
    """

    models = _models

    def __init__(self, *args, **kwargs):
        input_args = list(args)
        self._client = input_args.pop(0) if input_args else kwargs.pop("client")
        self._config = input_args.pop(0) if input_args else kwargs.pop("config")
        self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
        self._deserialize = input_args.pop(0) if input_args else kwargs.pop("deserializer")

    @distributed_trace
    def create(
        self,
        resource_group_name: str,
        search_service_name: str,
        name: str,
        search_management_request_options: Optional[_models.SearchManagementRequestOptions] = None,
        **kwargs: Any
    ) -> _models.QueryKey:
        """Generates a new query key for the specified Search service. You can create up to 50 query keys
        per service.

        :param resource_group_name: The name of the resource group within the current subscription. You
         can obtain this value from the Azure Resource Manager API or the portal. Required.
        :type resource_group_name: str
        :param search_service_name: The name of the Azure Cognitive Search service associated with the
         specified resource group. Required.
        :type search_service_name: str
        :param name: The name of the new query API key. Required.
        :type name: str
        :param search_management_request_options: Parameter group. Default value is None.
        :type search_management_request_options:
         ~azure.mgmt.search.models.SearchManagementRequestOptions
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: QueryKey or the result of cls(response)
        :rtype: ~azure.mgmt.search.models.QueryKey
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version = kwargs.pop(
            "api_version", _params.pop("api-version", self._config.api_version)
        )  # type: Literal["2020-03-13"]
        cls = kwargs.pop("cls", None)  # type: ClsType[_models.QueryKey]

        _client_request_id = None
        if search_management_request_options is not None:
            _client_request_id = search_management_request_options.client_request_id

        request = build_create_request(
            resource_group_name=resource_group_name,
            search_service_name=search_service_name,
            name=name,
            subscription_id=self._config.subscription_id,
            client_request_id=_client_request_id,
            api_version=api_version,
            template_url=self.create.metadata["url"],
            headers=_headers,
            params=_params,
        )
        request = _convert_request(request)
        request.url = self._client.format_url(request.url)  # type: ignore

        pipeline_response = self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
            request, stream=False, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            raise HttpResponseError(response=response, error_format=ARMErrorFormat)

        deserialized = self._deserialize("QueryKey", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    create.metadata = {"url": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Search/searchServices/{searchServiceName}/createQueryKey/{name}"}  # type: ignore

    @distributed_trace
    def list_by_search_service(
        self,
        resource_group_name: str,
        search_service_name: str,
        search_management_request_options: Optional[_models.SearchManagementRequestOptions] = None,
        **kwargs: Any
    ) -> Iterable["_models.QueryKey"]:
        """Returns the list of query API keys for the given Azure Cognitive Search service.

        :param resource_group_name: The name of the resource group within the current subscription. You
         can obtain this value from the Azure Resource Manager API or the portal. Required.
        :type resource_group_name: str
        :param search_service_name: The name of the Azure Cognitive Search service associated with the
         specified resource group. Required.
        :type search_service_name: str
        :param search_management_request_options: Parameter group. Default value is None.
        :type search_management_request_options:
         ~azure.mgmt.search.models.SearchManagementRequestOptions
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: An iterator like instance of either QueryKey or the result of cls(response)
        :rtype: ~azure.core.paging.ItemPaged[~azure.mgmt.search.models.QueryKey]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version = kwargs.pop(
            "api_version", _params.pop("api-version", self._config.api_version)
        )  # type: Literal["2020-03-13"]
        cls = kwargs.pop("cls", None)  # type: ClsType[_models.ListQueryKeysResult]

        error_map = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        def prepare_request(next_link=None):
            if not next_link:
                _client_request_id = None
                if search_management_request_options is not None:
                    _client_request_id = search_management_request_options.client_request_id

                request = build_list_by_search_service_request(
                    resource_group_name=resource_group_name,
                    search_service_name=search_service_name,
                    subscription_id=self._config.subscription_id,
                    client_request_id=_client_request_id,
                    api_version=api_version,
                    template_url=self.list_by_search_service.metadata["url"],
                    headers=_headers,
                    params=_params,
                )
                request = _convert_request(request)
                request.url = self._client.format_url(request.url)  # type: ignore

            else:
                # make call to next link with the client's api-version
                _parsed_next_link = urllib.parse.urlparse(next_link)
                _next_request_params = case_insensitive_dict(
                    {
                        key: [urllib.parse.quote(v) for v in value]
                        for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()
                    }
                )
                _next_request_params["api-version"] = self._config.api_version
                request = HttpRequest(
                    "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params
                )
                request = _convert_request(request)
                request.url = self._client.format_url(request.url)  # type: ignore
                request.method = "GET"
            return request

        def extract_data(pipeline_response):
            deserialized = self._deserialize("ListQueryKeysResult", pipeline_response)
            list_of_elem = deserialized.value
            if cls:
                list_of_elem = cls(list_of_elem)
            return deserialized.next_link or None, iter(list_of_elem)

        def get_next(next_link=None):
            request = prepare_request(next_link)

            pipeline_response = self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
                request, stream=False, **kwargs
            )
            response = pipeline_response.http_response

            if response.status_code not in [200]:
                map_error(status_code=response.status_code, response=response, error_map=error_map)
                raise HttpResponseError(response=response, error_format=ARMErrorFormat)

            return pipeline_response

        return ItemPaged(get_next, extract_data)

    list_by_search_service.metadata = {"url": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Search/searchServices/{searchServiceName}/listQueryKeys"}  # type: ignore

    @distributed_trace
    def delete(  # pylint: disable=inconsistent-return-statements
        self,
        resource_group_name: str,
        search_service_name: str,
        key: str,
        search_management_request_options: Optional[_models.SearchManagementRequestOptions] = None,
        **kwargs: Any
    ) -> None:
        """Deletes the specified query key. Unlike admin keys, query keys are not regenerated. The process
        for regenerating a query key is to delete and then recreate it.

        :param resource_group_name: The name of the resource group within the current subscription. You
         can obtain this value from the Azure Resource Manager API or the portal. Required.
        :type resource_group_name: str
        :param search_service_name: The name of the Azure Cognitive Search service associated with the
         specified resource group. Required.
        :type search_service_name: str
        :param key: The query key to be deleted. Query keys are identified by value, not by name.
         Required.
        :type key: str
        :param search_management_request_options: Parameter group. Default value is None.
        :type search_management_request_options:
         ~azure.mgmt.search.models.SearchManagementRequestOptions
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version = kwargs.pop(
            "api_version", _params.pop("api-version", self._config.api_version)
        )  # type: Literal["2020-03-13"]
        cls = kwargs.pop("cls", None)  # type: ClsType[None]

        _client_request_id = None
        if search_management_request_options is not None:
            _client_request_id = search_management_request_options.client_request_id

        request = build_delete_request(
            resource_group_name=resource_group_name,
            search_service_name=search_service_name,
            key=key,
            subscription_id=self._config.subscription_id,
            client_request_id=_client_request_id,
            api_version=api_version,
            template_url=self.delete.metadata["url"],
            headers=_headers,
            params=_params,
        )
        request = _convert_request(request)
        request.url = self._client.format_url(request.url)  # type: ignore

        pipeline_response = self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
            request, stream=False, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200, 204, 404]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            raise HttpResponseError(response=response, error_format=ARMErrorFormat)

        if cls:
            return cls(pipeline_response, None, {})

    delete.metadata = {"url": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Search/searchServices/{searchServiceName}/deleteQueryKey/{key}"}  # type: ignore


text:
package web

import (
	"context"
	"errors"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"sort"
	"strconv"
	"strings"

	"gate.computer/gate/internal/principal"
	server "gate.computer/gate/server/api"
	"gate.computer/gate/server/event"
	"gate.computer/gate/server/internal/monitor"
	"gate.computer/gate/server/web/api"
	internalapi "gate.computer/gate/server/web/internal/api"
	"gate.computer/gate/server/web/internal/protojson"
	"github.com/gorilla/websocket"
)

const maxWebsocketRequestSize = 4096

type respondedType struct{}

var responded respondedType

type errorWriter interface {
	SetHeader(key, value string)
	WriteError(status int, text string)
}

type (
	instanceMethod       func(ctx context.Context, s server.Server, instance string) error
	instanceStatusMethod func(ctx context.Context, s server.Server, instance string) (*server.Status, error)
	instanceWaiterMethod func(ctx context.Context, s server.Server, instance string) (server.Instance, error)
)

func deleteInstance(ctx context.Context, s server.Server, instance string) error {
	return s.DeleteInstance(ctx, instance)
}

func killInstance(ctx context.Context, s server.Server, instance string) (server.Instance, error) {
	return s.KillInstance(ctx, instance)
}

func suspendInstance(ctx context.Context, s server.Server, instance string) (server.Instance, error) {
	return s.SuspendInstance(ctx, instance)
}

func waitInstance(ctx context.Context, s server.Server, instance string) (*server.Status, error) {
	return s.WaitInstance(ctx, instance)
}

type privateConfig struct {
	Config
}

type webserver struct {
	privateConfig
	identity           string // JWT audience.
	pathKnownModules   string
	anyOrigin          bool
	localAuthorization bool
}

func NewHandler(pattern string, config *Config) http.Handler {
	return newHandler(pattern, config, "https", false)
}

// NewHandlerWithUnsecuredLocalAuthorization processes requests with unsigned
// JWT tokens under the local principal's identity.  Such tokens can be created
// by anyone without any secret knowledge.
func NewHandlerWithUnsecuredLocalAuthorization(pattern string, config *Config) http.Handler {
	for _, origin := range config.Origins {
		if strings.Contains(origin, "*") {
			panic("origin check disabled for unsecured local handler")
		}
	}

	if config.NonceStorage != nil {
		panic("nonce storage not supported for local principal")
	}

	return newHandler(pattern, config, "http", true)
}

func newHandler(pattern string, config *Config, scheme string, localAuthorization bool) http.Handler {
	s := &webserver{
		localAuthorization: localAuthorization,
	}

	if config != nil {
		s.Config = *config
	}
	if s.Authority == "" {
		s.Authority = strings.SplitN(pattern, "/", 2)[0]
	}
	if s.NewRequestID == nil {
		s.NewRequestID = defaultNewRequestID
	}
	if s.Monitor == nil {
		s.Monitor = monitor.Default
	}
	if !s.Configured() {
		panic("incomplete webserver configuration")
	}

	features := s.Server.Features()

	configOrigins := s.Origins
	s.Origins = nil
	for _, origin := range configOrigins {
		switch origin = strings.TrimSpace(origin); origin {
		case "":
		case "*":
			s.anyOrigin = true
		default:
			s.Origins = append(s.Origins, origin)
		}
	}

	p := strings.TrimRight(pattern, "/")                                    // host/path
	patternAPI := p + api.Path                                              // host/path/api/
	patternModule := p + api.PathModule                                     // host/path/api/module
	patternModules := p + api.PathModuleSources                             // host/path/api/module/
	patternKnownModule := p + api.PathModuleSources + api.KnownModuleSource // host/path/api/module/hash
	patternKnownModules := p + api.PathKnownModules                         // host/path/api/module/hash/
	patternInstances := p + api.PathInstances                               // host/path/api/instance/
	patternInstance := patternInstances[:len(patternInstances)-1]           // host/path/api/instance

	p = strings.TrimLeftFunc(p, func(r rune) bool { return r != '/' })   // /path
	pathAPI := p + api.Path                                              // /path/api/
	pathModule := p + api.PathModule                                     // /path/api/module
	pathModules := p + api.PathModuleSources                             // /path/api/module/
	pathKnownModule := p + api.PathModuleSources + api.KnownModuleSource // /path/api/module/hash
	s.pathKnownModules = p + api.PathKnownModules                        // /path/api/module/hash/
	pathInstances := p + api.PathInstances                               // /path/api/instance/
	pathInstance := pathInstances[:len(pathInstances)-1]                 // /path/api/instance

	s.identity = scheme + "://" + s.Authority + p + api.Path // https://authority/path/api/

	mux := http.NewServeMux()
	mux.HandleFunc(patternAPI, newFeatureHandler(s, pathAPI, features))
	mux.HandleFunc(patternModule, newRedirectHandler(s, pathModule))
	mux.HandleFunc(patternInstance, newRedirectHandler(s, pathInstance))
	mux.HandleFunc(patternInstances, newInstanceHandler(s, pathInstances))
	mux.HandleFunc(patternKnownModule, newRedirectHandler(s, pathKnownModule))
	mux.HandleFunc(patternKnownModules, newKnownModuleHandler(s))

	moduleSources := []string{api.KnownModuleSource}

	for _, relURI := range features.ModuleSources {
		patternSource := patternModule + relURI // host/path/api/module/source
		patternSourceDir := patternSource + "/" // host/path/api/module/source/

		pathSource := pathModule + relURI // /path/api/module/source
		pathSourceDir := pathSource + "/" // /path/api/module/source/

		mux.HandleFunc(patternSource, newRedirectHandler(s, pathSource))
		mux.HandleFunc(patternSourceDir, newModuleSourceHandler(s, pathModule, pathSourceDir))

		moduleSources = append(moduleSources, strings.TrimLeft(relURI, "/"))
	}

	sort.Strings(moduleSources)
	mux.HandleFunc(patternModules, newStaticHandler(s, pathModules, moduleSources))

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()
		ctx = server.ContextWithRequest(ctx, s.NewRequestID(r))
		ctx = server.ContextWithAddress(ctx, r.RemoteAddr)
		r = r.WithContext(ctx)

		s.Monitor(&event.Event{
			Type: event.TypeIfaceAccess,
			Meta: server.ContextMeta(ctx),
		}, nil)

		defer func() {
			if x := recover(); x != nil && x != responded {
				panic(x)
			}
		}()

		if !s.anyOrigin {
			if origin := r.Header.Get(api.HeaderOrigin); origin != "" {
				mustBeAllowedOrigin(w, r, s, origin)
			}
		}

		mux.ServeHTTP(w, r)
	})
}

type staticContent struct {
	content       []byte
	contentLength string
}

func prepareStaticContent(data interface{}) staticContent {
	content := mustMarshalJSON(data)
	return staticContent{
		content:       content,
		contentLength: strconv.Itoa(len(content)),
	}
}

// Path handlers.  Route methods and set up CORS.

func newRedirectHandler(s *webserver, path string) http.HandlerFunc {
	location := path + "/"

	return func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != path {
			respondPathNotFound(w, r, s)
			return
		}

		methods := "OPTIONS"
		setAccessControl(w, r, s, "GET, HEAD, "+methods)

		switch r.Method {
		case "GET", "HEAD":
			w.Header().Set("Location", location)
			w.WriteHeader(http.StatusMovedPermanently)

		case "OPTIONS":
			setOptions(w, methods)

		default:
			respondMethodNotAllowed(w, r, s, methods)
		}
	}
}

func newStaticHandler(s *webserver, path string, data interface{}) http.HandlerFunc {
	static := prepareStaticContent(data)

	return func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != path {
			respondPathNotFound(w, r, s)
			return
		}

		methods := "OPTIONS"
		setAccessControl(w, r, s, "GET, HEAD, "+methods)

		switch r.Method {
		case "GET", "HEAD":
			handleGetStatic(w, r, s, &static)

		case "OPTIONS":
			setOptions(w, methods)

		default:
			respondMethodNotAllowed(w, r, s, methods)
		}
	}
}

func newFeatureHandler(s *webserver, path string, featureAll *server.Features) http.HandlerFunc {
	featureScope := &api.Features{
		Scope: featureAll.Scope,
	}

	answers := [3]staticContent{
		prepareStaticContent(struct{}{}),
		prepareStaticContent(featureScope), // scope
		prepareStaticContent(featureScope), // all
	}

	return func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != path {
			respondPathNotFound(w, r, s)
			return
		}

		methods := "OPTIONS"
		setAccessControl(w, r, s, "GET, HEAD, "+methods)

		switch r.Method {
		case "GET", "HEAD":
			handleGetFeatures(w, r, s, &answers)

		case "OPTIONS":
			setOptions(w, methods)

		default:
			respondMethodNotAllowed(w, r, s, methods)
		}
	}
}

func newKnownModuleHandler(s *webserver) http.HandlerFunc {
	var (
		headersList = join(api.HeaderAuthorization)
		headersID   = join(api.HeaderAuthorization, api.HeaderContentType)
		exposed     = join(api.HeaderLocation, api.HeaderInstance, api.HeaderStatus)
	)

	return func(w http.ResponseWriter, r *http.Request) {
		if len(r.URL.Path) == len(s.pathKnownModules) {
			// Module directory listing

			methods := "OPTIONS, POST"
			setAccessControlAllowHeaders(w, r, s, "GET, HEAD, "+methods, headersList)

			switch r.Method {
			case "GET", "HEAD":
				w.WriteHeader(http.StatusNoContent)

			case "OPTIONS":
				setOptions(w, methods)

			case "POST":
				handlePostKnownModules(w, r, s)

			default:
				respondMethodNotAllowed(w, r, s, methods)
			}
		} else {
			// Module operations
			module := r.URL.Path[len(s.pathKnownModules):]

			methods := "OPTIONS, POST, PUT"
			setAccessControlAllowExposeHeaders(w, r, s, "GET, HEAD, "+methods, headersID, exposed)

			switch r.Method {
			case "GET", "HEAD":
				handleGetKnownModule(w, r, s, module)

			case "PUT":
				handlePutKnownModule(w, r, s, module)

			case "POST":
				handlePostKnownModule(w, r, s, module)

			case "OPTIONS":
				setOptions(w, methods)

			default:
				respondMethodNotAllowed(w, r, s, methods)
			}
		}
	}
}

func newModuleSourceHandler(s *webserver, sourceURIBase, sourcePath string) http.HandlerFunc {
	var (
		headers = join(api.HeaderAuthorization)
		exposed = join(api.HeaderLocation, api.HeaderInstance, api.HeaderStatus)
	)

	return func(w http.ResponseWriter, r *http.Request) {
		if len(r.URL.Path) == len(sourcePath) {
			// Module directory listing is not supported for sources.  The
			// directory clearly exists (it has modules in it), but doesn't
			// support any methods itself.

			methods := "OPTIONS"
			setAccessControl(w, r, s, "GET, HEAD, "+methods)

			switch r.Method {
			case "GET", "HEAD":
				w.WriteHeader(http.StatusNoContent)

			case "OPTIONS":
				setOptions(w, methods)

			default:
				respondMethodNotAllowed(w, r, s, methods)
			}
		} else {
			// Module operations
			module := r.URL.Path[len(sourceURIBase):]

			methods := "OPTIONS, POST"
			setAccessControlAllowExposeHeaders(w, r, s, "GET, HEAD, "+methods, headers, exposed)

			switch r.Method {
			case "GET", "HEAD":
				handleGetModuleSource(w, r, s, module)

			case "POST":
				handlePostModuleSource(w, r, s, module)

			case "OPTIONS":
				setOptions(w, methods)

			default:
				respondMethodNotAllowed(w, r, s, methods)
			}
		}
	}
}

func newInstanceHandler(s *webserver, instancesPath string) http.HandlerFunc {
	var (
		headersGet  = join(api.HeaderAuthorization)
		headersPost = join(api.HeaderAuthorization, api.HeaderContentType)
		exposed     = join(api.HeaderStatus)
	)

	return func(w http.ResponseWriter, r *http.Request) {
		if len(r.URL.Path) == len(instancesPath) {
			// Instance directory listing

			methods := "OPTIONS"
			setAccessControlAllowHeaders(w, r, s, "GET, HEAD, "+methods, headersGet)

			switch r.Method {
			case "GET", "HEAD":
				w.WriteHeader(http.StatusNoContent)

			case "POST":
				handlePostInstances(w, r, s)

			case "OPTIONS":
				setOptions(w, methods)

			default:
				respondMethodNotAllowed(w, r, s, methods)
			}
		} else {
			// Instance operations
			instance := r.URL.Path[len(instancesPath):]

			methods := "OPTIONS, POST"
			setAccessControlAllowExposeHeaders(w, r, s, "GET, HEAD, "+methods, headersPost, exposed)

			switch r.Method {
			case "GET", "HEAD":
				handleGetInstance(w, r, s, instance)

			case "POST":
				handlePostInstance(w, r, s, instance)

			case "OPTIONS":
				setOptions(w, methods)

			default:
				respondMethodNotAllowed(w, r, s, methods)
			}
		}
	}
}

// Method handlers.  Parse query parameters and check content headers.

func handleGetStatic(w http.ResponseWriter, r *http.Request, s *webserver, static *staticContent) {
	mustNotHaveQuery(w, r, s)
	mustAcceptJSON(w, r, s)
	handleStatic(w, r, s, static)
}

func handleGetFeatures(w http.ResponseWriter, r *http.Request, s *webserver, answers *[3]staticContent) {
	query := mustParseOptionalQuery(w, r, s)
	features := popOptionalParams(query, api.ParamFeature)
	mustNotHaveParams(w, r, s, query)

	if len(features) > 0 {
		mustAcceptJSON(w, r, s)
	}

	level := 0

	for _, v := range features {
		switch v {
		case api.FeatureScope:
			if level == 0 {
				level = 1
			}

		case api.FeatureAll:
			level = len(*answers) - 1

		default:
			respondUnsupportedFeature(w, r, s)
			return
		}
	}

	handleStatic(w, r, s, &(*answers)[level])
}

func handleGetKnownModule(w http.ResponseWriter, r *http.Request, s *webserver, key string) {
	query := mustParseOptionalQuery(w, r, s)
	pin := popOptionalActionParam(w, r, s, query, api.ActionPin)

	var modTags []string
	if pin {
		modTags = popOptionalParams(query, api.ParamModuleTag)
	}

	if _, found := query[api.ParamAction]; found {
		switch popLastParam(w, r, s, query, api.ParamAction) {
		case api.ActionCall:
			function := mustPopOptionalLastFunctionParam(w, r, s, query)
			instTags := popOptionalParams(query, api.ParamInstanceTag)
			invoke := popOptionalLastLogParam(w, r, s, query)
			mustNotHaveParams(w, r, s, query)
			handleCallWebsocket(w, r, s, pin, "", key, function, modTags, instTags, invoke)

		default:
			respondUnsupportedAction(w, r, s)
		}
	} else {
		if pin {
			respondUnsupportedAction(w, r, s)
		} else {
			mustNotHaveParams(w, r, s, query)
			mustAcceptWebAssembly(w, r, s)
			handleModuleDownload(w, r, s, key)
		}
	}
}

func handlePostKnownModules(w http.ResponseWriter, r *http.Request, s *webserver) {
	mustNotHaveQuery(w, r, s)
	mustNotHaveContentType(w, r, s)
	mustNotHaveContent(w, r, s)
	mustAcceptJSON(w, r, s)
	handleModuleList(w, r, s)
}

func handlePutKnownModule(w http.ResponseWriter, r *http.Request, s *webserver, key string) {
	mustHaveContentType(w, r, s, api.ContentTypeWebAssembly)
	mustHaveContentLength(w, r, s)
	query := mustParseOptionalQuery(w, r, s)
	pin := popOptionalActionParam(w, r, s, query, api.ActionPin)
	suspend := popOptionalActionParam(w, r, s, query, api.ActionSuspend)

	var modTags []string
	if pin {
		modTags = popOptionalParams(query, api.ParamModuleTag)
	}

	if _, found := query[api.ParamAction]; found {
		switch popLastParam(w, r, s, query, api.ParamAction) {
		case api.ActionCall:
			function := mustPopOptionalLastFunctionParam(w, r, s, query)
			instTags := popOptionalParams(query, api.ParamInstanceTag)
			invoke := popOptionalLastLogParam(w, r, s, query)
			mustNotHaveParams(w, r, s, query)
			handleCall(w, r, s, server.OpCallUpload, pin, true, "", key, function, modTags, instTags, invoke)

		case api.ActionLaunch:
			function := mustPopOptionalLastFunctionParam(w, r, s, query)
			instance := popOptionalLastParam(w, r, s, query, api.ParamInstance)
			instTags := popOptionalParams(query, api.ParamInstanceTag)
			invoke := popOptionalLastLogParam(w, r, s, query)
			mustNotHaveParams(w, r, s, query)
			handleLaunchUpload(w, r, s, pin, key, function, instance, modTags, instTags, suspend, invoke)

		default:
			respondUnsupportedAction(w, r, s)
		}
	} else {
		if pin {
			mustNotHaveParams(w, r, s, query)
			handleModuleUpload(w, r, s, key, modTags)
		} else {
			respondUnsupportedAction(w, r, s)
		}
	}
}

func handlePostKnownModule(w http.ResponseWriter, r *http.Request, s *webserver, key string) {
	query := mustParseQuery(w, r, s)

	if len(query[api.ParamAction]) == 0 {
		mustNotHaveParams(w, r, s, query)
		mustAcceptJSON(w, r, s)
		handleKnownModule(w, r, s, key)
		return
	}

	suspend := popOptionalActionParam(w, r, s, query, api.ActionSuspend)

	switch popLastParam(w, r, s, query, api.ParamAction) {
	case api.ActionCall:
		function := mustPopOptionalLastFunctionParam(w, r, s, query)
		instTags := popOptionalParams(query, api.ParamInstanceTag)
		invoke := popOptionalLastLogParam(w, r, s, query)
		mustNotHaveParams(w, r, s, query)
		handleCall(w, r, s, server.OpCallExtant, false, false, "", key, function, nil, instTags, invoke)

	case api.ActionLaunch:
		function := mustPopOptionalLastFunctionParam(w, r, s, query)
		instance := popOptionalLastParam(w, r, s, query, api.ParamInstance)
		instTags := popOptionalParams(query, api.ParamInstanceTag)
		invoke := popOptionalLastLogParam(w, r, s, query)
		mustNotHaveParams(w, r, s, query)
		mustNotHaveContentType(w, r, s)
		mustNotHaveContent(w, r, s)
		handleLaunch(w, r, s, server.OpLaunchExtant, false, "", key, function, instance, nil, instTags, suspend, invoke)

	case api.ActionPin:
		modTags := popOptionalParams(query, api.ParamModuleTag)
		mustNotHaveParams(w, r, s, query)
		mustNotHaveContentType(w, r, s)
		mustNotHaveContent(w, r, s)
		handleModulePin(w, r, s, key, modTags)

	case api.ActionUnpin:
		mustNotHaveParams(w, r, s, query)
		mustNotHaveContentType(w, r, s)
		mustNotHaveContent(w, r, s)
		handleModuleUnpin(w, r, s, key)

	default:
		respondUnsupportedAction(w, r, s)
	}
}

func handleGetModuleSource(w http.ResponseWriter, r *http.Request, s *webserver, source string) {
	query := mustParseQuery(w, r, s)
	pin := popOptionalActionParam(w, r, s, query, api.ActionPin)

	var modTags []string
	if pin {
		modTags = popOptionalParams(query, api.ParamModuleTag)
	}

	switch popLastParam(w, r, s, query, api.ParamAction) {
	case api.ActionCall:
		function := mustPopOptionalLastFunctionParam(w, r, s, query)
		instTags := popOptionalParams(query, api.ParamInstanceTag)
		invoke := popOptionalLastLogParam(w, r, s, query)
		mustNotHaveParams(w, r, s, query)
		handleCallWebsocket(w, r, s, pin, source, "", function, modTags, instTags, invoke)

	default:
		respondUnsupportedAction(w, r, s)
	}
}

func handlePostModuleSource(w http.ResponseWriter, r *http.Request, s *webserver, source string) {
	query := mustParseQuery(w, r, s)
	pin := popOptionalActionParam(w, r, s, query, api.ActionPin)

	var modTags []string
	if pin {
		modTags = popOptionalParams(query, api.ParamModuleTag)
	}

	if _, found := query[api.ParamAction]; found {
		suspend := popOptionalActionParam(w, r, s, query, api.ActionSuspend)

		switch popLastParam(w, r, s, query, api.ParamAction) {
		case api.ActionCall:
			if suspend {
				respondUnsupportedAction(w, r, s)
			}
			function := mustPopOptionalLastFunctionParam(w, r, s, query)
			instTags := popOptionalParams(query, api.ParamInstanceTag)
			invoke := popOptionalLastLogParam(w, r, s, query)
			mustNotHaveParams(w, r, s, query)
			handleCall(w, r, s, server.OpCallSource, pin, false, source, "", function, modTags, instTags, invoke)

		case api.ActionLaunch:
			function := mustPopOptionalLastFunctionParam(w, r, s, query)
			instance := popOptionalLastParam(w, r, s, query, api.ParamInstance)
			instTags := popOptionalParams(query, api.ParamInstanceTag)
			invoke := popOptionalLastLogParam(w, r, s, query)
			mustNotHaveParams(w, r, s, query)
			mustNotHaveContentType(w, r, s)
			mustNotHaveContent(w, r, s)
			handleLaunch(w, r, s, server.OpLaunchSource, pin, source, "", function, instance, modTags, instTags, suspend, invoke)

		default:
			respondUnsupportedAction(w, r, s)
		}
	} else {
		if pin {
			mustNotHaveParams(w, r, s, query)
			mustNotHaveContentType(w, r, s)
			mustNotHaveContent(w, r, s)
			handleModuleSource(w, r, s, source, modTags)
		} else {
			respondUnsupportedAction(w, r, s)
		}
	}
}

func handleGetInstance(w http.ResponseWriter, r *http.Request, s *webserver, instance string) {
	query := mustParseQuery(w, r, s)

	switch popLastParam(w, r, s, query, api.ParamAction) {
	case api.ActionIO:
		mustNotHaveParams(w, r, s, query)
		handleInstanceConnectWebsocket(w, r, s, instance)

	default:
		respondUnsupportedAction(w, r, s)
	}
}

func handlePostInstances(w http.ResponseWriter, r *http.Request, s *webserver) {
	mustNotHaveQuery(w, r, s)
	mustNotHaveContentType(w, r, s)
	mustNotHaveContent(w, r, s)
	mustAcceptJSON(w, r, s)
	handleInstanceList(w, r, s)
}

func handlePostInstance(w http.ResponseWriter, r *http.Request, s *webserver, instance string) {
	query := mustParseQuery(w, r, s)
	actions := popOptionalParams(query, api.ParamAction)

	switch len(actions) {
	case 0:
		mustNotHaveParams(w, r, s, query)
		mustAcceptJSON(w, r, s)
		handleInstanceInfo(w, r, s, instance)
		return

	case 1:
		switch actions[0] {
		case api.ActionIO:
			mustNotHaveParams(w, r, s, query)
			handleInstanceConnect(w, r, s, instance)
			return

		case api.ActionResume:
			function := mustPopOptionalLastFunctionParam(w, r, s, query)
			invoke := popOptionalLastLogParam(w, r, s, query)
			mustNotHaveParams(w, r, s, query)
			handleInstanceResume(w, r, s, function, instance, invoke)
			return

		case api.ActionSnapshot:
			modTags := popOptionalParams(query, api.ParamModuleTag)
			mustNotHaveParams(w, r, s, query)
			handleInstanceSnapshot(w, r, s, instance, modTags)
			return

		case api.ActionDelete:
			mustNotHaveParams(w, r, s, query)
			handleInstance(w, r, s, server.OpInstanceDelete, deleteInstance, instance)
			return

		case api.ActionUpdate:
			mustNotHaveParams(w, r, s, query)
			handleInstanceUpdate(w, r, s, instance)
			return

		case api.ActionDebug:
			mustNotHaveParams(w, r, s, query)
			handleInstanceDebug(w, r, s, instance)
			return
		}
	}

	var (
		kill    bool
		suspend bool
		wait    bool
	)
	for _, a := range actions {
		switch a {
		case api.ActionKill:
			kill = true

		case api.ActionSuspend:
			suspend = true

		case api.ActionWait:
			wait = true

		default:
			respondUnsupportedAction(w, r, s)
			return
		}
	}

	switch {
	case kill && !suspend:
		mustNotHaveParams(w, r, s, query)
		handleInstanceWaiter(w, r, s, server.OpInstanceKill, killInstance, instance, wait)

	case suspend && !kill:
		mustNotHaveParams(w, r, s, query)
		handleInstanceWaiter(w, r, s, server.OpInstanceSuspend, suspendInstance, instance, wait)

	case wait && !kill && !suspend:
		mustNotHaveParams(w, r, s, query)
		handleInstanceStatus(w, r, s, server.OpInstanceWait, waitInstance, instance)

	default:
		respondUnsupportedAction(w, r, s)
	}
}

// Action handlers.  Check authorization if needed, and serve the response.

func handleStatic(w http.ResponseWriter, r *http.Request, s *webserver, static *staticContent) {
	w.Header().Set("Cache-Control", cacheControlStatic)
	w.Header().Set(api.HeaderContentLength, static.contentLength)
	w.Header().Set(api.HeaderContentType, contentTypeJSON)
	w.WriteHeader(http.StatusOK)
	w.Write(static.content)
}

func handleModuleList(w http.ResponseWriter, r *http.Request, s *webserver) {
	ctx := server.ContextWithOp(r.Context(), server.OpModuleList)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	infos, err := s.Server.Modules(ctx)
	if err != nil {
		respondServerError(ctx, wr, s, "", "", "", "", err)
		return
	}

	sort.Sort(server.SortableModules(infos))
	content := protojson.MustMarshal(infos)
	w.Header().Set(api.HeaderContentLength, strconv.Itoa(len(content)))
	w.Header().Set(api.HeaderContentType, contentTypeJSON)
	w.WriteHeader(http.StatusOK)
	w.Write(content)
}

func handleKnownModule(w http.ResponseWriter, r *http.Request, s *webserver, key string) {
	ctx := server.ContextWithOp(r.Context(), server.OpModuleInfo)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	info, err := s.Server.ModuleInfo(ctx, key)
	if err != nil {
		respondServerError(ctx, wr, s, "", key, "", "", err)
		return
	}

	content := protojson.MustMarshal(info)
	w.Header().Set(api.HeaderContentLength, strconv.Itoa(len(content)))
	w.Header().Set(api.HeaderContentType, contentTypeJSON)
	w.WriteHeader(http.StatusOK)
	w.Write(content)
}

func handleModuleDownload(w http.ResponseWriter, r *http.Request, s *webserver, key string) {
	ctx := server.ContextWithOp(r.Context(), server.OpModuleDownload)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	content, length, err := s.Server.ModuleContent(ctx, key)
	if err != nil {
		respondServerError(ctx, wr, s, "", key, "", "", err)
		panic(responded)
	}
	defer content.Close()

	w.Header().Set(api.HeaderContentLength, strconv.FormatInt(length, 10))
	w.Header().Set(api.HeaderContentType, api.ContentTypeWebAssembly)
	w.WriteHeader(http.StatusOK)

	if r.Method != "HEAD" {
		io.Copy(w, content)
	}
}

func handleModuleUpload(w http.ResponseWriter, r *http.Request, s *webserver, key string, modTags []string) {
	ctx := server.ContextWithOp(r.Context(), server.OpModuleUpload)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)
	upload := moduleUpload(mustDecodeContent(ctx, wr, s), r.ContentLength, key)
	defer upload.Close()

	if _, err := s.Server.UploadModule(ctx, upload, modulePin(true, modTags)); err != nil {
		respondServerError(ctx, wr, s, "", key, "", "", err)
		panic(responded)
	}

	w.WriteHeader(http.StatusCreated)
}

func handleModuleSource(w http.ResponseWriter, r *http.Request, s *webserver, source string, modTags []string) {
	ctx := server.ContextWithOp(r.Context(), server.OpModuleSource)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	module, err := s.Server.SourceModule(ctx, source, modulePin(true, modTags))
	if err != nil {
		respondServerError(ctx, wr, s, source, "", "", "", err)
		return
	}

	w.Header().Set(api.HeaderLocation, s.pathKnownModules+module)
	w.WriteHeader(http.StatusCreated)
}

func handleModulePin(w http.ResponseWriter, r *http.Request, s *webserver, key string, modTags []string) {
	ctx := server.ContextWithOp(r.Context(), server.OpModulePin)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	if err := s.Server.PinModule(ctx, key, modulePin(true, modTags)); err != nil {
		respondServerError(ctx, wr, s, "", key, "", "", err)
		panic(responded)
	}

	w.WriteHeader(http.StatusNoContent)
}

func handleModuleUnpin(w http.ResponseWriter, r *http.Request, s *webserver, key string) {
	ctx := server.ContextWithOp(r.Context(), server.OpModuleUnpin)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	if err := s.Server.UnpinModule(ctx, key); err != nil {
		respondServerError(ctx, wr, s, "", key, "", "", err)
		panic(responded)
	}

	w.WriteHeader(http.StatusNoContent)
}

func handleCall(w http.ResponseWriter, r *http.Request, s *webserver, op server.Op, pin, content bool, source, key, function string, modTags, instTags []string, invoke *server.InvokeOptions) {
	ctx := server.ContextWithOp(r.Context(), op) // TODO: detail: post
	wr := &requestResponseWriter{w, r}

	launch := &server.LaunchOptions{
		Invoke:    invoke,
		Function:  function,
		Transient: true,
		Tags:      instTags,
	}

	var (
		module string
		inst   server.Instance
		err    error
	)
	switch {
	case content:
		ctx = mustParseAuthorizationHeader(ctx, wr, s, pin)
		upload := moduleUpload(mustDecodeContent(ctx, wr, s), r.ContentLength, key)
		defer upload.Close()

		module, inst, err = s.Server.UploadModuleInstance(ctx, upload, modulePin(pin, modTags), launch)
		if err != nil {
			respondServerError(ctx, wr, s, "", key, function, "", err)
			return
		}

	case source == "":
		ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

		module = key
		inst, err = s.Server.NewInstance(ctx, key, launch)
		if err != nil {
			respondServerError(ctx, wr, s, "", key, function, "", err)
			return
		}

	default:
		ctx = mustParseAuthorizationHeader(ctx, wr, s, pin)

		module, inst, err = s.Server.SourceModuleInstance(ctx, source, modulePin(pin, modTags), launch)
		if err != nil {
			// TODO: find out module hash
			respondServerError(ctx, wr, s, source, "", function, "", err)
			return
		}
	}
	defer inst.Kill(ctx) // TODO: error

	trail := acceptsTrailers(r)
	if trail {
		w.Header().Set("Trailer", api.HeaderStatus)
	}

	if principal.ContextID(ctx) != nil {
		if pin {
			w.Header().Set(api.HeaderLocation, s.pathKnownModules+module)
		}
		w.Header().Set(api.HeaderInstance, inst.ID())
	}

	if pin {
		w.WriteHeader(http.StatusCreated)
	} else {
		w.WriteHeader(http.StatusOK)
	}

	inst.Connect(ctx, r.Body, nopCloser{w})
	status := inst.Wait(ctx)

	if trail {
		w.Header().Set(api.HeaderStatus, string(protojson.MustMarshal(status)))
	}
}

func handleCallWebsocket(response http.ResponseWriter, request *http.Request, s *webserver, pin bool, source, key, function string, modTags, instTags []string, invoke *server.InvokeOptions) {
	ctx, cancel := context.WithCancel(request.Context())
	defer cancel()

	conn, err := websocketUpgrader.Upgrade(response, request, nil)
	if err != nil {
		reportProtocolError(ctx, s, err)
		return
	}
	defer conn.Close()

	origCloseHandler := conn.CloseHandler()
	conn.SetCloseHandler(func(code int, text string) error {
		cancel()
		return origCloseHandler(code, text)
	})

	conn.SetReadLimit(maxWebsocketRequestSize)

	var r api.Call

	err = conn.ReadJSON(&r)
	if err != nil {
		if e := net.Error(nil); errors.As(err, &e) {
			reportNetworkError(ctx, s, err)
		} else {
			reportProtocolError(ctx, s, err)
		}
		return
	}

	conn.SetReadLimit(0)

	var content bool

	switch r.ContentType {
	case api.ContentTypeWebAssembly:
		if source != "" {
			conn.WriteMessage(websocket.CloseMessage, websocketUnsupportedContent)
			reportProtocolError(ctx, s, errUnsupportedWebsocketContent)
			return
		}

		ctx = server.ContextWithOp(ctx, server.OpCallUpload) // TODO: detail: websocket
		content = true

	case "":
		if source == "" {
			ctx = server.ContextWithOp(ctx, server.OpCallExtant) // TODO: detail: websocket
		} else {
			ctx = server.ContextWithOp(ctx, server.OpCallSource) // TODO: detail: websocket
		}

	default:
		conn.WriteMessage(websocket.CloseMessage, websocketUnsupportedContentType)
		reportProtocolError(ctx, s, errUnsupportedWebsocketContentType)
		return
	}

	w := websocketResponseWriter{conn}

	launch := &server.LaunchOptions{
		Invoke:    invoke,
		Function:  function,
		Transient: true,
		Tags:      instTags,
	}

	var (
		module string
		inst   server.Instance
	)
	switch {
	case content:
		ctx = mustParseAuthorization(ctx, w, s, r.Authorization, pin)

		frameType, frame, err := conn.NextReader()
		if err != nil {
			reportNetworkError(ctx, s, err)
			return
		}
		if frameType != websocket.BinaryMessage {
			conn.WriteMessage(websocket.CloseMessage, websocketUnsupportedData)
			reportProtocolError(ctx, s, errWrongWebsocketMessageType)
			return
		}
		upload := moduleUpload(ioutil.NopCloser(frame), r.ContentLength, key)
		defer upload.Close()

		module, inst, err = s.Server.UploadModuleInstance(ctx, upload, modulePin(pin, modTags), launch)
		if err != nil {
			respondServerError(ctx, w, s, "", key, function, "", err)
			return
		}

	case source == "":
		ctx = mustParseAuthorization(ctx, w, s, r.Authorization, false)

		module = key
		inst, err = s.Server.NewInstance(ctx, key, launch)
		if err != nil {
			respondServerError(ctx, w, s, "", key, function, "", err)
			return
		}

	default:
		ctx = mustParseAuthorization(ctx, w, s, r.Authorization, pin)

		module, inst, err = s.Server.SourceModuleInstance(ctx, source, modulePin(pin, modTags), launch)
		if err != nil {
			// TODO: find out module hash
			respondServerError(ctx, w, s, source, "", function, "", err)
			return
		}
	}
	defer inst.Kill(ctx) // TODO: error

	var reply api.CallConnection

	if principal.ContextID(ctx) != nil {
		if pin {
			reply.Location = s.pathKnownModules + module
		}
		reply.Instance = inst.ID()
	}

	err = conn.WriteJSON(&reply)
	if err != nil {
		reportNetworkError(ctx, s, err)
		return
	}

	rw := newWebsocketReadWriteCanceler(conn, cancel)
	inst.Connect(ctx, rw, rw)
	status := inst.Wait(ctx)
	data := protojson.MustMarshal(&internalapi.ConnectionStatus{Status: status})
	if conn.WriteMessage(websocket.TextMessage, data) == nil {
		conn.WriteMessage(websocket.CloseMessage, websocketNormalClosure)
	}
}

func handleLaunch(w http.ResponseWriter, r *http.Request, s *webserver, op server.Op, pin bool, source, key, function, instance string, modTags, instTags []string, suspend bool, invoke *server.InvokeOptions) {
	ctx := server.ContextWithOp(r.Context(), op)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	launch := &server.LaunchOptions{
		Invoke:   invoke,
		Function: function,
		Instance: instance,
		Suspend:  suspend,
		Tags:     instTags,
	}

	var (
		module string
		inst   server.Instance
		err    error
	)
	if source == "" {
		module = key
		inst, err = s.Server.NewInstance(ctx, key, launch)
		if err != nil {
			respondServerError(ctx, wr, s, "", key, function, "", err)
			return
		}
	} else {
		module, inst, err = s.Server.SourceModuleInstance(ctx, source, modulePin(pin, modTags), launch)
		if err != nil {
			respondServerError(ctx, wr, s, source, "", function, "", err)
			return
		}
	}

	w.Header().Set(api.HeaderInstance, inst.ID())

	if pin {
		w.Header().Set(api.HeaderLocation, s.pathKnownModules+module)
		w.WriteHeader(http.StatusCreated)
	} else {
		w.WriteHeader(http.StatusNoContent)
	}
}

func handleLaunchUpload(w http.ResponseWriter, r *http.Request, s *webserver, pin bool, key, function, instance string, modTags, instTags []string, suspend bool, invoke *server.InvokeOptions) {
	ctx := server.ContextWithOp(r.Context(), server.OpLaunchUpload)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	launch := &server.LaunchOptions{
		Invoke:   invoke,
		Function: function,
		Instance: instance,
		Suspend:  suspend,
		Tags:     instTags,
	}

	upload := moduleUpload(mustDecodeContent(ctx, wr, s), r.ContentLength, key)
	defer upload.Close()

	key, inst, err := s.Server.UploadModuleInstance(ctx, upload, modulePin(pin, modTags), launch)
	if err != nil {
		respondServerError(ctx, wr, s, "", key, function, "", err)
		return
	}

	w.Header().Set(api.HeaderInstance, inst.ID())

	if pin {
		w.Header().Set(api.HeaderLocation, s.pathKnownModules+key)
		w.WriteHeader(http.StatusCreated)
	} else {
		w.WriteHeader(http.StatusNoContent)
	}
}

func handleInstanceList(w http.ResponseWriter, r *http.Request, s *webserver) {
	ctx := server.ContextWithOp(r.Context(), server.OpInstanceList)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	instances, err := s.Server.Instances(ctx)
	if err != nil {
		respondServerError(ctx, wr, s, "", "", "", "", err)
		return
	}

	sort.Sort(server.SortableInstances(instances))
	content := protojson.MustMarshal(instances)
	w.Header().Set(api.HeaderContentLength, strconv.Itoa(len(content)))
	w.Header().Set(api.HeaderContentType, contentTypeJSON)
	w.WriteHeader(http.StatusOK)
	w.Write(content)
}

func handleInstance(w http.ResponseWriter, r *http.Request, s *webserver, op server.Op, method instanceMethod, instance string) {
	ctx := server.ContextWithOp(r.Context(), op)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	if err := method(ctx, s.Server, instance); err != nil {
		respondServerError(ctx, wr, s, "", "", "", instance, err)
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

func handleInstanceInfo(w http.ResponseWriter, r *http.Request, s *webserver, instance string) {
	ctx := server.ContextWithOp(r.Context(), server.OpInstanceInfo)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	info, err := s.Server.InstanceInfo(ctx, instance)
	if err != nil {
		respondServerError(ctx, wr, s, "", "", "", instance, err)
		return
	}

	content := protojson.MustMarshal(info)
	w.Header().Set(api.HeaderContentLength, strconv.Itoa(len(content)))
	w.Header().Set(api.HeaderContentType, contentTypeJSON)
	w.WriteHeader(http.StatusOK)
	w.Write(content)
}

func handleInstanceStatus(w http.ResponseWriter, r *http.Request, s *webserver, op server.Op, method instanceStatusMethod, instance string) {
	ctx := server.ContextWithOp(r.Context(), op)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	status, err := method(ctx, s.Server, instance)
	if err != nil {
		respondServerError(ctx, wr, s, "", "", "", instance, err)
		return
	}

	w.Header().Set(api.HeaderStatus, string(protojson.MustMarshal(status)))
	w.WriteHeader(http.StatusNoContent)
}

func handleInstanceWaiter(w http.ResponseWriter, r *http.Request, s *webserver, op server.Op, method instanceWaiterMethod, instance string, wait bool) {
	ctx := server.ContextWithOp(r.Context(), op)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	inst, err := method(ctx, s.Server, instance)
	if err != nil {
		respondServerError(ctx, wr, s, "", "", "", instance, err)
		return
	}

	if wait {
		status := inst.Wait(ctx)
		w.Header().Set(api.HeaderStatus, string(protojson.MustMarshal(status)))
	}

	w.WriteHeader(http.StatusNoContent)
}

func handleInstanceResume(w http.ResponseWriter, r *http.Request, s *webserver, function, instance string, invoke *server.InvokeOptions) {
	ctx := server.ContextWithOp(r.Context(), server.OpInstanceResume)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	resume := &server.ResumeOptions{
		Invoke:   invoke,
		Function: function,
	}

	if _, err := s.Server.ResumeInstance(ctx, instance, resume); err != nil {
		respondServerError(ctx, wr, s, "", "", function, instance, err)
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

func handleInstanceConnect(w http.ResponseWriter, r *http.Request, s *webserver, instance string) {
	ctx := server.ContextWithOp(r.Context(), server.OpInstanceConnect) // TODO: detail: post
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	content := mustDecodeContent(ctx, wr, s)
	defer content.Close()

	inst, connIO, err := s.Server.InstanceConnection(ctx, instance)
	if err != nil {
		respondServerError(ctx, wr, s, "", "", "", instance, err)
		return
	}
	if connIO == nil {
		w.WriteHeader(http.StatusConflict)
		return
	}

	trail := acceptsTrailers(r)
	if trail {
		w.Header().Set("Trailer", api.HeaderStatus)
	}

	w.WriteHeader(http.StatusOK)

	if err := connIO(ctx, content, nopCloser{w}); err != nil {
		// Network error has already been reported by connIO.
		return
	}

	status := inst.Status(ctx)

	if trail {
		w.Header().Set(api.HeaderStatus, string(protojson.MustMarshal(status)))
	}
}

func handleInstanceConnectWebsocket(response http.ResponseWriter, request *http.Request, s *webserver, instance string) {
	ctx := server.ContextWithOp(request.Context(), server.OpInstanceConnect) // TODO: detail: websocket

	conn, err := websocketUpgrader.Upgrade(response, request, nil)
	if err != nil {
		reportProtocolError(ctx, s, err)
		return
	}
	defer conn.Close()

	conn.SetReadLimit(maxWebsocketRequestSize)

	var r api.IO

	err = conn.ReadJSON(&r)
	if err != nil {
		if e := net.Error(nil); errors.As(err, &e) {
			reportNetworkError(ctx, s, err)
		} else {
			reportProtocolError(ctx, s, err)
		}
		return
	}

	conn.SetReadLimit(0)

	w := websocketResponseWriter{conn}
	ctx = mustParseAuthorization(ctx, w, s, r.Authorization, true)

	inst, connIO, err := s.Server.InstanceConnection(ctx, instance)
	if err != nil {
		respondServerError(ctx, w, s, "", "", "", instance, err)
		conn.WriteMessage(websocket.CloseMessage, websocketNormalClosure)
		return
	}

	reply := &internalapi.IOConnection{Connected: connIO != nil}
	err = conn.WriteMessage(websocket.TextMessage, protojson.MustMarshal(reply))
	if err != nil {
		reportNetworkError(ctx, s, err)
		return
	}

	if connIO == nil {
		conn.WriteMessage(websocket.CloseMessage, websocketNotConnected)
		return
	}

	rw := newWebsocketReadWriter(conn)
	err = connIO(ctx, rw, rw)
	if err != nil {
		// Network error has already been reported by connIO.
		return
	}

	status := inst.Status(ctx)
	data := protojson.MustMarshal(&internalapi.ConnectionStatus{Status: status})
	err = conn.WriteMessage(websocket.TextMessage, data)
	if err != nil {
		reportNetworkError(ctx, s, err)
		return
	}

	conn.WriteMessage(websocket.CloseMessage, websocketNormalClosure)
}

func handleInstanceSnapshot(w http.ResponseWriter, r *http.Request, s *webserver, instance string, modTags []string) {
	ctx := server.ContextWithOp(r.Context(), server.OpInstanceSnapshot)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	module, err := s.Server.Snapshot(ctx, instance, modulePin(true, modTags))
	if err != nil {
		respondServerError(ctx, wr, s, "", "", "", instance, err)
		return
	}

	w.Header().Set(api.HeaderLocation, s.pathKnownModules+module)
	w.WriteHeader(http.StatusCreated)
}

func handleInstanceUpdate(w http.ResponseWriter, r *http.Request, s *webserver, instance string) {
	mustHaveContentType(w, r, s, api.ContentTypeJSON)
	ctx := server.ContextWithOp(r.Context(), server.OpInstanceUpdate)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	req := new(server.InstanceUpdate)
	if err := protojson.Decode(r.Body, req); err != nil {
		respondContentParseError(ctx, wr, s, err)
		return
	}

	info, err := s.Server.UpdateInstance(ctx, instance, req)
	if err != nil {
		respondServerError(ctx, wr, s, "", "", "", instance, err)
		return
	}

	if !acceptsJSON(r) {
		w.WriteHeader(http.StatusNoContent)
		return
	}

	content := protojson.MustMarshal(info)
	w.Header().Set(api.HeaderContentLength, strconv.Itoa(len(content)))
	w.Header().Set(api.HeaderContentType, contentTypeJSON)
	w.WriteHeader(http.StatusOK)
	w.Write(content)
}

func handleInstanceDebug(w http.ResponseWriter, r *http.Request, s *webserver, instance string) {
	mustHaveContentType(w, r, s, api.ContentTypeJSON)
	ctx := server.ContextWithOp(r.Context(), server.OpInstanceDebug)
	wr := &requestResponseWriter{w, r}
	ctx = mustParseAuthorizationHeader(ctx, wr, s, true)

	req := new(server.DebugRequest)
	if err := protojson.Decode(r.Body, req); err != nil {
		respondContentParseError(ctx, wr, s, err)
		return
	}

	res, err := s.Server.DebugInstance(ctx, instance, req)
	if err != nil {
		respondServerError(ctx, wr, s, "", "", "", instance, err)
		return
	}

	content := protojson.MustMarshal(res)
	w.Header().Set(api.HeaderContentLength, strconv.Itoa(len(content)))
	w.Header().Set(api.HeaderContentType, contentTypeJSON)
	w.WriteHeader(http.StatusOK)
	w.Write(content)
}

func moduleUpload(s io.ReadCloser, length int64, hash string) *server.ModuleUpload {
	return &server.ModuleUpload{
		Stream: s,
		Length: length,
		Hash:   hash,
	}
}

func modulePin(pin bool, tags []string) *server.ModuleOptions {
	return &server.ModuleOptions{
		Pin:  pin,
		Tags: tags,
	}
}

type nopCloser struct {
	io.Writer
}

func (nopCloser) Close() error {
	return nil
}


text:
package net.fortuna.ical4j.model.property;

import net.fortuna.ical4j.model.Parameter;
import net.fortuna.ical4j.model.ParameterList;
import net.fortuna.ical4j.model.Property;
import net.fortuna.ical4j.model.PropertyFactoryImpl;
import net.fortuna.ical4j.model.TextList;
import net.fortuna.ical4j.model.ValidationException;
import net.fortuna.ical4j.util.ParameterValidator;

/**
 * $Id$
 *
 * Created: [Apr 6, 2004]
 *
 * Defines a RESOURCES iCalendar component property.
 * @author benf
 */
public class Resources extends Property {

    private static final long serialVersionUID = -848562477226746807L;

    private TextList resources;

    /**
     * Default constructor.
     */
    public Resources() {
        super(RESOURCES, PropertyFactoryImpl.getInstance());
        resources = new TextList();
    }

    /**
     * @param aList a list of parameters for this component
     * @param aValue a value string for this component
     */
    public Resources(final ParameterList aList, final String aValue) {
        super(RESOURCES, aList, PropertyFactoryImpl.getInstance());
        setValue(aValue);
    }

    /**
     * @param rList a list of resources
     */
    public Resources(final TextList rList) {
        super(RESOURCES, PropertyFactoryImpl.getInstance());
        resources = rList;
    }

    /**
     * @param aList a list of parameters for this component
     * @param rList a list of resources
     */
    public Resources(final ParameterList aList, final TextList rList) {
        super(RESOURCES, aList, PropertyFactoryImpl.getInstance());
        resources = rList;
    }

    /**
     * {@inheritDoc}
     */
    public final void validate() throws ValidationException {

        /*
         * ; the following are optional, ; but MUST NOT occur more than once (";" altrepparam) / (";" languageparam) /
         */
        ParameterValidator.getInstance().assertOneOrLess(Parameter.ALTREP,
                getParameters());
        ParameterValidator.getInstance().assertOneOrLess(Parameter.LANGUAGE,
                getParameters());

        /*
         * ; the following is optional, ; and MAY occur more than once (";" xparam)
         */
    }

    /**
     * @return Returns the resources.
     */
    public final TextList getResources() {
        return resources;
    }

    /**
     * {@inheritDoc}
     */
    public final void setValue(final String aValue) {
        resources = new TextList(aValue);
    }

    /**
     * {@inheritDoc}
     */
    public final String getValue() {
        return getResources().toString();
    }
}


text:
{!! Form::open(array('url' => 'contatos/'.$contact->id, 'class'=>"form-horizontal", 'method'=>'PATCH' )) !!}

		Nome

			<input type="text" name="name" class="form-control" id="inputName" placeholder="Nome" value="{!! $contact->name or old('name') !!}" required="required">

		E-mail

			<input type="email" name="email" class="form-control" id="inputEmail" placeholder="E-mail" value="{!! $contact->email or old('email') !!}" required="required">

		Telefones

			<input type="tel" name="phones" class="form-control" id="inputPhones" placeholder="Telefone" value="{!!  $contact->phones or old('phones') !!}">

			<input type="tel" name="phones2" class="form-control" id="inputPhones2" placeholder="Telefone adicional" value="{!!  $contact->phones2 or old('phones2') !!}">

			<input type="tel" name="phones3" class="form-control" id="inputPhones3" placeholder="Telefone adicional" value="{!! $contact->phones3 or old('phones3') !!}">

		Skype

			<input type="tel" name="skype" class="form-control" id="inputSkype" placeholder="Skype" value="{!! $contact->skype or old('skype') !!}">

		Empresa

			<input type="text" name="company" class="form-control" id="inputCompany" placeholder="Empresa" value="{!! $contact->company or old('company') !!}">

		Endereço

			<input type="text" name="address" class="form-control" id="inputAddress" placeholder="Endereço" value="{!! $contact->address or old('address') !!}">

		Obeservações

			<textarea name="notes" class="form-control tinymce" rows="4" id="inputNotes">{!!  $contact->notes or old('notes') !!}</textarea>

			<button type="submit" class="btn btn-success">Salvar</button>

{!! Form::close() !!}


text:
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Comm. Soc. crittog. Ital. 1(4): 197 (1863)

#### Original name
Daldinia Ces. & De Not.

### Remarks
null