<commit_before>package gdal

/*
#include <cpl_vsi.h>
//#include "go_gdal.h"
//#include "gdal_version.h"

#cgo linux  CFLAGS: -I/usr/include/gdal
#cgo linux  LDFLAGS: -lgdal
#cgo darwin pkg-config: gdal
#cgo windows LDFLAGS: -lgdal.dll
*/
import "C"
import (
	"unsafe"
)

type VSILFile *C.VSILFILE
type VSIStatBufL C.VSIStatBufL

func VSIStatL(filename string) (VSIStatBufL, bool) {
	pszFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(pszFilename))

	var stat VSIStatBufL
	err := C.VSIStatL(pszFilename, (*C.VSIStatBufL)(&stat))
	success := err == 0

	return stat, success
}

func VSIStatExL(filename string, flags int) (VSIStatBufL, bool) {
	pszFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(pszFilename))

	var stat VSIStatBufL
	err := C.VSIStatExL(pszFilename, (*C.VSIStatBufL)(&stat), C.int(flags))
	success := err == 0

	return stat, success
}

func VSIIsCaseSensitiveFS(filename string) bool {
	pszFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(pszFilename))

	bSensitive := C.VSIIsCaseSensitiveFS(pszFilename)
	return (bSensitive != 0)
}

func VSIMkdir(path string, mode int) bool {
	pszPath := C.CString(path)
	defer C.free(unsafe.Pointer(pszPath))

	err := C.VSIMkdir(pszPath, C.long(mode))
	return err == 0
}

func VSIRmdir(path string) bool {
	pszPath := C.CString(path)
	defer C.free(unsafe.Pointer(pszPath))

	err := C.VSIRmdir(pszPath)
	return err == 0
}

func VSIUnlink(path string) bool {
	pszPath := C.CString(path)
	defer C.free(unsafe.Pointer(pszPath))

	err := C.VSIUnlink(pszPath)
	return err == 0
}

func VSIRename(oldPath, newPath string) bool {
	pszOldPath := C.CString(oldPath)
	defer C.free(unsafe.Pointer(pszOldPath))

	pszNewPath := C.CString(newPath)
	defer C.free(unsafe.Pointer(pszNewPath))

	err := C.VSIRename(pszOldPath, pszNewPath)
	return err == 0
}

func VSIStrerror(errno int) string {
	pszErr := C.VSIStrerror(C.int(errno))
	return C.GoString(pszErr)
}

func VSIInstallMemFileHandler() {
	C.VSIInstallMemFileHandler()
}

func VSIInstallLargeFileHandler() {
	C.VSIInstallLargeFileHandler()
}

func VSIInstallSubFileHandler() {
	C.VSIInstallSubFileHandler()
}

func VSIInstallSparseFileHandler() {
	C.VSIInstallSparseFileHandler()
}

func VSICleanupFileManager() {
	C.VSICleanupFileManager()
}

func VSIFileFromMemBuffer(filename string, data []byte, takeOwnership bool) VSILFile {
	pszFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(pszFilename))

	var bTakeOwnership C.int
	if takeOwnership {
		bTakeOwnership = C.TRUE
	} else {
		bTakeOwnership = C.FALSE
	}
	f := C.VSIFileFromMemBuffer(pszFilename, (*C.GByte)(&data[0]), C.vsi_l_offset(len(data)), bTakeOwnership)
	return VSILFile(f)
}

func VSIGetMemFileBuffer(filename string, unlinkAndSeize bool) []byte {
	pszFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(pszFilename))

	var bUnlinkAndSeize C.int
	if unlinkAndSeize {
		bUnlinkAndSeize = C.TRUE
	} else {
		bUnlinkAndSeize = C.FALSE
	}

	var pnDataLength C.vsi_l_offset
	pabyData := C.VSIGetMemFileBuffer(pszFilename, &pnDataLength, bUnlinkAndSeize)
	if pabyData == nil {
		return nil
	}

	data := C.GoBytes(unsafe.Pointer(pabyData), C.int(pnDataLength))
	if unlinkAndSeize {
		C.VSIFree(unsafe.Pointer(pabyData))
	}

	return data
}
<commit_msg>VSIL documentation and file wrappers<commit_after>package gdal

/*
#include <cpl_vsi.h>
//#include "go_gdal.h"
//#include "gdal_version.h"

#cgo linux  CFLAGS: -I/usr/include/gdal
#cgo linux  LDFLAGS: -lgdal
#cgo darwin pkg-config: gdal
#cgo windows LDFLAGS: -lgdal.dll
*/
import "C"
import (
	"unsafe"
)

type VSILFile *C.VSILFILE
type VSIStatBufL C.VSIStatBufL

// Open file.
//
// This function opens a file with the desired access. Large files (larger than 2GB) should be supported. Binary access is always implied and the "b" does not need to be included in the pszAccess string.
//
// On windows it is possible to define the configuration option GDAL_FILE_IS_UTF8 to have pszFilename treated as being in the local encoding instead of UTF-8, retoring the pre-1.8.0 behavior of VSIFOpenL().
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX fopen() function.
//
// Parameters:
//	filename 	the file to open. UTF-8 encoded.
//	access 	access requested (ie. "r", "r+", "w".
//
// Returns:
//	NULL on failure, or the file handle.
func VSIFOpenL(filename, access string) VSILFile {
	pszFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(pszFilename))

	pszAccess := C.CString(access)
	defer C.free(unsafe.Pointer(pszAccess))

	fp := C.VSIFOpenL(pszFilename, pszAccess)
	return VSILFile(fp)
}

// Close file.
//
// This function closes the indicated file.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX fclose() function.
//
// Parameters:
//	fp 	file handle opened with VSIFOpenL().
//
// Returns:
//	True on success or false on failure.
func VSIFCloseL(fp VSILFile) int {
	result := C.VSIFCloseL((*C.VSILFILE)(fp))
	return int(result)
}

// Seek to requested offset.
//
// Seek to the desired offset (nOffset) in the indicated file.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX fseek() call.
//
// Parameters:
//	fp 	file handle opened with VSIFOpenL().
//	offset 	offset in bytes.
//	whence 	one of SEEK_SET, SEEK_CUR or SEEK_END.
//
// Returns:
//	True on success or false on failure.
func VSIFSeekL(fp VSILFile, offset, whence int) bool {
	err := C.VSIFSeekL((*C.VSILFILE)(fp), C.vsi_l_offset(offset), C.int(whence))
	return err == 0
}

// Tell current file offset.
//
// Returns the current file read/write offset in bytes from the beginning of the file.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX ftell() call.
//
// Parameters:
//	fp 	file handle opened with VSIFOpenL().
//
// Returns:
//	file offset in bytes.
func VSIFTellL(fp VSILFile) int {
	offset := C.VSIFTellL((*C.VSILFILE)(fp))
	return int(offset)
}

// Analog of the POSIX rewind() call.
func VSIRewindL(fp VSILFile) {
	C.VSIRewindL((*C.VSILFILE)(fp))
}

// Read bytes from file.
//
// Reads nCount objects of nSize bytes from the indicated file at the current offset into the indicated buffer.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX fread() call.
//
// Parameters:
//	buffer 	the buffer into which the data should be read (at least nCount * nSize bytes in size.
//	size 	size of objects to read in bytes.
//	count 	number of objects to read.
//	fp 	file handle opened with VSIFOpenL().
//
// Returns:
//	number of objects successfully read.
func VSIFReadL(buffer []byte, size, count int, fp VSILFile) int {
	nRead := C.VSIFReadL(unsafe.Pointer(&buffer[0]), C.size_t(size), C.size_t(count), (*C.VSILFILE)(fp))
	return int(nRead)
}

// Write bytes to file.
//
// Writes nCount objects of nSize bytes to the indicated file at the current offset into the indicated buffer.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX fwrite() call.
//
// Parameters:
//	buffer 	the buffer from which the data should be written (at least nCount * nSize bytes in size.
//	size 	size of objects to read in bytes.
//	count 	number of objects to read.
//	fp 	file handle opened with VSIFOpenL().
//
// Returns:
//	number of objects successfully written.
func VSIFWriteL(buffer []byte, size, count int, fp VSILFile) int {
	nWritten := C.VSIFWriteL(unsafe.Pointer(&buffer[0]), C.size_t(size), C.size_t(count), (*C.VSILFILE)(fp))
	return int(nWritten)
}

// Test for end of file.
//
// Returns true if an end-of-file condition occured during the previous read operation. The end-of-file flag is cleared by a successfull VSIFSeekL() call.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX feof() call.
//
// Parameters:
//	fp 	file handle opened with VSIFOpenL().
//
// Returns:
//	True if at EOF else false.
func VSIFEofL(fp VSILFile) bool {
	bEnd := C.VSIFEofL((*C.VSILFILE)(fp))
	return bEnd != C.FALSE
}

// Truncate/expand the file to the specified size.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX ftruncate() call.
//
// Parameters:
//	fp 	file handle opened with VSIFOpenL().
//	newSize 	new size in bytes.
//
// Returns:
//	True on success or false on error.
func VSIFTruncateL(fp VSILFile, newSize int) bool {
	err := C.VSIFTruncateL((*C.VSILFILE)(fp), C.vsi_l_offset(newSize))
	return err == 0
}

// Flush pending writes to disk.
//
// For files in write or update mode and on filesystem types where it is applicable, all pending output on the file is flushed to the physical disk.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX fflush() call.
//
// Parameters:
//	fp 	file handle opened with VSIFOpenL().
//
// Returns:
//	True on success or false on error.
func VSIFFlushL(fp VSILFile) bool {
	err := C.VSIFFlushL((*C.VSILFILE)(fp))
	return err == 0
}

// Analog of the POSIX putc() call.
//
// Parameters:
//	fp 	file handle opened with VSIFOpenL().
//
// Returns:
//	True on success or false on error.
func VSIFPutcL(c int, fp VSILFile) bool {
	nWritten := C.VSIFPutcL(C.int(c), (*C.VSILFILE)(fp))
	return nWritten > 0
}

// Get filesystem object info.
//
// Fetches status information about a filesystem object (file, directory, etc). The returned information is placed in the VSIStatBufL structure. For portability only the st_size (size in bytes), and st_mode (file type). This method is similar to VSIStat(), but will work on large files on systems where this requires special calls.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX stat() function.
//
// Parameters:
//	filename 	the path of the filesystem object to be queried. UTF-8 encoded.
//
// Returns:
//	statBuf 	the structure with information.
//	success 	True on success or false on an error.
func VSIStatL(filename string) (statBuf VSIStatBufL, success bool) {
	pszFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(pszFilename))

	err := C.VSIStatL(pszFilename, (*C.VSIStatBufL)(&statBuf))
	success = err == 0

	return statBuf, success
}

// Get filesystem object info.
//
// Fetches status information about a filesystem object (file, directory, etc). The returned information is placed in the VSIStatBufL structure. For portability only the st_size (size in bytes), and st_mode (file type). This method is similar to VSIStat(), but will work on large files on systems where this requires special calls.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX stat() function, with an extra parameter to specify which information is needed, which offers a potential for speed optimizations on specialized and potentially slow virtual filesystem objects (/vsigzip/, /vsicurl/)
//
// Parameters:
//	filename 	the path of the filesystem object to be queried. UTF-8 encoded.
//	flags 	0 to get all information, or VSI_STAT_EXISTS_FLAG, VSI_STAT_NATURE_FLAG or VSI_STAT_SIZE_FLAG, or a combination of those to get partial info.
//
// Returns:
//	statBuf 	the structure with information.
//	success 	True on success or false on an error.
func VSIStatExL(filename string, flags int) (statBuf VSIStatBufL, success bool) {
	pszFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(pszFilename))

	err := C.VSIStatExL(pszFilename, (*C.VSIStatBufL)(&statBuf), C.int(flags))
	success = err == 0

	return statBuf, success
}

// Returns if the filenames of the filesystem are case sensitive.
//
// This method retrieves to which filesystem belongs the passed filename and return TRUE if the filenames of that filesystem are case sensitive.
//
// Currently, this will return FALSE only for Windows real filenames. Other VSI virtual filesystems are case sensitive.
//
// This methods avoid ugly ifndef WIN32 / endif code, that is wrong when dealing with virtual filenames.
//
// Parameters:
//	filename 	the path of the filesystem object to be tested. UTF-8 encoded.
//
// Returns:
//	True if the filenames of the filesystem are case sensitive.
func VSIIsCaseSensitiveFS(filename string) bool {
	pszFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(pszFilename))

	bSensitive := C.VSIIsCaseSensitiveFS(pszFilename)
	return (bSensitive != 0)
}

// Create a directory.
//
// Create a new directory with the indicated mode. The mode is ignored on some platforms. A reasonable default mode value would be 0666. This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX mkdir() function.
//
// Parameters:
//	pszPathname 	the path to the directory to create. UTF-8 encoded.
//	mode 	the permissions mode.
func VSIMkdir(path string, mode int) bool {
	pszPath := C.CString(path)
	defer C.free(unsafe.Pointer(pszPath))

	err := C.VSIMkdir(pszPath, C.long(mode))
	return err == 0
}

// Delete a directory.
//
// Deletes a directory object from the file system. On some systems the directory must be empty before it can be deleted.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX rmdir() function.
//
// Parameters:
//	pszDirname 	the path of the directory to be deleted. UTF-8 encoded.
//
// Returns:
//	True on success or false on an error.
func VSIRmdir(path string) bool {
	pszPath := C.CString(path)
	defer C.free(unsafe.Pointer(pszPath))

	err := C.VSIRmdir(pszPath)
	return err == 0
}

// Delete a file.
//
// Deletes a file object from the file system.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX unlink() function.
//
// Parameters:
//	pszFilename 	the path of the file to be deleted. UTF-8 encoded.
//
// Returns:
//	0 on success or -1 on an error.
func VSIUnlink(path string) bool {
	pszPath := C.CString(path)
	defer C.free(unsafe.Pointer(pszPath))

	err := C.VSIUnlink(pszPath)
	return err == 0
}

// Rename a file.
//
// Renames a file object in the file system. It should be possible to rename a file onto a new filesystem, but it is safest if this function is only used to rename files that remain in the same directory.
//
// This method goes through the VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
//
// Analog of the POSIX rename() function.
//
// Parameters:
//	oldpath 	the name of the file to be renamed. UTF-8 encoded.
//	newpath 	the name the file should be given. UTF-8 encoded.
//
// Returns:
//	0 on success or -1 on an error.
func VSIRename(oldPath, newPath string) bool {
	pszOldPath := C.CString(oldPath)
	defer C.free(unsafe.Pointer(pszOldPath))

	pszNewPath := C.CString(newPath)
	defer C.free(unsafe.Pointer(pszNewPath))

	err := C.VSIRename(pszOldPath, pszNewPath)
	return err == 0
}

func VSIStrerror(errno int) string {
	pszErr := C.VSIStrerror(C.int(errno))
	return C.GoString(pszErr)
}

// Install "memory" file system handler.
//
// A special file handler is installed that allows block of memory to be treated as files. All portions of the file system underneath the base path "/vsimem/" will be handled by this driver.
//
// Normal VSI*L functions can be used freely to create and destroy memory arrays treating them as if they were real file system objects. Some additional methods exist to efficient create memory file system objects without duplicating original copies of the data or to "steal" the block of memory associated with a memory file.
//
// At this time the memory handler does not properly handle directory semantics for the memory portion of the filesystem. The VSIReadDir() function is not supported though this will be corrected in the future.
//
// Calling this function repeatedly should do no harm, though it is not necessary. It is already called the first time a virtualizable file access function (ie. VSIFOpenL(), VSIMkDir(), etc) is called.
func VSIInstallMemFileHandler() {
	C.VSIInstallMemFileHandler()
}

func VSIInstallLargeFileHandler() {
	C.VSIInstallLargeFileHandler()
}

// Install /vsisubfile/ virtual file handler.
//
// This virtual file system handler allows access to subregions of files, treating them as a file on their own to the virtual file system functions (VSIFOpenL(), etc).
//
// A special form of the filename is used to indicate a subportion of another file:
//
// /vsisubfile/<offset>[_<size>],<filename>
//
// The size parameter is optional. Without it the remainder of the file from the start offset as treated as part of the subfile. Otherwise only <size> bytes from <offset> are treated as part of the subfile. The <filename> portion may be a relative or absolute path using normal rules. The <offset> and <size> values are in bytes.
//
// e.g. /vsisubfile/1000_3000,/data/abc.ntf /vsisubfile/5000,../xyz/raw.dat
//
// Unlike the /vsimem/ or conventional file system handlers, there is no meaningful support for filesystem operations for creating new files, traversing directories, and deleting files within the /vsisubfile/ area. Only the VSIStatL(), VSIFOpenL() and operations based on the file handle returned by VSIFOpenL() operate properly.
func VSIInstallSubFileHandler() {
	C.VSIInstallSubFileHandler()
}

// Install /vsisparse/ virtual file handler.
//
// The sparse virtual file handler allows a virtual file to be composed from chunks of data in other files, potentially with large spaces in the virtual file set to a constant value. This can make it possible to test some sorts of operations on what seems to be a large file with image data set to a constant value. It is also helpful when wanting to add test files to the test suite that are too large, but for which most of the data can be ignored. It could, in theory, also be used to treat several files on different file systems as one large virtual file.
func VSIInstallSparseFileHandler() {
	C.VSIInstallSparseFileHandler()
}

func VSICleanupFileManager() {
	C.VSICleanupFileManager()
}

// Create memory "file" from a buffer.
//
// A virtual memory file is created from the passed buffer with the indicated filename. Under normal conditions the filename would need to be absolute and within the /vsimem/ portion of the filesystem.
//
// The buffer remains the responsibility of the caller, and should not go out of scope as long as it might be accessed as a file. In no circumstances does this function take a copy of the data contents.
func VSIFileFromMemBuffer(filename string, data []byte) VSILFile {
	pszFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(pszFilename))

	fp := C.VSIFileFromMemBuffer(pszFilename, (*C.GByte)(&data[0]), C.vsi_l_offset(len(data)), C.FALSE)
	return VSILFile(fp)
}

// Fetch buffer underlying memory file.
//
// This function returns a pointer to the memory buffer underlying a virtual "in memory" file. If bUnlinkAndSeize is TRUE the filesystem object will be deleted, and ownership of the buffer will pass to the caller otherwise the underlying file will remain in existance.
//
// Parameters:
//	pszFilename 	the name of the file to grab the buffer of.
//	pnDataLength 	(file) length returned in this variable.
//	bUnlinkAndSeize 	TRUE to remove the file, or FALSE to leave unaltered.
//
// Returns:
//	pointer to memory buffer or NULL on failure.
func VSIGetMemFileBuffer(filename string, unlinkAndSeize bool) []byte {
	pszFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(pszFilename))

	var bUnlinkAndSeize C.int
	if unlinkAndSeize {
		bUnlinkAndSeize = C.TRUE
	} else {
		bUnlinkAndSeize = C.FALSE
	}

	var pnDataLength C.vsi_l_offset
	pabyData := C.VSIGetMemFileBuffer(pszFilename, &pnDataLength, bUnlinkAndSeize)
	if pabyData == nil {
		return nil
	}

	data := C.GoBytes(unsafe.Pointer(pabyData), C.int(pnDataLength))
	if unlinkAndSeize {
		C.VSIFree(unsafe.Pointer(pabyData))
	}

	return data
}
<|endoftext|>


<commit_before>// Package vue provides gopherjs bindings for VueJS
package vue

import (
	"github.com/gopherjs/gopherjs/js"
)

var (
	vue  = js.Global.Get("Vue")
	vMap = make(map[interface{}]*Vue, 0)
)

type Vue struct {
	*js.Object
	///////////////////////////// Instance Properties
	// vm.$data
	// 	Type: Object
	// Details:
	// 		The data object that the Vue instance is observing.
	//  	You can swap it with a new object.
	// 		The Vue instance proxies access to the properties on its data object.
	Data *js.Object `js:"$data"`

	// vm.$el
	//  Type: HTMLElement
	//  Read only
	// Details:
	//  	The DOM element that the Vue instance is managing.
	// 		Note that for Fragment Instances, vm.$el will return an anchor node that
	// 		indicates the starting position of the fragment.
	El *js.Object `js:"$el"`

	// vm.$options
	//  Type: Object
	//  Read only
	// Details:
	//    The instantiation options used for the current Vue instance.
	//    This is useful when you want to include custom properties in the options:
	//
	// 	  new Vue({
	// 	    customOption: 'foo',
	// 	    created: function () {
	// 	      console.log(this.$options.customOption) // -> 'foo'
	// 	    }
	// 	  })
	Options *js.Object `js:"$options"`

	// vm.$parent
	//  Type: Vue instance
	//  Read only
	// Details:
	// 		The parent instance, if the current instance has one.
	Parent *js.Object `js:"$parent"`

	// vm.$root
	//  Type: Vue instance
	//  Read only
	// Details:
	// 		The root Vue instance of the current component tree.
	// 		If the current instance has no parents this value will be itself.
	Root *js.Object `js:"$root"`

	// vm.$children
	//  Type: Array<Vue instance>
	//  Read only
	// Details:
	// 	The direct child components of the current instance.
	Children *js.Object `js:"$children"`

	// vm.$refs
	// 	Type: Object
	// 	Read only
	// Details:
	// 	An object that holds child components that have v-ref registered.
	// See also:
	// 	Child Component Refs
	// 	v-ref.
	Refs *js.Object `js:"$refs"`

	// vm.$els
	// 	Type: Object
	// 	Read only
	// Details:
	// 	An object that holds DOM elements that have v-el registered.
	// See also: v-el.
	Els *js.Object `js:"$els"`

	// vm.$watch( expression, callback, [deep, immediate] )
	//  expression String
	//  callback( newValue, oldValue ) Function
	//  deep Boolean optional
	//  immdediate Boolean optional
	// Watch an expression on the Vue instance for changes.
	// The expression can be a single keypath or actual expressions:
	Watch func(
		expression string,
		callback func(newVal, oldVal *js.Object),
		deepWatch bool,
	) (unwatcher func()) `js:"$watch"`

	// vm.$eval( expression )
	// 	expression String
	// Evaluate an expression that can also contain filters.
	// assuming vm.msg = 'hello'
	// vm.$eval('msg | uppercase') // -> 'HELLO'
	Eval func(expression string) *js.Object `js:"$eval"`

	// vm.$get( expression )
	// 	expression String
	// Retrieve a value from the Vue instance given an expression.
	// Expressions that throw errors will be suppressed and return undefined.
	Get func(expression string) *js.Object `js:"$get"`

	// vm.$set( keypath, value )
	// 	keypath String
	// 	value *
	// Set a data value on the Vue instance given a valid keypath.
	// If the path doesn’t exist it will be created.
	Set func(keypath string, val interface{}) `js:"$set"`

	// vm.$add( keypath, value )
	//
	// 	keypath String
	// 	value *
	// Add a root level property to the Vue instance (and also its $data).
	// Due to the limitations of ES5, Vue cannot detect properties directly
	// added to or deleted from an Object,
	// so use this method and vm.$delete when you need to do so. Additionally,
	// all observed objects are augmented with these two methods too.
	Add func(keypath string, val interface{}) `js:"$add"`

	// vm.$delete( keypath )
	// 	keypath String
	// Delete a root level property on the Vue instance (and also its $data).
	Delete func(keypath string) `js:"$delete"`

	// vm.$interpolate( templateString )
	// 	templateString String
	// Evaluate a piece of template string containing mustache interpolations.
	// Note that this method simply performs string interpolation;
	// attribute directives are not compiled.
	//
	// // assuming vm.msg = 'hello'
	// vm.$interpolate('{{msg}} world!') // -> 'hello world!'
	Interpolate func(templateString string) `js:"$interpolate"`

	////////////////////////////////// Events

	// Each vm is also an event emitter.
	// When you have multiple nested ViewModels,
	// you can use the event system to communicate between them.
	//
	// vm.$dispatch( event, [args…] )
	//	event String
	// 	args… optional
	//
	// Dispatch an event from the current vm that propagates all the way up to its $root.
	// If a callback returns false, it will stop the propagation at its owner instance.
	Dispatch func(event string, args ...interface{}) `js:"$dispatch"`

	// vm.$broadcast( event, [args…] )
	// 	event String
	// 	args… optional
	//
	// Emit an event to all children vms of the current vm,
	// which gets further broadcasted to their children all the way down.
	// If a callback returns false, its owner instance will not broadcast
	// the event any further.
	Broadcast func(event string, args ...interface{}) `js:"$broadcast"`

	// vm.$emit( event, [args…] )
	// 	event String
	// args… optional
	//
	// Trigger an event on this vm only.
	Emit func(event string, args ...interface{}) `js:"$emit"`

	// vm.$on( event, callback )
	// 	event String
	// callback Function
	//
	// Listen for an event on the current vm
	On func(event string, callback interface{}) `js:"$on"`

	// vm.$once( event, callback )
	// 	event String
	// callback Function
	//
	// Attach a one-time only listener for an event.
	Once func(event string, callback interface{}) `js:"$once"`

	// vm.$off( [event, callback] )
	// 	event String optional
	// callback Function optional
	//
	// If no arguments are given, stop listening for all events;
	// if only the event is given, remove all callbacks for that event;
	// if both event and callback are given, remove that specific callback only.
	Off func(event ...string) `js:"$off"`

	// DOM
	// All vm DOM manipulation methods work like their jQuery counterparts -
	// except they also trigger Vue.js transitions if there are any declared
	// on vm’s $el. For more details on transitions see Adding Transition Effects.

	// vm.$appendTo( element|selector, [callback] )
	// 	element HTMLElement | selector String
	// callback Function optional
	// Append the vm’s $el to target element. The argument can be either
	// an element or a querySelector string.
	AppendTo func(elementOrselector string) `js:"$appendTo"`

	// vm.$before( element|selector, [callback] )
	// 	element HTMLElement | selector String
	// callback Function optional
	// Insert the vm’s $el before target element.
	Before func(elementOrselector string) `js:"$before"`

	// vm.$after( element|selector, [callback] )
	// 	element HTMLElement | selector String
	// callback Function optional
	// Insert the vm’s $el after target element.
	After func(elementOrselector string) `js:"$after"`

	// vm.$remove( [callback] )
	// 	callback Function optional
	// Remove the vm’s $el from the DOM.
	Remove func() `js:"$remove"`

	/////////////////////   Lifecycle

	// vm.$mount( [element|selector] )
	// 	element HTMLElement | selector String optional
	// If the Vue instance didn’t get an el option at instantiation,
	// you can manually call $mount() to assign an element to it and
	// start the compilation. If no argument is provided,
	// an empty <div> will be automatically created. Calling $mount()
	// on an already mounted instance will have no effect.
	// The method returns the instance itself so you can chain other
	// instance methods after it.
	Mount func(elementOrselector string) *Vue `js:"$mount"`

	// vm.$destroy( [remove] )
	// remove Boolean optional
	// Completely destroy a vm. Clean up its connections with other existing vms,
	// unbind all its directives and remove its $el from the DOM.
	// Also, all $on and $watch listeners will be automatically removed.
	Destroy func(remove bool) `js:"$destroy"`

	// vm.$compile( element )
	// 	element HTMLElement
	// Partially compile a piece of DOM (Element or DocumentFragment).
	// The method returns a decompile function that tearsdown the directives
	// created during the process. Note the decompile function does not remove
	// the DOM. This method is exposed primarily for writing advanced custom directives.
	Compile func(element string) `js:"$compile"`

	// vm.$addChild( [options, constructor] )
	// options Object optional
	// constructor Function optional
	//
	// Adds a child instance to the current instance.
	// The options object is the same in manually instantiating an instance.
	// Optionally you can pass in a constructor created from Vue.extend().
	//
	// There are three implications of a parent-child relationship between instances:
	// The parent and child can communicate via the event system.
	// The child has access to all parent assets (e.g. custom directives).
	// The child, if inheriting parent scope, has access to parent scope data properties.
	AddChild func(options js.M) `js:"$addChild"`

	// vm.$log( [keypath] )
	//
	// keypath String optional
	// Log the current instance data as a plain object, which is more
	// console-inspectable than a bunch of getter/setters.
	// Also accepts an optional key.
	//
	// vm.$log() // logs entire ViewModel data
	// vm.$log('item') // logs vm.item
	Log func(keypath ...interface{}) `js:"$log"`
}

// New creates a VueJS Instance to apply bidings between `structPtr` and
// `selectorOrElementOrFunction` target, it also connects the generated VueJS
// instance with the `structPtr`, you can use `vue.GetVM` from you code to
// access the generated VueJS Instance (can be used as `this` for JavaScirpt side).
//
//  * all `exported fields` of the `struct` would become VueJS Instance's data
//  which can be used in the html to do data binding: v-bind, etc
//
//  * all `exported funcs` of the `struct` would become VueJS Instance's methods
//  which can be called as html event handler: v-on, etc
//
//  * the `struct` talked above should have an embeded anonymous `*js.Object` field
//  and `exported fields` should have proper `js struct tag` for
//  bidirectionaly data bindings
//
/////////////// ONE IMPORTANT NOTICE `struct exported funcs` ///////////////////
//
// Rules for exported functions usage:
//
//  * If your func uses any of the `exported fields`, then DONOT modify any.
//  These can be viewed roughly as `computed attribute` in `VueJS` wourld,
//  with the form of function invocation (invoke).
//
//  * If your func modifies any of the `exported fields`, then DONOT use it
//  in any data `DISPLAYing` expression or directive. They can be used as
//  event handlers (their main use cases).
//
// These rules are required for VueJS dependency system to work correctly.
//
// You can get this *Vue instance through `vue.GetVM(structPtr)`
// which acts as `this` of the VueJS(javascript) side of world
func New(selectorOrElementOrFunction interface{}, structPtr interface{}) *Vue {
	o := vue.New(js.M{
		"el":      selectorOrElementOrFunction,
		"data":    structPtr,
		"methods": js.MakeWrapper(structPtr),
	})
	vm := &Vue{
		Object: o,
	}
	vMap[structPtr] = vm
	return vm
}

// GetVM returns coresponding VueJS instance from a gopherjs struct pointer
// (the underlying ViewModel data), this function is mainly in
// gopherjs struct method functions to reference the `VueJS instance`
func GetVM(structPtr interface{}) *Vue {
	vm, ok := vMap[structPtr]
	if !ok {
		println("Vue not registerd yet:", structPtr)
		panic("Vue not registerd yet")
	}
	return vm
}

// WatchEx using a simpler form to do Vue.$watch
func (v *Vue) WatchEx(expression string, callback func(newVal *js.Object)) (unwatcher func()) {
	obj := v.Call("$watch", expression, callback)
	return func() {
		obj.Invoke()
	}
}
<commit_msg>update documentation<commit_after>// Package vue provides gopherjs bindings for VueJS. see func `New` for
//  futher information
package vue

import (
	"github.com/gopherjs/gopherjs/js"
)

var (
	vue  = js.Global.Get("Vue")
	vMap = make(map[interface{}]*Vue, 0)
)

type Vue struct {
	*js.Object
	///////////////////////////// Instance Properties
	// vm.$data
	// 	Type: Object
	// Details:
	//  The data object that the Vue instance is observing.
	//  You can swap it with a new object.
	//  The Vue instance proxies access to the properties on its data object.
	Data *js.Object `js:"$data"`

	// vm.$el
	//  Type: HTMLElement
	//  Read only
	// Details:
	//  The DOM element that the Vue instance is managing.
	//	Note that for Fragment Instances, vm.$el will
	//  return an anchor node that
	//	indicates the starting position of the fragment.
	El *js.Object `js:"$el"`

	// vm.$options
	//  Type: Object
	//  Read only
	// Details:
	//  The instantiation options used for the current Vue instance.
	//  This is useful when you want to include custom
	//  properties in the options:
	//	 new Vue({
	//	   customOption: 'foo',
	//	   created: function () {
	//	     console.log(this.$options.customOption) // -> 'foo'
	//	   }
	//	 })
	Options *js.Object `js:"$options"`

	// vm.$parent
	//  Type: Vue instance
	//  Read only
	// Details:
	// 		The parent instance, if the current instance has one.
	Parent *js.Object `js:"$parent"`

	// vm.$root
	//  Type: Vue instance
	//  Read only
	// Details:
	// 		The root Vue instance of the current component tree.
	// 		If the current instance has no parents this value will be itself.
	Root *js.Object `js:"$root"`

	// vm.$children
	//  Type: Array<Vue instance>
	//  Read only
	// Details:
	// 	The direct child components of the current instance.
	Children *js.Object `js:"$children"`

	// vm.$refs
	// 	Type: Object
	// 	Read only
	// Details:
	// 	An object that holds child components that have v-ref registered.
	// See also:
	// 	Child Component Refs
	// 	v-ref.
	Refs *js.Object `js:"$refs"`

	// vm.$els
	// 	Type: Object
	// 	Read only
	// Details:
	// 	An object that holds DOM elements that have v-el registered.
	// See also: v-el.
	Els *js.Object `js:"$els"`

	// vm.$watch( expression, callback, [deep, immediate] )
	//  expression String
	//  callback( newValue, oldValue ) Function
	//  deep Boolean optional
	//  immdediate Boolean optional
	// Watch an expression on the Vue instance for changes.
	// The expression can be a single keypath or actual expressions:
	Watch func(
		expression string,
		callback func(newVal, oldVal *js.Object),
		deepWatch bool,
	) (unwatcher func()) `js:"$watch"`

	// vm.$eval( expression )
	// 	expression String
	// Evaluate an expression that can also contain filters.
	// assuming vm.msg = 'hello'
	// vm.$eval('msg | uppercase') // -> 'HELLO'
	Eval func(expression string) *js.Object `js:"$eval"`

	// vm.$get( expression )
	// 	expression String
	// Retrieve a value from the Vue instance given an expression.
	// Expressions that throw errors will be suppressed
	// and return undefined.
	Get func(expression string) *js.Object `js:"$get"`

	// vm.$set( keypath, value )
	// 	keypath String
	// 	value *
	// Set a data value on the Vue instance given a valid keypath.
	// If the path doesn’t exist it will be created.
	Set func(keypath string, val interface{}) `js:"$set"`

	// vm.$add( keypath, value )
	//
	// 	keypath String
	// 	value *
	// Add a root level property to the Vue instance (and also its $data).
	// Due to the limitations of ES5, Vue cannot detect properties directly
	// added to or deleted from an Object,
	// so use this method and vm.$delete when you need to do so. Additionally,
	// all observed objects are augmented with these two methods too.
	Add func(keypath string, val interface{}) `js:"$add"`

	// vm.$delete( keypath )
	// 	keypath String
	// Delete a root level property on the Vue instance (and also its $data).
	Delete func(keypath string) `js:"$delete"`

	// vm.$interpolate( templateString )
	// 	templateString String
	// Evaluate a piece of template string containing
	// mustache interpolations.
	// Note that this method simply performs string interpolation;
	// attribute directives are not compiled.
	//
	// // assuming vm.msg = 'hello'
	// vm.$interpolate('{{msg}} world!') // -> 'hello world!'
	Interpolate func(templateString string) `js:"$interpolate"`

	////////////////////////////////// Events

	// Each vm is also an event emitter.
	// When you have multiple nested ViewModels,
	// you can use the event system to communicate between them.
	//
	// vm.$dispatch( event, [args…] )
	//	event String
	// 	args… optional
	//
	// Dispatch an event from the current vm that propagates
	// all the way up to its $root. If a callback returns false,
	// it will stop the propagation at its owner instance.
	Dispatch func(event string, args ...interface{}) `js:"$dispatch"`

	// vm.$broadcast( event, [args…] )
	// 	event String
	// 	args… optional
	//
	// Emit an event to all children vms of the current vm,
	// which gets further broadcasted to their children all the way down.
	// If a callback returns false, its owner instance will not broadcast
	// the event any further.
	Broadcast func(event string, args ...interface{}) `js:"$broadcast"`

	// vm.$emit( event, [args…] )
	// 	event String
	// args… optional
	//
	// Trigger an event on this vm only.
	Emit func(event string, args ...interface{}) `js:"$emit"`

	// vm.$on( event, callback )
	// 	event String
	// callback Function
	//
	// Listen for an event on the current vm
	On func(event string, callback interface{}) `js:"$on"`

	// vm.$once( event, callback )
	// 	event String
	// callback Function
	//
	// Attach a one-time only listener for an event.
	Once func(event string, callback interface{}) `js:"$once"`

	// vm.$off( [event, callback] )
	// 	event String optional
	// callback Function optional
	//
	// If no arguments are given, stop listening for all events;
	// if only the event is given, remove all callbacks for that event;
	// if both event and callback are given,
	// remove that specific callback only.
	Off func(event ...string) `js:"$off"`

	// DOM
	// All vm DOM manipulation methods work like their jQuery counterparts -
	// except they also trigger Vue.js transitions if there are any declared
	// on vm’s $el. For more details on transitions
	// see Adding Transition Effects.

	// vm.$appendTo( element|selector, [callback] )
	// 	element HTMLElement | selector String
	// callback Function optional
	// Append the vm’s $el to target element. The argument can be either
	// an element or a querySelector string.
	AppendTo func(elementOrselector string) `js:"$appendTo"`

	// vm.$before( element|selector, [callback] )
	// 	element HTMLElement | selector String
	// callback Function optional
	// Insert the vm’s $el before target element.
	Before func(elementOrselector string) `js:"$before"`

	// vm.$after( element|selector, [callback] )
	// 	element HTMLElement | selector String
	// callback Function optional
	// Insert the vm’s $el after target element.
	After func(elementOrselector string) `js:"$after"`

	// vm.$remove( [callback] )
	// 	callback Function optional
	// Remove the vm’s $el from the DOM.
	Remove func() `js:"$remove"`

	/////////////////////   Lifecycle

	// vm.$mount( [element|selector] )
	// 	element HTMLElement | selector String optional
	// If the Vue instance didn’t get an el option at instantiation,
	// you can manually call $mount() to assign an element to it and
	// start the compilation. If no argument is provided,
	// an empty <div> will be automatically created. Calling $mount()
	// on an already mounted instance will have no effect.
	// The method returns the instance itself so you can chain other
	// instance methods after it.
	Mount func(elementOrselector string) *Vue `js:"$mount"`

	// vm.$destroy( [remove] )
	//  remove Boolean optional
	// Completely destroy a vm.
	// Clean up its connections with other existing vms,
	// unbind all its directives and remove its $el from the DOM.
	// Also, all $on and $watch listeners will be automatically removed.
	Destroy func(remove bool) `js:"$destroy"`

	// vm.$compile( element )
	// 	element HTMLElement
	// Partially compile a piece of DOM (Element or DocumentFragment).
	// The method returns a decompile function that tearsdown the directives
	// created during the process.
	// Note the decompile function does not remove the DOM.
	// This method is exposed primarily for
	// writing advanced custom directives.
	Compile func(element string) `js:"$compile"`

	// vm.$addChild( [options, constructor] )
	//  options Object optional
	//  constructor Function optional
	//
	// Adds a child instance to the current instance.
	// The options object is the same in manually instantiating an instance.
	// Optionally you can pass in a constructor created from Vue.extend().
	//
	// There are three implications of
	// a parent-child relationship between instances:
	//  The parent and child can communicate via the event system.
	//  The child has access to all parent assets (e.g. custom directives).
	//  The child, if inheriting parent scope,
	//   has access to parent scope data properties.
	AddChild func(options js.M) `js:"$addChild"`

	// vm.$log( [keypath] )
	//
	// keypath String optional
	// Log the current instance data as a plain object, which is more
	// console-inspectable than a bunch of getter/setters.
	// Also accepts an optional key.
	//
	// vm.$log() // logs entire ViewModel data
	// vm.$log('item') // logs vm.item
	Log func(keypath ...interface{}) `js:"$log"`
}

// New creates a VueJS Instance to apply bidings between `structPtr` and
// `selectorOrElementOrFunction` target, it also connects the generated VueJS
// instance with the `structPtr`, you can use `vue.GetVM` from you code to
// access the generated VueJS Instance (can be used as `this` for JavaScirpt side).
//
//  * all `exported fields` of the `struct` would become VueJS Instance's data
//  which can be used in the html to do data binding: v-bind, etc
//
//  * all `exported funcs` of the `struct` would become VueJS Instance's methods
//  which can be called as html event handler: v-on, etc
//
//  * the `struct` talked above should have an embeded anonymous `*js.Object` field
//  and `exported fields` should have proper `js struct tag` for
//  bidirectionaly data bindings
//
// Rules for exported functions usage IMPORTANT!:
//
//  * If your func uses any of the `exported fields`, then DONOT modify any.
//  These can be viewed roughly as `computed attribute` in `VueJS` wourld,
//  with the form of function invocation (invoke).
//
//  * If your func modifies any of the `exported fields`, then DONOT use it
//  in any data `DISPLAYing` expression or directive. They can be used as
//  event handlers (their main use cases).
//
// These rules are required for VueJS dependency system to work correctly.
//
// You can get this *Vue instance through `vue.GetVM(structPtr)`
// which acts as `this` of the VueJS(javascript) side of world
func New(selectorOrElementOrFunction interface{}, structPtr interface{}) *Vue {
	o := vue.New(js.M{
		"el":      selectorOrElementOrFunction,
		"data":    structPtr,
		"methods": js.MakeWrapper(structPtr),
	})
	vm := &Vue{
		Object: o,
	}
	vMap[structPtr] = vm
	return vm
}

// GetVM returns coresponding VueJS instance from a gopherjs struct pointer
// (the underlying ViewModel data), this function is mainly in
// gopherjs struct method functions to reference the `VueJS instance`
func GetVM(structPtr interface{}) *Vue {
	vm, ok := vMap[structPtr]
	if !ok {
		println("Vue not registerd yet:", structPtr)
		panic("Vue not registerd yet")
	}
	return vm
}

// WatchEx using a simpler form to do Vue.$watch
func (v *Vue) WatchEx(expression string, callback func(newVal *js.Object)) (unwatcher func()) {
	obj := v.Call("$watch", expression, callback)
	return func() {
		obj.Invoke()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strconv"
)

var datauriPattern *regexp.Regexp

func init() {
	compileDatauriPattern()
}

func main() {
	http.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) {
		switch req.Method {
		case "GET":
			handleGet(res, req)
		case "POST":
			handlePost(res, req)
		default:
			http.Error(res, "Only GET and POST supported", http.StatusMethodNotAllowed)
		}
	})

	port := os.Getenv("PORT")
	log.Println("listening:true port:", port)
	log.Fatal(http.ListenAndServe(":"+port, nil))
}

func compileDatauriPattern() {
	var err error
	datauriPattern, err = regexp.Compile("^data:(.*?)?(;base64)?,(.+)$")
	if err != nil {
		log.Fatal(err)
	}
}

func handleGet(res http.ResponseWriter, req *http.Request) {
	uri := req.URL.Query().Get("uri")
	match := datauriPattern.FindStringSubmatch(uri)
	if len(match) == 0 {
		log.Println("get.error.uri:", uri)
		http.Error(res, "Parameter 'uri' must be present and in RFC 2397 form", http.StatusBadRequest)
		return
	}
	contentType := match[1]
	isBase64 := match[2] != ""
	data := match[3]

	if req.URL.Query().Get("status") != "" {
		statusCode, err := strconv.Atoi(req.URL.Query().Get("status"))
		if err != nil {
			log.Println("get.error.base64.decode:", err)
			http.Error(res, "Error parsing status code to integer", http.StatusBadRequest)
			return
		}
		res.WriteHeader(statusCode)
	}

	res.Header().Set("Content-Type", contentType)
	if isBase64 {
		decoded, err := base64.StdEncoding.DecodeString(data)
		if err != nil {
			log.Println("get.error.base64.decode:", err)
			http.Error(res, "Error decoding base64: "+err.Error(), http.StatusBadRequest)
			return
		}
		res.Write(decoded)
	} else {
		fmt.Fprint(res, data)
	}
}

func handlePost(res http.ResponseWriter, req *http.Request) {
	scheme := "http"
	if req.TLS != nil || req.Header.Get("X-Forwarded-Proto") == "https" {
		scheme = "https"
	}

	data, err := ioutil.ReadAll(req.Body)
	if err != nil {
		log.Println("post.error.body:", err)
		http.Error(res, "Error reading request body: "+err.Error(), http.StatusBadRequest)
		return
	}

	contentType := req.Header.Get("Content-Type")
	if contentType == "" || contentType == "application/x-www-form-urlencoded" {
		contentType = http.DetectContentType(data)
	}

	base64 := base64.StdEncoding.EncodeToString(data)
	datauri := "data:" + contentType + ";base64," + base64
	uri := scheme + "://" + req.Host + req.URL.Path + "?uri=" + url.QueryEscape(datauri)

	res.Header().Set("Content-Type", "text/uri-list; charset=utf-8")
	fmt.Fprintln(res, uri)
}
<commit_msg>Allow PUT to also work for POST<commit_after>package main

import (
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strconv"
)

var datauriPattern *regexp.Regexp

func init() {
	compileDatauriPattern()
}

func main() {
	http.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) {
		switch req.Method {
		case "GET":
			handleGet(res, req)
		case "POST":
			handlePost(res, req)
		case "PUT":
			handlePost(res, req)
		default:
			http.Error(res, "Only GET and POST supported", http.StatusMethodNotAllowed)
		}
	})

	port := os.Getenv("PORT")
	log.Println("listening:true port:", port)
	log.Fatal(http.ListenAndServe(":"+port, nil))
}

func compileDatauriPattern() {
	var err error
	datauriPattern, err = regexp.Compile("^data:(.*?)?(;base64)?,(.+)$")
	if err != nil {
		log.Fatal(err)
	}
}

func handleGet(res http.ResponseWriter, req *http.Request) {
	uri := req.URL.Query().Get("uri")
	match := datauriPattern.FindStringSubmatch(uri)
	if len(match) == 0 {
		log.Println("get.error.uri:", uri)
		http.Error(res, "Parameter 'uri' must be present and in RFC 2397 form", http.StatusBadRequest)
		return
	}
	contentType := match[1]
	isBase64 := match[2] != ""
	data := match[3]

	if req.URL.Query().Get("status") != "" {
		statusCode, err := strconv.Atoi(req.URL.Query().Get("status"))
		if err != nil {
			log.Println("get.error.base64.decode:", err)
			http.Error(res, "Error parsing status code to integer", http.StatusBadRequest)
			return
		}
		res.WriteHeader(statusCode)
	}

	res.Header().Set("Content-Type", contentType)
	if isBase64 {
		decoded, err := base64.StdEncoding.DecodeString(data)
		if err != nil {
			log.Println("get.error.base64.decode:", err)
			http.Error(res, "Error decoding base64: "+err.Error(), http.StatusBadRequest)
			return
		}
		res.Write(decoded)
	} else {
		fmt.Fprint(res, data)
	}
}

func handlePost(res http.ResponseWriter, req *http.Request) {
	scheme := "http"
	if req.TLS != nil || req.Header.Get("X-Forwarded-Proto") == "https" {
		scheme = "https"
	}

	data, err := ioutil.ReadAll(req.Body)
	if err != nil {
		log.Println("post.error.body:", err)
		http.Error(res, "Error reading request body: "+err.Error(), http.StatusBadRequest)
		return
	}

	contentType := req.Header.Get("Content-Type")
	if contentType == "" || contentType == "application/x-www-form-urlencoded" {
		contentType = http.DetectContentType(data)
	}

	base64 := base64.StdEncoding.EncodeToString(data)
	datauri := "data:" + contentType + ";base64," + base64
	uri := scheme + "://" + req.Host + req.URL.Path + "?uri=" + url.QueryEscape(datauri)

	res.Header().Set("Content-Type", "text/uri-list; charset=utf-8")
	fmt.Fprintln(res, uri)
}
<|endoftext|>


<commit_before>package main

// Slack outgoing webhooks are handled here. Requests come in and are
// examined to see if we need to respond. If we do, we immmediately respond
//
// Create an outgoing webhook in your Slack here:
// https://my.slack.com/services/new/outgoing-webhook

import (
	"encoding/json"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"
)

type WebhookResponse struct {
	Username string `json:"username"`
	Text     string `json:"text"`
	Channel  string `json:"channel"`
}

func init() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		incomingText := r.PostFormValue("text")
		log.Printf("Handling incoming request: %s", incomingText)

		if strings.Contains(incomingText, "<@U123>") {
			var response WebhookResponse
			response.Username = botUsername
			response.Text = "Slack is the best and has reduced email by 70%!"
			log.Printf("Sending response: %s", response.Text)

			b, err := json.Marshal(response)
			if err != nil {
				log.Fatal(err)
			}

			time.Sleep(5 * time.Second)
			w.Write(b)
		}
	})
}

func StartServer(port int) {
	log.Printf("Starting HTTP server on %d", port)
	err := http.ListenAndServe(":"+strconv.Itoa(port), nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>Smaller wait<commit_after>package main

// Slack outgoing webhooks are handled here. Requests come in and are
// examined to see if we need to respond. If we do, we immmediately respond
//
// Create an outgoing webhook in your Slack here:
// https://my.slack.com/services/new/outgoing-webhook

import (
	"encoding/json"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"
)

type WebhookResponse struct {
	Username string `json:"username"`
	Text     string `json:"text"`
	Channel  string `json:"channel"`
}

func init() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		incomingText := r.PostFormValue("text")
		log.Printf("Handling incoming request: %s", incomingText)

		if strings.Contains(incomingText, "<@U123>") {
			var response WebhookResponse
			response.Username = botUsername
			response.Text = "Slack is the best and has reduced email by 70%!"
			log.Printf("Sending response: %s", response.Text)

			b, err := json.Marshal(response)
			if err != nil {
				log.Fatal(err)
			}

			time.Sleep(1 * time.Second)
			w.Write(b)
		}
	})
}

func StartServer(port int) {
	log.Printf("Starting HTTP server on %d", port)
	err := http.ListenAndServe(":"+strconv.Itoa(port), nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package main

// Slack outgoing webhooks are handled here. Requests come in and are run through
// the markov chain to generate a response, which is sent back to Slack.
//
// Create an outgoing webhook in your Slack here:
// https://my.slack.com/services/new/outgoing-webhook

import (
	"encoding/json"
	"log"
	"strconv"
	"math/rand"
	"net/http"
	"strings"
	"time"
)

type WebhookResponse struct {
	Username string `json:"username"`
	Text     string `json:"text"`
}

func init() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		incomingText := r.PostFormValue("text")
		if incomingText != "" && r.PostFormValue("user_id") != "" && r.PostFormValue("user_id") != "USLACKBOT"{
			text := parseText(incomingText)
			//log.Printf("Handling incoming request: %s", text)

			if text != "" {
				markovChain.Write(text)
			}

			go func() {
				markovChain.Save(stateFile)
			}()

			if rand.Intn(100) < responseChance || strings.Contains(strings.ToLower(incomingText), strings.ToLower(botUsername)) {
				var response WebhookResponse
				response.Username = botUsername
				if strings.Contains(incomingText, "TG") && strings.HasPrefix(strings.ToLower(incomingText), strings.ToLower(botUsername)) {
					responseChance -= 5
					response.Text = "Okay :( je suis à "+strconv.Itoa(responseChance)+"%"
				} else if strings.Contains(incomingText, "BS") && strings.HasPrefix(strings.ToLower(incomingText), strings.ToLower(botUsername)) {
					responseChance += 5
					response.Text = "Okay :D je suis à "+strconv.Itoa(responseChance)+"%"
				} else if strings.Contains(incomingText, "moral") && strings.HasPrefix(strings.ToLower(incomingText), strings.ToLower(botUsername)) {
					response.Text = "Environ "+strconv.Itoa(responseChance)+"% mon capitaine !"
				} else {
					response.Text = markovChain.Generate(numWords)
				}
				//log.Printf("Sending response: %s", response.Text)

				b, err := json.Marshal(response)
				if err != nil {
					log.Fatal(err)
				}

				time.Sleep(5 * time.Second)
				w.Write(b)
			}
		}
	})
}

func StartServer(addr string) {
	log.Printf("Starting HTTP server on %s", addr)
	err := http.ListenAndServe(addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>Add bounds for response chance<commit_after>package main

// Slack outgoing webhooks are handled here. Requests come in and are run through
// the markov chain to generate a response, which is sent back to Slack.
//
// Create an outgoing webhook in your Slack here:
// https://my.slack.com/services/new/outgoing-webhook

import (
	"encoding/json"
	"log"
	"strconv"
	"math/rand"
	"net/http"
	"strings"
	"time"
)

type WebhookResponse struct {
	Username string `json:"username"`
	Text     string `json:"text"`
}

func init() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		incomingText := r.PostFormValue("text")
		if incomingText != "" && r.PostFormValue("user_id") != "" && r.PostFormValue("user_id") != "USLACKBOT"{
			text := parseText(incomingText)
			//log.Printf("Handling incoming request: %s", text)

			if text != "" {
				markovChain.Write(text)
			}

			go func() {
				markovChain.Save(stateFile)
			}()

			if rand.Intn(100) < responseChance || strings.Contains(strings.ToLower(incomingText), strings.ToLower(botUsername)) {
				var response WebhookResponse
				response.Username = botUsername
				if strings.Contains(incomingText, "TG") && strings.HasPrefix(strings.ToLower(incomingText), strings.ToLower(botUsername)) {
					responseChance -= 5
					if responseChance < 0 {
						responseChance = 0
					}
					response.Text = "Okay :( je suis à "+strconv.Itoa(responseChance)+"%"
				} else if strings.Contains(incomingText, "BS") && strings.HasPrefix(strings.ToLower(incomingText), strings.ToLower(botUsername)) {
					responseChance += 5
					if responseChance > 100 {
						responseChance = 100
					}
					response.Text = "Okay :D je suis à "+strconv.Itoa(responseChance)+"%"
				} else if strings.Contains(incomingText, "moral") && strings.HasPrefix(strings.ToLower(incomingText), strings.ToLower(botUsername)) {
					response.Text = "Environ "+strconv.Itoa(responseChance)+"% mon capitaine !"
				} else {
					response.Text = markovChain.Generate(numWords)
				}
				//log.Printf("Sending response: %s", response.Text)

				b, err := json.Marshal(response)
				if err != nil {
					log.Fatal(err)
				}

				time.Sleep(5 * time.Second)
				w.Write(b)
			}
		}
	})
}

func StartServer(addr string) {
	log.Printf("Starting HTTP server on %s", addr)
	err := http.ListenAndServe(addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package terraform_vix

import (
	"log"

	"github.com/hashicorp/terraform/helper/resource"
)

// resourceMap is the mapping of resources we support to their basic
// operations. This makes it easy to implement new resource types.
var resourceMap *resource.Map

func init() {
	// Terraform is already adding the timestamp for us
	log.SetFlags(log.Lshortfile)

	resourceMap = &resource.Map{
		Mapping: map[string]resource.Resource{
			"vix_vm": resource.Resource{
				ConfigValidator: resource_vix_vm_validation(),
				Create:          resource_vix_vm_create,
				Destroy:         resource_vix_vm_destroy,
				Diff:            resource_vix_vm_diff,
				Refresh:         resource_vix_vm_refresh,
				Update:          resource_vix_vm_update,
			},

			"vix_sharedfolder": resource.Resource{
				ConfigValidator: resource_vix_sharedfolder_validation(),
				Create:          resource_vix_sharedfolder_create,
				Destroy:         resource_vix_sharedfolder_destroy,
				Diff:            resource_vix_sharedfolder_diff,
				Refresh:         resource_vix_sharedfolder_refresh,
				Update:          resource_vix_sharedfolder_update,
			},

			"vix_vnic": resource.Resource{
				ConfigValidator: resource_vix_vnic_validation(),
				Create:          resource_vix_vnic_create,
				Destroy:         resource_vix_vnic_destroy,
				Diff:            resource_vix_vnic_diff,
				Refresh:         resource_vix_vnic_refresh,
				Update:          resource_vix_vnic_update,
			},

			"vix_vswitch": resource.Resource{
				ConfigValidator: resource_vix_vswitch_validation(),
				Create:          resource_vix_vswitch_create,
				Destroy:         resource_vix_vswitch_destroy,
				Diff:            resource_vix_vswitch_diff,
				Refresh:         resource_vix_vswitch_refresh,
				Update:          resource_vix_vswitch_update,
			},
		},
	}
}
<commit_msg>Terraform does not support what we were intending here<commit_after>package terraform_vix

import (
	"log"

	"github.com/hashicorp/terraform/helper/resource"
)

// resourceMap is the mapping of resources we support to their basic
// operations. This makes it easy to implement new resource types.
var resourceMap *resource.Map

func init() {
	// Terraform is already adding the timestamp for us
	log.SetFlags(log.Lshortfile)

	resourceMap = &resource.Map{
		Mapping: map[string]resource.Resource{
			"vix_vm": resource.Resource{
				ConfigValidator: resource_vix_vm_validation(),
				Create:          resource_vix_vm_create,
				Destroy:         resource_vix_vm_destroy,
				Diff:            resource_vix_vm_diff,
				Refresh:         resource_vix_vm_refresh,
				Update:          resource_vix_vm_update,
			},

			// "vix_sharedfolder": resource.Resource{
			// 	ConfigValidator: resource_vix_sharedfolder_validation(),
			// 	Create:          resource_vix_sharedfolder_create,
			// 	Destroy:         resource_vix_sharedfolder_destroy,
			// 	Diff:            resource_vix_sharedfolder_diff,
			// 	Refresh:         resource_vix_sharedfolder_refresh,
			// 	Update:          resource_vix_sharedfolder_update,
			// },

			// "vix_vnic": resource.Resource{
			// 	ConfigValidator: resource_vix_vnic_validation(),
			// 	Create:          resource_vix_vnic_create,
			// 	Destroy:         resource_vix_vnic_destroy,
			// 	Diff:            resource_vix_vnic_diff,
			// 	Refresh:         resource_vix_vnic_refresh,
			// 	Update:          resource_vix_vnic_update,
			// },

			"vix_vswitch": resource.Resource{
				ConfigValidator: resource_vix_vswitch_validation(),
				Create:          resource_vix_vswitch_create,
				Destroy:         resource_vix_vswitch_destroy,
				Diff:            resource_vix_vswitch_diff,
				Refresh:         resource_vix_vswitch_refresh,
				Update:          resource_vix_vswitch_update,
			},
		},
	}
}
<|endoftext|>


<commit_before>package organisations

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/Financial-Times/neo-utils-go/neoutils"
	"github.com/jmcvetta/neoism"
)

type service struct {
	cypherRunner neoutils.CypherRunner
	indexManager neoutils.IndexManager
}

func NewCypherOrganisationService(cypherRunner neoutils.CypherRunner, indexManager neoutils.IndexManager) service {
	return service{cypherRunner, indexManager}
}

func (cd service) Initialise() error {
	return neoutils.EnsureConstraints(cd.indexManager, map[string]string{
		"Thing":        "uuid",
		"Concept":      "uuid",
		"Organisation": "uuid",
		"Identifier":   "value"})
}

func setProps(props *map[string]interface{}, item *string, propName string) {
	if *item != "" {
		(*props)[propName] = *item
	}
}

func setListProps(props *map[string]interface{}, itemList *[]string, propName string) {
	var items []string

	for _, item := range *itemList {
		items = append(items, item)
	}

	if len(items) > 0 {
		(*props)[propName] = items
	}
}

//Write - Writes an Organisation node
func (cd service) Write(thing interface{}) error {
	o := thing.(organisation)

	props := map[string]interface{}{
		"uuid":       o.UUID,
		"properName": o.ProperName,
		"prefLabel":  o.ProperName,
	}

	setProps(&props, &o.LegalName, "legalName")
	setProps(&props, &o.ShortName, "shortName")
	setProps(&props, &o.HiddenLabel, "hiddenLabel")
	setListProps(&props, &o.FormerNames, "formerNames")
	setListProps(&props, &o.LocalNames, "localNames")
	setListProps(&props, &o.TradeNames, "tradeNames")
	setListProps(&props, &o.Aliases, "aliases")

	deleteEntityRelationshipsQuery := &neoism.CypherQuery{
		Statement: `MATCH (o:Thing {uuid:{uuid}})
		OPTIONAL MATCH (o)-[hc:HAS_CLASSIFICATION]->(ic)
		OPTIONAL MATCH (o)-[soo:SUB_ORGANISATION_OF]->(p)
		OPTIONAL MATCH (o)<-[iden:IDENTIFIES]-(i)
		DELETE hc, soo, iden, i`,
		Parameters: map[string]interface{}{
			"uuid": o.UUID,
		},
	}

	queries := []*neoism.CypherQuery{deleteEntityRelationshipsQuery}

	var statement bytes.Buffer

	statement.WriteString(`MERGE (o:Thing {uuid: {uuid}})
					REMOVE o:PublicCompany:Company:Organisation:Concept:Thing
					SET o={props} `)

	identifierLabels := map[string]string{
		fsAuthority:  factsetIdentifierLabel,
		leiAuthority: leiIdentifierLabel,
		tmeAuthority: tmeIdentifierLabel,
	}
	for _, identifier := range o.Identifiers {

		if identifierLabels[identifier.Authority] == "" {
			return fmt.Errorf("This identifier type- %v, is not supported. Only FACTSET_EDM, LEI and FT-TME are currently supported", identifier.Authority)
		}
		addIdentfierQuery := addIdentifierQuery(identifier, o.UUID, identifierLabels[identifier.Authority])
		queries = append(queries, addIdentfierQuery)
	}

	err, stringType := o.Type.String()
	if err == nil {
		statement.WriteString("SET o:" + stringType + " ")
	} else {
		return err
	}

	if o.IndustryClassification != "" {
		statement.WriteString("MERGE (ic:Thing{uuid:'" + o.IndustryClassification + "'}) MERGE (o)-[:HAS_CLASSIFICATION]->(ic) ")
	}

	if o.ParentOrganisation != "" {
		statement.WriteString("MERGE (p:Thing{uuid:'" + o.ParentOrganisation + "'}) MERGE (o)-[:SUB_ORGANISATION_OF]->(p) ")
	}

	writeQuery := &neoism.CypherQuery{
		Statement: statement.String(),
		Parameters: map[string]interface{}{
			"uuid":  o.UUID,
			"props": props,
		},
	}

	//fmt.Printf("Write Query:", writeQuery.Statement)
	queries = append(queries, writeQuery)

	return cd.cypherRunner.CypherBatch(queries)
}

func addIdentifierQuery(identifier identifier, uuid string, identifierLabel string) *neoism.CypherQuery {

	statementTemplate := fmt.Sprintf(`MERGE (o:Thing {uuid:{uuid}})
					MERGE (i:Identifier {value:{value} , authority:{authority}})
					MERGE (o)<-[:IDENTIFIES]-(i)
					set i : %s `, identifierLabel)

	query := &neoism.CypherQuery{
		Statement: statementTemplate,
		Parameters: map[string]interface{}{
			"uuid":      uuid,
			"value":     identifier.IdentifierValue,
			"authority": identifier.Authority,
		},
	}
	return query
}

//Read - Internal Read of an Organisation
func (cd service) Read(uuid string) (interface{}, bool, error) {

	results := []struct {
		UUID          string       `json:"o.uuid"`
		Type          []string     `json:"type"`
		ProperName    string       `json:"o.properName"`
		LegalName     string       `json:"o.legalName"`
		ShortName     string       `json:"o.shortName"`
		HiddenLabel   string       `json:"o.hiddenLabel"`
		Identifiers   []identifier `json:"identifiers"`
		TradeNames    []string     `json:"o.tradeNames"`
		LocalNames    []string     `json:"o.localNames"`
		FormerNames   []string     `json:"o.formerNames"`
		Aliases       []string     `json:"o.aliases"`
		ParentOrgUUID string       `json:"par.uuid"`
		IndustryUUID  string       `json:"ind.uuid"`
	}{}

	readQuery := &neoism.CypherQuery{

		Statement: `MATCH (o:Organisation:Concept{uuid:{uuid}})
            OPTIONAL MATCH (o)-[:SUB_ORGANISATION_OF]->(par:Thing)
            OPTIONAL MATCH (o)-[:HAS_CLASSIFICATION]->(ind:Thing)
            OPTIONAL MATCH (o)<-[:IDENTIFIES]-(id:Identifier)
			with o, ind, par,  collect({authority:id.authority, identifierValue:id.value})as identifiers
            RETURN o.uuid , o.properName , labels(o) as Type, o.legalName, o.shortName, o.hiddenLabel,
            o.formerNames, o.tradeNames, o.localNames, o.aliases, ind.uuid, par.uuid, identifiers`,
		Parameters: map[string]interface{}{
			"uuid": uuid,
		},
		Result: &results,
	}

	if err := cd.cypherRunner.CypherBatch([]*neoism.CypherQuery{readQuery}); err != nil || len(results) == 0 {
		return organisation{}, false, err
	}

	result := results[0]

	o := organisation{
		UUID:                   result.UUID,
		ProperName:             result.ProperName,
		LegalName:              result.LegalName,
		ShortName:              result.ShortName,
		HiddenLabel:            result.HiddenLabel,
		TradeNames:             result.TradeNames,
		LocalNames:             result.LocalNames,
		FormerNames:            result.FormerNames,
		Identifiers:            result.Identifiers,
		Aliases:                result.Aliases,
		ParentOrganisation:     result.ParentOrgUUID,
		IndustryClassification: result.IndustryUUID,
	}

	addType(&o.Type, &result.Type)
	sortIdentifiers(o.Identifiers)

	if len(o.Identifiers) == 0 {
		o.Identifiers = make([]identifier, 0, 0)
	}

	return o, true, nil
}

func addType(orgType *OrgType, types *[]string) {
	i := len(*types)
	if i == 3 {
		*orgType = Organisation
	}
	if i == 4 {
		*orgType = Company
	}
	if i == 5 {
		*orgType = PublicCompany
	}
}

//Delete - Deletes an Organisation
func (pcd service) Delete(uuid string) (bool, error) {
	clearNode := &neoism.CypherQuery{
		Statement: `
			MATCH (org:Thing {uuid: {uuid}})
			OPTIONAL MATCH (p)<-[iden:IDENTIFIES]-(i:Identifier)
			REMOVE org:Concept:Organisation:Company:PublicCompany
			DELETE iden, i
			SET org={ uuid: {uuid}}
		`,
		Parameters: map[string]interface{}{
			"uuid": uuid,
		},
		IncludeStats: true,
	}
	qs := []*neoism.CypherQuery{
		clearNode,
		{
			Statement: `
		MATCH (org:Thing {uuid: {uuid}})
		OPTIONAL MATCH (org)-[a]-(x) WITH org, count(a) AS relCount WHERE relCount = 0
		DELETE org
		`,
			Parameters: map[string]interface{}{
				"uuid": uuid,
			},
		},
	}

	err := pcd.cypherRunner.CypherBatch(qs)

	s1, err := clearNode.Stats()

	if err != nil {
		return false, err
	}

	if s1.ContainsUpdates && s1.LabelsRemoved > 0 {
		return true, err
	}

	return false, err
}

func (s service) Check() error {
	return neoutils.Check(s.cypherRunner)
}

type countResult []struct {
	Count int `json:"c"`
}

func (s service) Count() (int, error) {

	results := countResult{}

	err := s.cypherRunner.CypherBatch([]*neoism.CypherQuery{{
		Statement: `MATCH (n:Organisation) return count(n) as c`,
		Result:    &results,
	}})

	if err != nil {
		return 0, err
	}

	return results[0].Count, nil
}

func (s service) DecodeJSON(dec *json.Decoder) (interface{}, string, error) {
	org := organisation{}
	err := dec.Decode(&org)
	return org, org.UUID, err
}

const (
	fsAuthority            = "http://api.ft.com/system/FACTSET-EDM"
	leiAuthority           = "http://api.ft.com/system/LEI"
	tmeAuthority           = "http://api.ft.com/system/FT-TME"
	factsetIdentifierLabel = "FactsetIdentifier"
	leiIdentifierLabel     = "LegalEntityIdentifier"
	tmeIdentifierLabel     = "TMEIdentifier"
)
<commit_msg>bumped version<commit_after>package organisations

import (
	"encoding/json"
	"fmt"
	"github.com/Financial-Times/neo-utils-go/neoutils"
	"github.com/jmcvetta/neoism"
)

type service struct {
	cypherRunner neoutils.CypherRunner
	indexManager neoutils.IndexManager
}

func NewCypherOrganisationService(cypherRunner neoutils.CypherRunner, indexManager neoutils.IndexManager) service {
	return service{cypherRunner, indexManager}
}

func (cd service) Initialise() error {
	return neoutils.EnsureConstraints(cd.indexManager, map[string]string{
		"Thing":        "uuid",
		"Concept":      "uuid",
		"Organisation": "uuid",
		"Identifier":   "value"})
}

func setProps(props *map[string]interface{}, item *string, propName string) {
	if *item != "" {
		(*props)[propName] = *item
	}
}

func setListProps(props *map[string]interface{}, itemList *[]string, propName string) {
	var items []string

	for _, item := range *itemList {
		items = append(items, item)
	}

	if len(items) > 0 {
		(*props)[propName] = items
	}
}

//Write - Writes an Organisation node
func (cd service) Write(thing interface{}) error {
	o := thing.(organisation)

	props := map[string]interface{}{
		"uuid":       o.UUID,
		"properName": o.ProperName,
		"prefLabel":  o.ProperName,
	}

	setProps(&props, &o.LegalName, "legalName")
	setProps(&props, &o.ShortName, "shortName")
	setProps(&props, &o.HiddenLabel, "hiddenLabel")
	setListProps(&props, &o.FormerNames, "formerNames")
	setListProps(&props, &o.LocalNames, "localNames")
	setListProps(&props, &o.TradeNames, "tradeNames")
	setListProps(&props, &o.Aliases, "aliases")

	deleteEntityRelationshipsQuery := &neoism.CypherQuery{
		Statement: `MATCH (o:Thing {uuid:{uuid}})
		OPTIONAL MATCH (o)-[hc:HAS_CLASSIFICATION]->(ic)
		OPTIONAL MATCH (o)-[soo:SUB_ORGANISATION_OF]->(p)
		OPTIONAL MATCH (o)<-[iden:IDENTIFIES]-(i)
		DELETE hc, soo, iden, i`,
		Parameters: map[string]interface{}{
			"uuid": o.UUID,
		},
	}

	queries := []*neoism.CypherQuery{deleteEntityRelationshipsQuery}

	resetOrgQuery := &neoism.CypherQuery{
		Statement: `MERGE (o:Thing {uuid: {uuid}})
					REMOVE o:PublicCompany:Company:Organisation:Concept
					SET o={props}`,
		Parameters: map[string]interface{}{
			"uuid":  o.UUID,
			"props": props,
		},
	}
	queries = append(queries, resetOrgQuery)

	identifierLabels := map[string]string{
		fsAuthority:  factsetIdentifierLabel,
		leiAuthority: leiIdentifierLabel,
		tmeAuthority: tmeIdentifierLabel,
	}
	for _, identifier := range o.Identifiers {

		if identifierLabels[identifier.Authority] == "" {
			return fmt.Errorf("This identifier type- %v, is not supported. Only FACTSET_EDM, LEI and FT-TME are currently supported", identifier.Authority)
		}
		addIdentfierQuery := addIdentifierQuery(identifier, o.UUID, identifierLabels[identifier.Authority])
		queries = append(queries, addIdentfierQuery)
	}

	err, stringType := o.Type.String()
	if err == nil {
		setTypeStatement := fmt.Sprintf(`MERGE (o:Thing {uuid: {uuid}})  set o : %s `, stringType)
		setTypeQuery := &neoism.CypherQuery{
			Statement: setTypeStatement,
			Parameters: map[string]interface{}{
				"uuid": o.UUID,
			},
		}
		queries = append(queries, setTypeQuery)

	} else {
		return err
	}

	if o.IndustryClassification != "" {

		industryClassQuery := &neoism.CypherQuery{
			Statement: "MERGE (o:Thing {uuid: {uuid}}) MERGE (ic:Thing{uuid: {indUuid}}) MERGE (o:Thing {uuid: {uuid}})-[:HAS_CLASSIFICATION]->(ic) ",
			Parameters: map[string]interface{}{
				"uuid":    o.UUID,
				"indUuid": o.IndustryClassification,
			},
		}
		queries = append(queries, industryClassQuery)
	}

	if o.ParentOrganisation != "" {
		parentQuery := &neoism.CypherQuery{
			Statement: "MERGE (o:Thing {uuid: {uuid}}) MERGE (p:Thing{uuid: {paUuid}}) MERGE (o)-[:SUB_ORGANISATION_OF]->(p) ",
			Parameters: map[string]interface{}{
				"uuid":   o.UUID,
				"paUuid": o.ParentOrganisation,
			},
		}
		queries = append(queries, parentQuery)
	}
	return cd.cypherRunner.CypherBatch(queries)
}

func addIdentifierQuery(identifier identifier, uuid string, identifierLabel string) *neoism.CypherQuery {

	statementTemplate := fmt.Sprintf(`MERGE (o:Thing {uuid:{uuid}})
					MERGE (i:Identifier {value:{value} , authority:{authority}})
					MERGE (o)<-[:IDENTIFIES]-(i)
					set i : %s `, identifierLabel)

	query := &neoism.CypherQuery{
		Statement: statementTemplate,
		Parameters: map[string]interface{}{
			"uuid":      uuid,
			"value":     identifier.IdentifierValue,
			"authority": identifier.Authority,
		},
	}
	return query
}

//Read - Internal Read of an Organisation
func (cd service) Read(uuid string) (interface{}, bool, error) {

	results := []struct {
		UUID          string       `json:"o.uuid"`
		Type          []string     `json:"type"`
		ProperName    string       `json:"o.properName"`
		LegalName     string       `json:"o.legalName"`
		ShortName     string       `json:"o.shortName"`
		HiddenLabel   string       `json:"o.hiddenLabel"`
		Identifiers   []identifier `json:"identifiers"`
		TradeNames    []string     `json:"o.tradeNames"`
		LocalNames    []string     `json:"o.localNames"`
		FormerNames   []string     `json:"o.formerNames"`
		Aliases       []string     `json:"o.aliases"`
		ParentOrgUUID string       `json:"par.uuid"`
		IndustryUUID  string       `json:"ind.uuid"`
	}{}

	readQuery := &neoism.CypherQuery{

		Statement: `MATCH (o:Organisation:Concept{uuid:{uuid}})
            OPTIONAL MATCH (o)-[:SUB_ORGANISATION_OF]->(par:Thing)
            OPTIONAL MATCH (o)-[:HAS_CLASSIFICATION]->(ind:Thing)
            OPTIONAL MATCH (o)<-[:IDENTIFIES]-(id:Identifier)
			with o, ind, par,  collect({authority:id.authority, identifierValue:id.value})as identifiers
            RETURN o.uuid , o.properName , labels(o) as Type, o.legalName, o.shortName, o.hiddenLabel,
            o.formerNames, o.tradeNames, o.localNames, o.aliases, ind.uuid, par.uuid, identifiers`,
		Parameters: map[string]interface{}{
			"uuid": uuid,
		},
		Result: &results,
	}

	if err := cd.cypherRunner.CypherBatch([]*neoism.CypherQuery{readQuery}); err != nil || len(results) == 0 {
		return organisation{}, false, err
	}

	result := results[0]

	o := organisation{
		UUID:                   result.UUID,
		ProperName:             result.ProperName,
		LegalName:              result.LegalName,
		ShortName:              result.ShortName,
		HiddenLabel:            result.HiddenLabel,
		TradeNames:             result.TradeNames,
		LocalNames:             result.LocalNames,
		FormerNames:            result.FormerNames,
		Identifiers:            result.Identifiers,
		Aliases:                result.Aliases,
		ParentOrganisation:     result.ParentOrgUUID,
		IndustryClassification: result.IndustryUUID,
	}

	addType(&o.Type, &result.Type)
	sortIdentifiers(o.Identifiers)

	if len(o.Identifiers) == 0 {
		o.Identifiers = make([]identifier, 0, 0)
	}

	return o, true, nil
}

func addType(orgType *OrgType, types *[]string) {
	i := len(*types)
	if i == 3 {
		*orgType = Organisation
	}
	if i == 4 {
		*orgType = Company
	}
	if i == 5 {
		*orgType = PublicCompany
	}
}

//Delete - Deletes an Organisation
func (pcd service) Delete(uuid string) (bool, error) {
	clearNode := &neoism.CypherQuery{
		Statement: `
			MATCH (org:Thing {uuid: {uuid}})
			OPTIONAL MATCH (p)<-[iden:IDENTIFIES]-(i:Identifier)
			REMOVE org:Concept:Organisation:Company:PublicCompany
			DELETE iden, i
			SET org={ uuid: {uuid}}
		`,
		Parameters: map[string]interface{}{
			"uuid": uuid,
		},
		IncludeStats: true,
	}
	qs := []*neoism.CypherQuery{
		clearNode,
		{
			Statement: `
		MATCH (org:Thing {uuid: {uuid}})
		OPTIONAL MATCH (org)-[a]-(x) WITH org, count(a) AS relCount WHERE relCount = 0
		DELETE org
		`,
			Parameters: map[string]interface{}{
				"uuid": uuid,
			},
		},
	}

	err := pcd.cypherRunner.CypherBatch(qs)

	s1, err := clearNode.Stats()

	if err != nil {
		return false, err
	}

	if s1.ContainsUpdates && s1.LabelsRemoved > 0 {
		return true, err
	}

	return false, err
}

func (s service) Check() error {
	return neoutils.Check(s.cypherRunner)
}

type countResult []struct {
	Count int `json:"c"`
}

func (s service) Count() (int, error) {

	results := countResult{}

	err := s.cypherRunner.CypherBatch([]*neoism.CypherQuery{{
		Statement: `MATCH (n:Organisation) return count(n) as c`,
		Result:    &results,
	}})

	if err != nil {
		return 0, err
	}

	return results[0].Count, nil
}

func (s service) DecodeJSON(dec *json.Decoder) (interface{}, string, error) {
	org := organisation{}
	err := dec.Decode(&org)
	return org, org.UUID, err
}

const (
	fsAuthority            = "http://api.ft.com/system/FACTSET-EDM"
	leiAuthority           = "http://api.ft.com/system/LEI"
	tmeAuthority           = "http://api.ft.com/system/FT-TME"
	factsetIdentifierLabel = "FactsetIdentifier"
	leiIdentifierLabel     = "LegalEntityIdentifier"
	tmeIdentifierLabel     = "TMEIdentifier"
)
<|endoftext|>


<commit_before>// Copyright 2017 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.

package widgets

import (
	"image"

	. "github.com/gizak/termui"
	rw "github.com/mattn/go-runewidth"
)

type List struct {
	Block
	Rows             []string
	WrapText         bool
	TextStyle        Style
	SelectedRow      uint
	topRow           uint
	SelectedRowStyle Style
}

func NewList() *List {
	return &List{
		Block:            *NewBlock(),
		TextStyle:        Theme.List.Text,
		SelectedRowStyle: Theme.List.Text,
	}
}

func (self *List) Draw(buf *Buffer) {
	self.Block.Draw(buf)

	point := self.Inner.Min

	if self.SelectedRow >= uint(self.Inner.Max.Y)+self.topRow-2 {
		self.topRow = self.SelectedRow - uint(self.Inner.Max.Y) + 2
	} else if self.SelectedRow < self.topRow {
		self.topRow = self.SelectedRow
	}

	for row := self.topRow; row < uint(len(self.Rows)) && point.Y < self.Inner.Max.Y; row++ {
		cells := ParseText(self.Rows[row], self.TextStyle)
		if self.WrapText {
			cells = WrapCells(cells, uint(self.Inner.Dx()))
		}
		for j := 0; j < len(cells) && point.Y < self.Inner.Max.Y; j++ {
			style := cells[j].Style
			if row == self.SelectedRow {
				style = self.SelectedRowStyle
			}
			if cells[j].Rune == '\n' {
				point = image.Pt(self.Inner.Min.X, point.Y+1)
			} else {
				if point.X+1 == self.Inner.Max.X+1 && len(cells) > self.Inner.Dx() {
					buf.SetCell(NewCell(ELLIPSES, style), point.Add(image.Pt(-1, 0)))
					break
				} else {
					buf.SetCell(NewCell(cells[j].Rune, style), point)
					point = point.Add(image.Pt(rw.RuneWidth(cells[j].Rune), 0))
				}
			}
		}
		point = image.Pt(self.Inner.Min.X, point.Y+1)
	}

	if self.topRow > 0 {
		buf.SetCell(
			NewCell(UP_ARROW, NewStyle(ColorWhite)),
			image.Pt(self.Inner.Max.X-1, self.Inner.Min.Y),
		)
	}
	if len(self.Rows) > int(self.topRow)+self.Inner.Dy() {
		buf.SetCell(
			NewCell(DOWN_ARROW, NewStyle(ColorWhite)),
			image.Pt(self.Inner.Max.X-1, self.Inner.Max.Y-1),
		)
	}
}

// ScrollAmount scrolls by amount given. If amount is < 0, then scroll up.
// There is no need to set self.topRow, as this will be set automatically when drawn,
// since if the selected item is off screen then the topRow variable will change accordingly.
func (self *List) ScrollAmount(amount int) {
	if len(self.Rows)-int(self.SelectedRow) <= amount {
		self.SelectedRow = uint(len(self.Rows) - 1)
	} else if int(self.SelectedRow)+amount < 0 {
		self.SelectedRow = 0
	} else {
		self.SelectedRow += uint(amount)
	}
}

func (self *List) ScrollUp() {
	self.ScrollAmount(-1)
}

func (self *List) ScrollDown() {
	self.ScrollAmount(1)
}

// PageUp scrolls up one whole page.
func (self *List) PageUp() {
	// If an item is selected below top row, then go to the top row.
	if self.SelectedRow > self.topRow {
		self.SelectedRow = self.topRow
	} else {
		self.ScrollAmount(-self.Inner.Dy())
	}
}

// PageDown scolls down one whole page.
func (self *List) PageDown() {
	self.ScrollAmount(self.Inner.Dy())
}

func (self *List) HalfPageUp() {
	self.ScrollAmount(-int(FloorFloat64(float64(self.Inner.Dy()) / 2)))
}

func (self *List) HalfPageDown() {
	self.ScrollAmount(int(FloorFloat64(float64(self.Inner.Dy()) / 2)))
}

func (self *List) ScrollTop() {
	self.SelectedRow = 0
}

func (self *List) ScrollBottom() {
	self.SelectedRow = uint(len(self.Rows) - 1)
}
<commit_msg>Formatting<commit_after>// Copyright 2017 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.

package widgets

import (
	"image"

	rw "github.com/mattn/go-runewidth"

	. "github.com/gizak/termui"
)

type List struct {
	Block
	Rows             []string
	WrapText         bool
	TextStyle        Style
	SelectedRow      uint
	topRow           uint
	SelectedRowStyle Style
}

func NewList() *List {
	return &List{
		Block:            *NewBlock(),
		TextStyle:        Theme.List.Text,
		SelectedRowStyle: Theme.List.Text,
	}
}

func (self *List) Draw(buf *Buffer) {
	self.Block.Draw(buf)

	point := self.Inner.Min

	if self.SelectedRow >= uint(self.Inner.Max.Y)+self.topRow-2 {
		self.topRow = self.SelectedRow - uint(self.Inner.Max.Y) + 2
	} else if self.SelectedRow < self.topRow {
		self.topRow = self.SelectedRow
	}

	for row := self.topRow; row < uint(len(self.Rows)) && point.Y < self.Inner.Max.Y; row++ {
		cells := ParseText(self.Rows[row], self.TextStyle)
		if self.WrapText {
			cells = WrapCells(cells, uint(self.Inner.Dx()))
		}
		for j := 0; j < len(cells) && point.Y < self.Inner.Max.Y; j++ {
			style := cells[j].Style
			if row == self.SelectedRow {
				style = self.SelectedRowStyle
			}
			if cells[j].Rune == '\n' {
				point = image.Pt(self.Inner.Min.X, point.Y+1)
			} else {
				if point.X+1 == self.Inner.Max.X+1 && len(cells) > self.Inner.Dx() {
					buf.SetCell(NewCell(ELLIPSES, style), point.Add(image.Pt(-1, 0)))
					break
				} else {
					buf.SetCell(NewCell(cells[j].Rune, style), point)
					point = point.Add(image.Pt(rw.RuneWidth(cells[j].Rune), 0))
				}
			}
		}
		point = image.Pt(self.Inner.Min.X, point.Y+1)
	}

	if self.topRow > 0 {
		buf.SetCell(
			NewCell(UP_ARROW, NewStyle(ColorWhite)),
			image.Pt(self.Inner.Max.X-1, self.Inner.Min.Y),
		)
	}
	if len(self.Rows) > int(self.topRow)+self.Inner.Dy() {
		buf.SetCell(
			NewCell(DOWN_ARROW, NewStyle(ColorWhite)),
			image.Pt(self.Inner.Max.X-1, self.Inner.Max.Y-1),
		)
	}
}

// ScrollAmount scrolls by amount given. If amount is < 0, then scroll up.
// There is no need to set self.topRow, as this will be set automatically when drawn,
// since if the selected item is off screen then the topRow variable will change accordingly.
func (self *List) ScrollAmount(amount int) {
	if len(self.Rows)-int(self.SelectedRow) <= amount {
		self.SelectedRow = uint(len(self.Rows) - 1)
	} else if int(self.SelectedRow)+amount < 0 {
		self.SelectedRow = 0
	} else {
		self.SelectedRow += uint(amount)
	}
}

func (self *List) ScrollUp() {
	self.ScrollAmount(-1)
}

func (self *List) ScrollDown() {
	self.ScrollAmount(1)
}

// PageUp scrolls up one whole page.
func (self *List) PageUp() {
	// If an item is selected below top row, then go to the top row.
	if self.SelectedRow > self.topRow {
		self.SelectedRow = self.topRow
	} else {
		self.ScrollAmount(-self.Inner.Dy())
	}
}

// PageDown scolls down one whole page.
func (self *List) PageDown() {
	self.ScrollAmount(self.Inner.Dy())
}

func (self *List) HalfPageUp() {
	self.ScrollAmount(-int(FloorFloat64(float64(self.Inner.Dy()) / 2)))
}

func (self *List) HalfPageDown() {
	self.ScrollAmount(int(FloorFloat64(float64(self.Inner.Dy()) / 2)))
}

func (self *List) ScrollTop() {
	self.SelectedRow = 0
}

func (self *List) ScrollBottom() {
	self.SelectedRow = uint(len(self.Rows) - 1)
}
<|endoftext|>


<commit_before>package version

import (
	"os"
	"strings"
	"time"

	"github.com/blang/semver"
	"github.com/drausin/libri/libri/common/errors"
)

// Current contains the current build info.
var Current BuildInfo

// these variables are populated by ldflags during builds and fall back to population from git repo
// when they're not set (e.g., during tests)
var (
	// GitBranch is the current git branch
	GitBranch string

	// GitRevision is the current git commit hash.
	GitRevision string

	// BuildDate is the date of the build.
	BuildDate string
)

var semverString = "0.2.0"

const (
	develop         = "develop"
	master          = "master"
	snapshot        = "snapshot"
	buildDateFormat = "2006-01-02" // ISO 8601 date format
)

var branchPrefixes = []string{
	"feature/",
	"release/",
	"bugfix/",
}

// BuildInfo contains info about the current build.
type BuildInfo struct {
	Version     semver.Version
	GitBranch   string
	GitRevision string
	BuildDate   string
}

func init() {
	wd, err := os.Getwd()
	errors.MaybePanic(err)
	g := git{dir: wd}

	if GitBranch == "" {
		GitBranch = g.Branch()
	}
	if GitRevision == "" {
		GitRevision, err = g.Commit()
		errors.MaybePanic(err)
	}
	if BuildDate == "" {
		BuildDate = time.Now().UTC().Format(buildDateFormat)
	}
	Version := semver.MustParse(semverString)
	if GitBranch == master {
		// no pre-release tags to add
	} else if GitBranch == develop {
		Version.Pre = []semver.PRVersion{{VersionStr: snapshot}}
	} else {
		Version.Pre = []semver.PRVersion{{VersionStr: stripPrefixes(GitBranch)}}
	}
	Current = BuildInfo{
		Version:     Version,
		GitBranch:   GitBranch,
		GitRevision: GitRevision,
		BuildDate:   BuildDate,
	}
}

func stripPrefixes(branch string) string {
	for _, prefix := range branchPrefixes {
		if strings.HasPrefix(branch, prefix) {
			return strings.TrimPrefix(branch, prefix)
		}
	}
	return branch
}
<commit_msg>bump to next (in progress) version<commit_after>package version

import (
	"os"
	"strings"
	"time"

	"github.com/blang/semver"
	"github.com/drausin/libri/libri/common/errors"
)

// Current contains the current build info.
var Current BuildInfo

// these variables are populated by ldflags during builds and fall back to population from git repo
// when they're not set (e.g., during tests)
var (
	// GitBranch is the current git branch
	GitBranch string

	// GitRevision is the current git commit hash.
	GitRevision string

	// BuildDate is the date of the build.
	BuildDate string
)

var semverString = "0.3.0"

const (
	develop         = "develop"
	master          = "master"
	snapshot        = "snapshot"
	buildDateFormat = "2006-01-02" // ISO 8601 date format
)

var branchPrefixes = []string{
	"feature/",
	"release/",
	"bugfix/",
}

// BuildInfo contains info about the current build.
type BuildInfo struct {
	Version     semver.Version
	GitBranch   string
	GitRevision string
	BuildDate   string
}

func init() {
	wd, err := os.Getwd()
	errors.MaybePanic(err)
	g := git{dir: wd}

	if GitBranch == "" {
		GitBranch = g.Branch()
	}
	if GitRevision == "" {
		GitRevision, err = g.Commit()
		errors.MaybePanic(err)
	}
	if BuildDate == "" {
		BuildDate = time.Now().UTC().Format(buildDateFormat)
	}
	Version := semver.MustParse(semverString)
	if GitBranch == master {
		// no pre-release tags to add
	} else if GitBranch == develop {
		Version.Pre = []semver.PRVersion{{VersionStr: snapshot}}
	} else {
		Version.Pre = []semver.PRVersion{{VersionStr: stripPrefixes(GitBranch)}}
	}
	Current = BuildInfo{
		Version:     Version,
		GitBranch:   GitBranch,
		GitRevision: GitRevision,
		BuildDate:   BuildDate,
	}
}

func stripPrefixes(branch string) string {
	for _, prefix := range branchPrefixes {
		if strings.HasPrefix(branch, prefix) {
			return strings.TrimPrefix(branch, prefix)
		}
	}
	return branch
}
<|endoftext|>


<commit_before>// Tideland Go REST Server Library - REST - Path
//
// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.

package rest

//--------------------
// IMPORTS
//--------------------

import (
	"net/http"

	"github.com/tideland/golib/stringex"
)

//--------------------
// CONSTANTS
//--------------------

// Path indexes for the different parts.
const (
	PathDomain     = 0
	PathResource   = 1
	PathResourceID = 2
)

//--------------------
// PATH
//--------------------

// Path provides access to the parts of a
// request path interesting for handling a
// job.
type Path interface {
	// Length returns the number of parts of the path.
	Length() int

	// Part returns the parts of the URL path based on the
	// index or an empty string.
	Part(index int) string

	// Domain returns the requests domain.
	Domain() string

	// Resource returns the requests resource.
	Resource() string

	// ResourceID return the requests resource ID.
	ResourceID() string
}

// path implements Path.
type path struct {
	parts []string
}

// newPath returns the analyzed path.
func newPath(env *environment, r *http.Request) *path {
	parts := stringex.SplitMap(r.URL.Path, "/", func(p string) (string, bool) {
		if part == "" {
			return "", false
		}
		return part, true
	})[env.basepartsLen:]
	switch len(parts) {
	case 1:
		parts = append(parts, env.defaultResource)
	case 0:
		parts = append(parts, env.defaultDomain, nev.defaultResource)
	}
	return &path{
		parts: parts,
	}
}

// EOF
<commit_msg>Continued path implementation<commit_after>// Tideland Go REST Server Library - REST - Path
//
// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.

package rest

//--------------------
// IMPORTS
//--------------------

import (
	"net/http"
	"strings"

	"github.com/tideland/golib/stringex"
)

//--------------------
// CONSTANTS
//--------------------

// Path indexes for the different parts.
const (
	PathDomain     = 0
	PathResource   = 1
	PathResourceID = 2
)

//--------------------
// PATH
//--------------------

// Path provides access to the parts of a
// request path interesting for handling a
// job.
type Path interface {
	// Length returns the number of parts of the path.
	Length() int

	// Part returns the parts of the URL path based on the
	// index or an empty string.
	Part(index int) string

	// Domain returns the requests domain.
	Domain() string

	// Resource returns the requests resource.
	Resource() string

	// ResourceID return the requests resource ID.
	ResourceID() string
}

// path implements Path.
type path struct {
	parts []string
}

// newPath returns the analyzed path.
func newPath(env *environment, r *http.Request) *path {
	parts := stringex.SplitMap(r.URL.Path, "/", func(p string) (string, bool) {
		if part == "" {
			return "", false
		}
		return part, true
	})[env.basepartsLen:]
	switch len(parts) {
	case 1:
		parts = append(parts, env.defaultResource)
	case 0:
		parts = append(parts, env.defaultDomain, nev.defaultResource)
	}
	return &path{
		parts: parts,
	}
}

// Length implements Path.
func (p *path) Length() int {
	return len(p.parts)
}

// Part implements Path.
func (p *path) Part(index int) string {
	if len(p.parts) <= index {
		return ""
	}
	return p.parts[index]
}

// Domain implements Path.
func (p *path) Domain() string {
	return p.parts[PathDomain]
}

// Resource implements Path.
func (p *path) Resource() string {
	return p.parts[PathResource]
}

// ResourceID implements Path.
func (p *path) ResourceID() string {
	if len(p.parts) > 2 {
		return strings.Join(p.parts[PathResourceID:], "/")
	}
	return ""
}

// EOF
<|endoftext|>