text:
ANSIBLE_METADATA = {'status': ['preview'],
                    'supported_by': 'community',
                    'version': '1.0'}

DOCUMENTATION = '''
---
module: vmware_guest
short_description: Manages virtualmachines in vcenter
description:
    - Uses pyvmomi to ...
    - copy a template to a new virtualmachine
    - poweron/poweroff/restart a virtualmachine
    - remove a virtualmachine
version_added: 2.2
author: James Tanner (@jctanner) <tanner.jc@gmail.com>
notes:
    - Tested on vSphere 6.0
requirements:
    - "python >= 2.6"
    - PyVmomi
options:
   state:
        description:
            - What state should the virtualmachine be in?
        required: True
        choices: ['present', 'absent', 'poweredon', 'poweredoff', 'restarted', 'suspended']
   name:
        description:
            - Name of the newly deployed guest
        required: True
   name_match:
        description:
            - If multiple vms matching the name, use the first or last found
        required: False
        default: 'first'
        choices: ['first', 'last']
   uuid:
        description:
            - UUID of the instance to manage if known, this is vmware's unique identifier.
            - This is required if name is not supplied.
        required: False
   template:
        description:
            - Name of the template to deploy, if needed to create the guest (state=present).
            - If the guest exists already this setting will be ignored.
        required: False
   folder:
        description:
            - Destination folder path for the new guest
        required: False
   hardware:
        description:
            - Attributes such as cpus, memory, osid, and disk controller
        required: False
   disk:
        description:
            - A list of disks to add
        required: False
   nic:
        description:
            - A list of nics to add
        required: False
   wait_for_ip_address:
        description:
            - Wait until vcenter detects an IP address for the guest
        required: False
   force:
        description:
            - Ignore warnings and complete the actions
        required: False
   datacenter:
        description:
            - Destination datacenter for the deploy operation
        required: True
   esxi_hostname:
        description:
            - The esxi hostname where the VM will run.
        required: False
   annotation:
        description:
            - A note or annotation to include in the VM
        required: False
        version_added: "2.3"
   customize:
        description:
           - Should customization spec be run
        required: False
        version_added: "2.3"
   ips:
        description:
           - IP Addresses to set
        required: False
        version_added: "2.3"
   networks:
        description:
          - Network to use should include VM network name and gateway
        required: False
        version_added: "2.3"
   dns_servers:
        description:
          - DNS servers to use
        required: False
        version_added: "2.3"
   domain:
        description:
          - Domain to use while customizing
        required: False
        version_added: "2.3"
   snapshot_op:
        description:
          - A key, value pair of snapshot operation types and their additional required parameters.
        required: False
        version_added: "2.3"
extends_documentation_fragment: vmware.documentation
'''

EXAMPLES = '''
Example from Ansible playbook
#
# Create a VM from a template
#
    - name: create the VM
      vmware_guest:
        validate_certs: False
        hostname: 192.0.2.44
        username: administrator@vsphere.local
        password: vmware
        name: testvm_2
        state: poweredon
        folder: testvms
        disk:
            - size_gb: 10
              type: thin
              datastore: g73_datastore
        nic:
            - type: vmxnet3
              network: VM Network
              network_type: standard
        hardware:
            memory_mb: 512
            num_cpus: 1
            osid: centos64guest
            scsi: paravirtual
        datacenter: datacenter1
        esxi_hostname: 192.0.2.117
        template: template_el7
        wait_for_ip_address: yes
      register: deploy

#
# Clone Template and customize
#
   - name: Clone template and customize
     vmware_guest:
       hostname: "192.168.1.209"
       username: "administrator@vsphere.local"
       password: "vmware"
       validate_certs: False
       name: testvm-2
       datacenter: datacenter1
       cluster: cluster
       validate_certs: False
       template: template_el7
       customize: True
       domain: "example.com"
       dns_servers: ['192.168.1.1','192.168.1.2']
       ips: "192.168.1.100"
       networks:
         '192.168.1.0/24':
           network: 'VM Network'
           gateway: '192.168.1.1'
#
# Gather facts only
#
    - name: gather the VM facts
      vmware_guest:
        validate_certs: False
        hostname: 192.168.1.209
        username: administrator@vsphere.local
        password: vmware
        name: testvm_2
        esxi_hostname: 192.168.1.117
      register: facts

### Snapshot Operations
# Create snapshot
  - vmware_guest:
     hostname: 192.168.1.209
     username: administrator@vsphere.local
     password: vmware
     validate_certs: False
     name: dummy_vm
     snapshot_op:
         op_type: create
         name: snap1
         description: snap1_description

# Remove a snapshot
  - vmware_guest:
     hostname: 192.168.1.209
     username: administrator@vsphere.local
     password: vmware
     validate_certs: False
     name: dummy_vm
     snapshot_op:
         op_type: remove
         name: snap1

# Revert to a snapshot
  - vmware_guest:
     hostname: 192.168.1.209
     username: administrator@vsphere.local
     password: vmware
     validate_certs: False
     name: dummy_vm
     snapshot_op:
         op_type: revert
         name: snap1

# List all snapshots of a VM
  - vmware_guest:
     hostname: 192.168.1.209
     username: administrator@vsphere.local
     password: vmware
     validate_certs: False
     name: dummy_vm
     snapshot_op:
         op_type: list_all

# List current snapshot of a VM
  - vmware_guest:
     hostname: 192.168.1.209
     username: administrator@vsphere.local
     password: vmware
     validate_certs: False
     name: dummy_vm
     snapshot_op:
         op_type: list_current

# Remove all snapshots of a VM
  - vmware_guest:
     hostname: 192.168.1.209
     username: administrator@vsphere.local
     password: vmware
     validate_certs: False
     name: dummy_vm
     snapshot_op:
         op_type: remove_all
'''

RETURN = """
instance:
    descripton: metadata about the new virtualmachine
    returned: always
    type: dict
    sample: None
"""

try:
    import json
except ImportError:
    import simplejson as json

HAS_PYVMOMI = False
try:
    import pyVmomi
    from pyVmomi import vim
    HAS_PYVMOMI = True
except ImportError:
    pass

import os
import time
from netaddr import IPNetwork, IPAddress

from ansible.module_utils.urls import fetch_url

class PyVmomiHelper(object):

    def __init__(self, module):

        if not HAS_PYVMOMI:
            module.fail_json(msg='pyvmomi module required')

        self.module = module
        self.params = module.params
        self.si = None
        self.smartconnect()
        self.datacenter = None
        self.folders = None
        self.foldermap = None

    def smartconnect(self):
        self.content = connect_to_api(self.module)

    def _build_folder_tree(self, folder, tree={}, treepath=None):

        tree = {'virtualmachines': [],
                        'subfolders': {},
                        'vimobj': folder,
                        'name': folder.name}

        children = None
        if hasattr(folder, 'childEntity'):
            children = folder.childEntity

        if children:
            for child in children:
                if child == folder or child in tree:
                    continue
                if isinstance(child, vim.Folder):
                    ctree = self._build_folder_tree(child)
                    tree['subfolders'][child] = dict.copy(ctree)
                elif isinstance(child, vim.VirtualMachine):
                    tree['virtualmachines'].append(child)
        else:
            if isinstance(folder, vim.VirtualMachine):
                return folder
        return tree

    def _build_folder_map(self, folder, vmap={}, inpath='/'):

        ''' Build a searchable index for vms+uuids+folders '''

        if isinstance(folder, tuple):
            folder = folder[1]

        if not 'names' in vmap:
            vmap['names'] = {}
        if not 'uuids' in vmap:
            vmap['uuids'] = {}
        if not 'paths' in vmap:
            vmap['paths'] = {}

        if inpath == '/':
            thispath = '/vm'
        else:
            thispath = os.path.join(inpath, folder['name'])

        if thispath not in vmap['paths']:
            vmap['paths'][thispath] = []

        # helpful for isolating folder objects later on
        if not 'path_by_fvim' in vmap:
            vmap['path_by_fvim'] = {}
        if not 'fvim_by_path' in vmap:
            vmap['fvim_by_path'] = {}
        # store object by path and store path by object
        vmap['fvim_by_path'][thispath] = folder['vimobj']
        vmap['path_by_fvim'][folder['vimobj']] = thispath

        # helpful for isolating vm objects later on
        if not 'path_by_vvim' in vmap:
            vmap['path_by_vvim'] = {}
        if not 'vvim_by_path' in vmap:
            vmap['vvim_by_path'] = {}
        if thispath not in vmap['vvim_by_path']:
            vmap['vvim_by_path'][thispath] = []

        for item in folder.items():
            k = item[0]
            v = item[1]

            if k == 'name':
                pass
            elif k == 'subfolders':
                for x in v.items():
                    vmap = self._build_folder_map(x, vmap=vmap, inpath=thispath)
            elif k == 'virtualmachines':
                for x in v:
                    if not x.config.name in vmap['names']:
                        vmap['names'][x.config.name] = []
                    vmap['names'][x.config.name].append(x.config.uuid)
                    vmap['uuids'][x.config.uuid] = x.config.name
                    vmap['paths'][thispath].append(x.config.uuid)

                    if x not in vmap['vvim_by_path'][thispath]:
                        vmap['vvim_by_path'][thispath].append(x)
                    if x not in vmap['path_by_vvim']:
                        vmap['path_by_vvim'][x] = thispath
        return vmap

    def getfolders(self):

        if not self.datacenter:
            self.get_datacenter()
        self.folders = self._build_folder_tree(self.datacenter.vmFolder)
        self.folder_map = self._build_folder_map(self.folders)
        return (self.folders, self.folder_map)

    def compile_folder_path_for_object(self, vobj):
        ''' make a /vm/foo/bar/baz like folder path for an object '''
        paths = []
        if isinstance(vobj, vim.Folder):
            paths.append(vobj.name)

        thisobj = vobj
        while hasattr(thisobj, 'parent'):
            thisobj = thisobj.parent
            if isinstance(thisobj, vim.Folder):
                paths.append(thisobj.name)
        paths.reverse()
        if paths[0] == 'Datacenters':
            paths.remove('Datacenters')
        return '/' + '/'.join(paths)

    def get_datacenter(self):
        self.datacenter = get_obj(self.content, [vim.Datacenter],
                                   self.params['datacenter'])

    def getvm(self, name=None, uuid=None, folder=None, name_match=None):

        # https://www.vmware.com/support/developer/vc-sdk/visdk2xpubs/ReferenceGuide/vim.SearchIndex.html
        # self.si.content.searchIndex.FindByInventoryPath('DC1/vm/test_folder')

        vm = None
        folder_path = None
        searchpath = None

        if uuid:
            vm = self.content.searchIndex.FindByUuid(uuid=uuid, vmSearch=True)

        elif folder:

            if self.params['folder'].endswith('/'):
                self.params['folder'] = self.params['folder'][0:-1]

            # Build the absolute folder path to pass into the search method
            if self.params['folder'].startswith('/vm'):
                searchpath = '%s' % self.params['datacenter']
                searchpath += self.params['folder']
            elif self.params['folder'].startswith('/'):
                searchpath = '%s' % self.params['datacenter']
                searchpath += '/vm' + self.params['folder']
            else:
                # need to look for matching absolute path
                if not self.folders:
                    self.getfolders()
                paths = self.folder_map['paths'].keys()
                paths = [x for x in paths if x.endswith(self.params['folder'])]
                if len(paths) > 1:
                    self.module.fail_json(msg='%s matches more than one folder. Please use the absolute path starting with /vm/' % self.params['folder'])
                elif paths:
                    searchpath = paths[0]

            if searchpath:
                # get all objects for this path ...
                fObj = self.content.searchIndex.FindByInventoryPath(searchpath)
                if fObj:
                    if isinstance(fObj, vim.Datacenter):
                        fObj = fObj.vmFolder
                    for cObj in fObj.childEntity:
                        if not isinstance(cObj, vim.VirtualMachine):
                            continue
                        if cObj.name == name:
                            vm = cObj
                            break

        if not vm:

            # FIXME - this is unused if folder has a default value
            vmList = get_all_objs(self.content, [vim.VirtualMachine])

            # narrow down by folder
            if folder:
                if not self.folders:
                    self.getfolders()

                # compare the folder path of each VM against the search path
                for item in vmList.items():
                    vobj = item[0]
                    if not isinstance(vobj.parent, vim.Folder):
                        continue
                    if self.compile_folder_path_for_object(vobj) == searchpath:
                        return vobj

            if name_match:
                if name_match == 'first':
                    vm = get_obj(self.content, [vim.VirtualMachine], name)
                elif name_match == 'last':
                    matches = []
                    vmList = get_all_objs(self.content, [vim.VirtualMachine])
                    for thisvm in vmList:
                        if thisvm.config.name == name:
                            matches.append(thisvm)
                    if matches:
                        vm = matches[-1]
            else:
                matches = []
                vmList = get_all_objs(self.content, [vim.VirtualMachine])
                for thisvm in vmList:
                    if thisvm.config.name == name:
                        matches.append(thisvm)
                    if len(matches) > 1:
                        module.fail_json(msg='more than 1 vm exists by the name %s. Please specify a uuid, or a folder, or a datacenter or name_match' % name)
                    if matches:
                        vm = matches[0]

        return vm

    def set_powerstate(self, vm, state, force):
        """
        Set the power status for a VM determined by the current and
        requested states. force is forceful
        """
        facts = self.gather_facts(vm)
        expected_state = state.replace('_', '').lower()
        current_state = facts['hw_power_status'].lower()
        result = {}

        # Need Force
        if not force and current_state not in ['poweredon', 'poweredoff']:
            return "VM is in %s power state. Force is required!" % current_state

        # State is already true
        if current_state == expected_state:
            result['changed'] = False
            result['failed'] = False
        else:
            task = None
            try:
                if expected_state == 'poweredoff':
                    task = vm.PowerOff()

                elif expected_state == 'poweredon':
                    task = vm.PowerOn()

                elif expected_state == 'restarted':
                    if current_state in ('poweredon', 'poweringon', 'resetting'):
                        task = vm.Reset()
                    else:
                        result = {'changed': False, 'failed': True,
                                  'msg': "Cannot restart VM in the current state %s" % current_state}

            except Exception:
                result = {'changed': False, 'failed': True,
                          'msg': get_exception()}

            if task:
                self.wait_for_task(task)
                if task.info.state == 'error':
                    result = {'changed': False, 'failed': True, 'msg': task.info.error.msg}
                else:
                    result = {'changed': True, 'failed': False}

        # need to get new metadata if changed
        if result['changed']:
            newvm = self.getvm(uuid=vm.config.uuid)
            facts = self.gather_facts(newvm)
            result['instance'] = facts
        return result

    def gather_facts(self, vm):

        ''' Gather facts from vim.VirtualMachine object. '''

        facts = {
            'module_hw': True,
            'hw_name': vm.config.name,
            'hw_power_status': vm.summary.runtime.powerState,
            'hw_guest_full_name':  vm.summary.guest.guestFullName,
            'hw_guest_id': vm.summary.guest.guestId,
            'hw_product_uuid': vm.config.uuid,
            'hw_processor_count': vm.config.hardware.numCPU,
            'hw_memtotal_mb': vm.config.hardware.memoryMB,
            'hw_interfaces':[],
            'ipv4': None,
            'ipv6': None,
        }

        netDict = {}
        for device in vm.guest.net:
            mac = device.macAddress
            ips = list(device.ipAddress)
            netDict[mac] = ips
        for k,v in netDict.iteritems():
            for ipaddress in v:
                if ipaddress:
                    if '::' in ipaddress:
                        facts['ipv6'] = ipaddress
                    else:
                        facts['ipv4'] = ipaddress

        for idx,entry in enumerate(vm.config.hardware.device):
            if not hasattr(entry, 'macAddress'):
                continue

            factname = 'hw_eth' + str(idx)
            facts[factname] = {
                'addresstype': entry.addressType,
                'label': entry.deviceInfo.label,
                'macaddress': entry.macAddress,
                'ipaddresses': netDict.get(entry.macAddress, None),
                'macaddress_dash': entry.macAddress.replace(':', '-'),
                'summary': entry.deviceInfo.summary,
            }
            facts['hw_interfaces'].append('eth'+str(idx))

        return facts

    def remove_vm(self, vm):
        # https://www.vmware.com/support/developer/converter-sdk/conv60_apireference/vim.ManagedEntity.html#destroy
        task = vm.Destroy()
        self.wait_for_task(task)

        if task.info.state == 'error':
            return ({'changed': False, 'failed': True, 'msg': task.info.error.msg})
        else:
            return ({'changed': True, 'failed': False})

    def deploy_template(self, poweron=False, wait_for_ip=False):

        # https://github.com/vmware/pyvmomi-community-samples/blob/master/samples/clone_vm.py
        # https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.vm.CloneSpec.html
        # https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.vm.ConfigSpec.html
        # https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html

        # FIXME:
        #   - clusters
        #   - multiple datacenters
        #   - resource pools
        #   - multiple templates by the same name
        #   - multiple disks
        #   - changing the esx host is ignored?
        #   - static IPs

        # FIXME: need to search for this in the same way as guests to ensure accuracy
        template = get_obj(self.content, [vim.VirtualMachine], self.params['template'])
        if not template:
            self.module.fail_json(msg="Could not find a template named %s" % self.params['template'])

        datacenters = get_all_objs(self.content, [vim.Datacenter])
        datacenter = get_obj(self.content, [vim.Datacenter],
                             self.params['datacenter'])
        if not datacenter:
            self.module.fail_json(msg='No datacenter named %s was found' % self.params['datacenter'])

        if not self.foldermap:
            self.folders, self.foldermap = self.getfolders()

        # find matching folders
        if self.params['folder'].startswith('/'):
            folders = [x for x in self.foldermap['fvim_by_path'].items() if x[0] == self.params['folder']]
        else:
            folders = [x for x in self.foldermap['fvim_by_path'].items() if x[0].endswith(self.params['folder'])]

        # throw error if more than one match or no matches
        if len(folders) == 0:
            self.module.fail_json(msg='no folder matched the path: %s' % self.params['folder'])
        elif len(folders) > 1:
            self.module.fail_json(msg='too many folders matched "%s", please give the full path starting with /vm/' % self.params['folder'])

        # grab the folder vim object
        destfolder = folders[0][1]

        # if the user wants a cluster, get the list of hosts for the cluster and use the first one
        if self.params['cluster']:
            cluster = get_obj(self.content, [vim.ClusterComputeResource], self.params['cluster'])
            if not cluster:
                self.module.fail_json(msg="Failed to find a cluster named %s" % self.params['cluster'])
            #resource_pool = cluster.resourcePool
            hostsystems = [x for x in cluster.host]
            hostsystem = hostsystems[0]
        else:
            hostsystem = get_obj(self.content, [vim.HostSystem], self.params['esxi_hostname'])
            if not hostsystem:
                self.module.fail_json(msg="Failed to find a host named %s" % self.params['esxi_hostname'])

        # set the destination datastore in the relocation spec
        datastore_name = None
        datastore = None
        if self.params['disk']:
            if 'datastore' in self.params['disk'][0]:
                datastore_name = self.params['disk'][0]['datastore']
                datastore = get_obj(self.content, [vim.Datastore], datastore_name)
        if not datastore:
            # use the template's existing DS
            disks = [x for x in template.config.hardware.device if isinstance(x, vim.vm.device.VirtualDisk)]
            datastore = disks[0].backing.datastore
            datastore_name = datastore.name
        if not datastore:
            self.module.fail_json(msg="Failed to find a matching datastore")

        # create the relocation spec
        relospec = vim.vm.RelocateSpec()
        relospec.host = hostsystem
        relospec.datastore = datastore

        # Find the associated resourcepool for the host system
        #   * FIXME: find resourcepool for clusters too
        resource_pool = None
        resource_pools = get_all_objs(self.content, [vim.ResourcePool])
        for rp in resource_pools.items():
            if not rp[0]:
                continue
            if not hasattr(rp[0], 'parent'):
                continue
            if rp[0].parent == hostsystem.parent:
                resource_pool = rp[0]
                break
        if resource_pool:
            relospec.pool = resource_pool
        else:
            self.module.fail_json(msg="Failed to find a resource group for %s" \
                                  % hostsystem.name)

        clonespec_kwargs = {}
        clonespec_kwargs['location'] = relospec

        # create disk spec if not default
        if self.params['disk']:
            # grab the template's first disk and modify it for this customization
            disks = [x for x in template.config.hardware.device if isinstance(x, vim.vm.device.VirtualDisk)]
            diskspec = vim.vm.device.VirtualDeviceSpec()
            # set the operation to edit so that it knows to keep other settings
            diskspec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit
            diskspec.device = disks[0]

            # get the first disk attributes
            pspec = self.params.get('disk')[0]

            # is it thin?
            if pspec.get('type', '').lower() == 'thin':
                diskspec.device.backing.thinProvisioned = True

            # which datastore?
            if pspec.get('datastore'):
                # This is already handled by the relocation spec,
                # but it needs to eventually be handled for all the
                # other disks defined
                pass

            # what size is it?
            if [x for x in pspec.keys() if x.startswith('size_') or x == 'size']:
                # size_tb, size_gb, size_mb, size_kb, size_b ...?
                if 'size' in pspec:
                    expected = ''.join(c for c in pspec['size'] if c.isdigit())
                    unit = pspec['size'].replace(expected, '').lower()
                    expected = int(expected)
                else:
                    param = [x for x in pspec.keys() if x.startswith('size_')][0]
                    unit = param.split('_')[-1].lower()
                    expected = [x[1] for x in pspec.items() if x[0].startswith('size_')][0]
                    expected = int(expected)

                kb = None
                if unit == 'tb':
                    kb = expected * 1024 * 1024 * 1024
                elif unit == 'gb':
                    kb = expected * 1024 * 1024
                elif unit ==' mb':
                    kb = expected * 1024
                elif unit == 'kb':
                    kb = expected
                else:
                    self.module.fail_json(msg='%s is not a supported unit for disk size' % unit)
                diskspec.device.capacityInKB = kb

            # tell the configspec that the disk device needs to change
            configspec = vim.vm.ConfigSpec(deviceChange=[diskspec])
            clonespec_kwargs['config'] = configspec

        # set cpu/memory/etc
        if 'hardware' in self.params:
            if not 'config' in clonespec_kwargs:
                clonespec_kwargs['config'] = vim.vm.ConfigSpec()
            if 'num_cpus' in self.params['hardware']:
                clonespec_kwargs['config'].numCPUs = \
                    int(self.params['hardware']['num_cpus'])
            if 'memory_mb' in self.params['hardware']:
                clonespec_kwargs['config'].memoryMB = \
                    int(self.params['hardware']['memory_mb'])

        # lets try and assign a static ip addresss
        if self.params['customize'] is True:
            ip_settings = list()
            if self.params['ips']:
                for ip_string in self.params['ips']:
                    ip = IPAddress(self.params['ips'])
                    for network in self.params['networks']:
                        if network:
                            if ip in IPNetwork(network):
                                self.params['networks'][network]['ip'] = str(ip)
                                ipnet = IPNetwork(network)
                                self.params['networks'][network]['subnet_mask'] = str(
                                  ipnet.netmask
                                )
                                ip_settings.append(self.params['networks'][network])

            key = 0
            network = get_obj(self.content, [vim.Network], ip_settings[key]['network'])
            datacenter = get_obj(self.content, [vim.Datacenter], self.params['datacenter'])
            # get the folder where VMs are kept for this datacenter
            destfolder = datacenter.vmFolder

            cluster = get_obj(self.content, [vim.ClusterComputeResource],self.params['cluster'])

            devices = []
            adaptermaps = []

            try:
                for device in template.config.hardware.device:
                    if hasattr(device, 'addressType'):
                        nic = vim.vm.device.VirtualDeviceSpec()
                        nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.remove
                        nic.device = device
                        devices.append(nic)
            except:
                pass

                # single device support
            nic = vim.vm.device.VirtualDeviceSpec()
            nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
            nic.device = vim.vm.device.VirtualVmxnet3()
            nic.device.wakeOnLanEnabled = True
            nic.device.addressType = 'assigned'
            nic.device.deviceInfo = vim.Description()
            nic.device.deviceInfo.label = 'Network Adapter %s' % (key + 1)
            nic.device.deviceInfo.summary = ip_settings[key]['network']

            if hasattr(get_obj(self.content, [vim.Network], ip_settings[key]['network']), 'portKeys'):
            # VDS switch
                pg_obj = get_obj(self.content, [vim.dvs.DistributedVirtualPortgroup], ip_settings[key]['network'])
                dvs_port_connection = vim.dvs.PortConnection()
                dvs_port_connection.portgroupKey= pg_obj.key
                dvs_port_connection.switchUuid= pg_obj.config.distributedVirtualSwitch.uuid
                nic.device.backing = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo()
                nic.device.backing.port = dvs_port_connection

            else:
            # vSwitch
                nic.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo()
                nic.device.backing.network = get_obj(self.content, [vim.Network], ip_settings[key]['network'])
                nic.device.backing.deviceName = ip_settings[key]['network']

            nic.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo()
            nic.device.connectable.startConnected = True
            nic.device.connectable.allowGuestControl = True
            nic.device.connectable.connected = True
            nic.device.connectable.allowGuestControl = True
            devices.append(nic)

            # Update the spec with the added NIC
            clonespec_kwargs['config'].deviceChange = devices

            guest_map = vim.vm.customization.AdapterMapping()
            guest_map.adapter = vim.vm.customization.IPSettings()
            guest_map.adapter.ip = vim.vm.customization.FixedIp()
            guest_map.adapter.ip.ipAddress = str(ip_settings[key]['ip'])
            guest_map.adapter.subnetMask = str(ip_settings[key]['subnet_mask'])

            try:
                guest_map.adapter.gateway = ip_settings[key]['gateway']
            except:
                pass

            try:
                guest_map.adapter.dnsDomain = self.params['domain']
            except:
                pass

            adaptermaps.append(guest_map)

            # DNS settings
            globalip = vim.vm.customization.GlobalIPSettings()
            globalip.dnsServerList = self.params['dns_servers']
            globalip.dnsSuffixList = str(self.params['domain'])

            # Hostname settings
            ident = vim.vm.customization.LinuxPrep()
            ident.domain = str(self.params['domain'])
            ident.hostName = vim.vm.customization.FixedName()
            ident.hostName.name = self.params['name']

            customspec = vim.vm.customization.Specification()
            clonespec_kwargs['customization'] = customspec

            clonespec_kwargs['customization'].nicSettingMap = adaptermaps
            clonespec_kwargs['customization'].globalIPSettings = globalip
            clonespec_kwargs['customization'].identity = ident

        clonespec = vim.vm.CloneSpec(**clonespec_kwargs)
        task = template.Clone(folder=destfolder, name=self.params['name'], spec=clonespec)
        self.wait_for_task(task)

        if task.info.state == 'error':
            # https://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2021361
            # https://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2173
            return ({'changed': False, 'failed': True, 'msg': task.info.error.msg})
        else:

            # set annotation
            vm = task.info.result
            if self.params['annotation']:
                annotation_spec = vim.vm.ConfigSpec()
                annotation_spec.annotation = str(self.params['annotation'])
                task = vm.ReconfigVM_Task(annotation_spec)
                self.wait_for_task(task)
            if wait_for_ip:
                self.set_powerstate(vm, 'poweredon', force=False)
                self.wait_for_vm_ip(vm)
            vm_facts = self.gather_facts(vm)
            return ({'changed': True, 'failed': False, 'instance': vm_facts})

    def wait_for_task(self, task):
        # https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.Task.html
        # https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.TaskInfo.html
        # https://github.com/virtdevninja/pyvmomi-community-samples/blob/master/samples/tools/tasks.py
        while task.info.state not in ['success', 'error']:
            time.sleep(1)

    def wait_for_vm_ip(self, vm, poll=100, sleep=5):
        ips = None
        facts = {}
        thispoll = 0
        while not ips and thispoll <= poll:
            newvm = self.getvm(uuid=vm.config.uuid)
            facts = self.gather_facts(newvm)
            if facts['ipv4'] or facts['ipv6']:
                ips = True
            else:
                time.sleep(sleep)
                thispoll += 1

        return facts

    def fetch_file_from_guest(self, vm, username, password, src, dest):

        ''' Use VMWare's filemanager api to fetch a file over http '''

        result = {'failed': False}

        tools_status = vm.guest.toolsStatus
        if (tools_status == 'toolsNotInstalled' or
                tools_status == 'toolsNotRunning'):
            result['failed'] = True
            result['msg'] = "VMwareTools is not installed or is not running in the guest"
            return result

        # https://github.com/vmware/pyvmomi/blob/master/docs/vim/vm/guest/NamePasswordAuthentication.rst
        creds = vim.vm.guest.NamePasswordAuthentication(
            username=username, password=password
        )

        # https://github.com/vmware/pyvmomi/blob/master/docs/vim/vm/guest/FileManager/FileTransferInformation.rst
        fti = self.content.guestOperationsManager.fileManager. \
                            InitiateFileTransferFromGuest(vm, creds, src)

        result['size'] = fti.size
        result['url'] = fti.url

        # Use module_utils to fetch the remote url returned from the api
        rsp, info = fetch_url(self.module, fti.url, use_proxy=False,
                             force=True, last_mod_time=None,
                             timeout=10, headers=None)

        # save all of the transfer data
        for k,v in info.iteritems():
            result[k] = v

        # exit early if xfer failed
        if info['status'] != 200:
            result['failed'] = True
            return result

        # attempt to read the content and write it
        try:
            with open(dest, 'wb') as f:
                f.write(rsp.read())
        except Exception as e:
            result['failed'] = True
            result['msg'] = str(e)

        return result

    def push_file_to_guest(self, vm, username, password, src, dest, overwrite=True):

        ''' Use VMWare's filemanager api to push a file over http '''

        result = {'failed': False}

        tools_status = vm.guest.toolsStatus
        if (tools_status == 'toolsNotInstalled' or
                tools_status == 'toolsNotRunning'):
            result['failed'] = True
            result['msg'] = "VMwareTools is not installed or is not running in the guest"
            return result

        # https://github.com/vmware/pyvmomi/blob/master/docs/vim/vm/guest/NamePasswordAuthentication.rst
        creds = vim.vm.guest.NamePasswordAuthentication(
            username=username, password=password
        )

        # the api requires a filesize in bytes
        filesize = None
        fdata = None
        try:
            #filesize = os.path.getsize(src)
            filesize = os.stat(src).st_size
            fdata = None
            with open(src, 'rb') as f:
                fdata = f.read()
            result['local_filesize'] = filesize
        except Exception as e:
            result['failed'] = True
            result['msg'] = "Unable to read src file: %s" % str(e)
            return result

        # https://www.vmware.com/support/developer/converter-sdk/conv60_apireference/vim.vm.guest.FileManager.html#initiateFileTransferToGuest
        file_attribute = vim.vm.guest.FileManager.FileAttributes()
        url = self.content.guestOperationsManager.fileManager. \
                InitiateFileTransferToGuest(vm, creds, dest, file_attribute,
                                            filesize, overwrite)

        # PUT the filedata to the url ...
        rsp, info = fetch_url(self.module, url, method="put", data=fdata,
                             use_proxy=False, force=True, last_mod_time=None,
                             timeout=10, headers=None)

        result['msg'] = str(rsp.read())

        # save all of the transfer data
        for k,v in info.iteritems():
            result[k] = v

        return result

    def run_command_in_guest(self, vm, username, password, program_path, program_args, program_cwd, program_env):

        result = {'failed': False}

        tools_status = vm.guest.toolsStatus
        if (tools_status == 'toolsNotInstalled' or
                tools_status == 'toolsNotRunning'):
            result['failed'] = True
            result['msg'] = "VMwareTools is not installed or is not running in the guest"
            return result

        # https://github.com/vmware/pyvmomi/blob/master/docs/vim/vm/guest/NamePasswordAuthentication.rst
        creds = vim.vm.guest.NamePasswordAuthentication(
            username=username, password=password
        )

        res = None
        pdata = None
        try:
            # https://github.com/vmware/pyvmomi/blob/master/docs/vim/vm/guest/ProcessManager.rst
            pm = self.content.guestOperationsManager.processManager
            # https://www.vmware.com/support/developer/converter-sdk/conv51_apireference/vim.vm.guest.ProcessManager.ProgramSpec.html
            ps = vim.vm.guest.ProcessManager.ProgramSpec(
                #programPath=program,
                #arguments=args
                programPath=program_path,
                arguments=program_args,
                workingDirectory=program_cwd,
            )
            res = pm.StartProgramInGuest(vm, creds, ps)
            result['pid'] = res
            pdata = pm.ListProcessesInGuest(vm, creds, [res])

            # wait for pid to finish
            while not pdata[0].endTime:
                time.sleep(1)
                pdata = pm.ListProcessesInGuest(vm, creds, [res])
            result['owner'] = pdata[0].owner
            result['startTime'] = pdata[0].startTime.isoformat()
            result['endTime'] = pdata[0].endTime.isoformat()
            result['exitCode'] = pdata[0].exitCode
            if result['exitCode'] != 0:
                result['failed'] = True
                result['msg'] = "program exited non-zero"
            else:
                result['msg'] = "program completed successfully"

        except Exception as e:
            result['msg'] = str(e)
            result['failed'] = True

        return result

    def list_snapshots_recursively(self, snapshots):
        snapshot_data = []
        snap_text = ''
        for snapshot in snapshots:
            snap_text = 'Id: %s; Name: %s; Description: %s; CreateTime: %s; State: %s'%(snapshot.id, snapshot.name,
                            snapshot.description, snapshot.createTime, snapshot.state)
            snapshot_data.append(snap_text)
            snapshot_data = snapshot_data + self.list_snapshots_recursively(snapshot.childSnapshotList)
        return snapshot_data

    def get_snapshots_by_name_recursively(self, snapshots, snapname):
        snap_obj = []
        for snapshot in snapshots:
            if snapshot.name == snapname:
                snap_obj.append(snapshot)
            else:
                snap_obj = snap_obj + self.get_snapshots_by_name_recursively(snapshot.childSnapshotList, snapname)
        return snap_obj

    def get_current_snap_obj(self, snapshots, snapob):
        snap_obj = []
        for snapshot in snapshots:
            if snapshot.snapshot == snapob:
                snap_obj.append(snapshot)
            snap_obj = snap_obj + self.get_current_snap_obj(snapshot.childSnapshotList, snapob)
        return snap_obj

    def snapshot_vm(self, vm, guest, snapshot_op):
        ''' To perform snapshot operations create/remove/revert/list_all/list_current/remove_all '''

        try:
            snapshot_op_name = snapshot_op['op_type']
        except KeyError:
            self.module.fail_json(msg="Specify op_type - create/remove/revert/list_all/list_current/remove_all")

        task = None
        result = {}

        if snapshot_op_name not in ['create', 'remove', 'revert', 'list_all', 'list_current', 'remove_all']:
            self.module.fail_json(msg="Specify op_type - create/remove/revert/list_all/list_current/remove_all")

        if snapshot_op_name != 'create' and vm.snapshot is None:
            self.module.exit_json(msg="VM - %s doesn't have any snapshots"%guest)

        if snapshot_op_name == 'create':
            try:
                snapname = snapshot_op['name']
            except KeyError:
                self.module.fail_json(msg="specify name & description(optional) to create a snapshot")

            if 'description' in snapshot_op:
                snapdesc = snapshot_op['description']
            else:
                snapdesc = ''

            dumpMemory = False
            quiesce = False
            task = vm.CreateSnapshot(snapname, snapdesc, dumpMemory, quiesce)

        elif snapshot_op_name in ['remove', 'revert']:
            try:
                snapname = snapshot_op['name']
            except KeyError:
                self.module.fail_json(msg="specify snapshot name")

            snap_obj = self.get_snapshots_by_name_recursively(vm.snapshot.rootSnapshotList, snapname)

            #if len(snap_obj) is 0; then no snapshots with specified name
            if len(snap_obj) == 1:
                snap_obj = snap_obj[0].snapshot
                if snapshot_op_name == 'remove':
                    task = snap_obj.RemoveSnapshot_Task(True)
                else:
                    task = snap_obj.RevertToSnapshot_Task()
            else:
                self.module.exit_json(msg="Couldn't find any snapshots with specified name: %s on VM: %s"%(snapname, guest))

        elif snapshot_op_name == 'list_all':
            snapshot_data = self.list_snapshots_recursively(vm.snapshot.rootSnapshotList)
            result['snapshot_data'] = snapshot_data

        elif snapshot_op_name == 'list_current':
            current_snapref = vm.snapshot.currentSnapshot
            current_snap_obj = self.get_current_snap_obj(vm.snapshot.rootSnapshotList, current_snapref)
            result['current_snapshot'] = 'Id: %s; Name: %s; Description: %s; CreateTime: %s; State: %s'%(current_snap_obj[0].id,
                            current_snap_obj[0].name, current_snap_obj[0].description, current_snap_obj[0].createTime,
                            current_snap_obj[0].state)

        elif snapshot_op_name == 'remove_all':
            task = vm.RemoveAllSnapshots()

        if task:
            self.wait_for_task(task)
            if task.info.state == 'error':
                result = {'changed': False, 'failed': True, 'msg': task.info.error.msg}
            else:
                result = {'changed': True, 'failed': False}

        return result

def get_obj(content, vimtype, name):
    """
    Return an object by name, if name is None the
    first found object is returned
    """
    obj = None
    container = content.viewManager.CreateContainerView(
        content.rootFolder, vimtype, True)
    for c in container.view:
        if name:
            if c.name == name:
                obj = c
                break
        else:
            obj = c
            break

    container.Destroy()
    return obj

def main():

    vm = None

    module = AnsibleModule(
        argument_spec=dict(
            hostname=dict(
                type='str',
                default=os.environ.get('VMWARE_HOST')
            ),
            username=dict(
                type='str',
                default=os.environ.get('VMWARE_USER')
            ),
            password=dict(
                type='str', no_log=True,
                default=os.environ.get('VMWARE_PASSWORD')
            ),
            state=dict(
                required=False,
                choices=[
                    'poweredon',
                    'poweredoff',
                    'present',
                    'absent',
                    'restarted',
                    'reconfigured'
                ],
                default='present'),
            validate_certs=dict(required=False, type='bool', default=True),
            template_src=dict(required=False, type='str', aliases=['template']),
            annotation=dict(required=False, type='str', aliases=['notes']),
            name=dict(required=True, type='str'),
            name_match=dict(required=False, type='str', default='first'),
            snapshot_op=dict(required=False, type='dict', default={}),
            uuid=dict(required=False, type='str'),
            folder=dict(required=False, type='str', default='/vm', aliases=['folder']),
            disk=dict(required=False, type='list'),
            nic=dict(required=False, type='list'),
            hardware=dict(required=False, type='dict', default={}),
            force=dict(required=False, type='bool', default=False),
            datacenter=dict(required=False, type='str', default=None),
            esxi_hostname=dict(required=False, type='str', default=None),
            cluster=dict(required=False, type='str', default=None),
            wait_for_ip_address=dict(required=False, type='bool', default=True),
            customize=dict(required=False, type='bool', default=False),
            ips=dict(required=False, type='str', default=None),
            dns_servers=dict(required=False, type='list', default=None),
            domain=dict(required=False, type='str', default=None),
            networks=dict(required=False, type='dict', default={})
        ),
        supports_check_mode=True,
        mutually_exclusive=[],
        required_together=[
            ['state', 'force'],
            ['template'],
        ],
    )

    pyv = PyVmomiHelper(module)

    # Check if the VM exists before continuing
    vm = pyv.getvm(name=module.params['name'],
                   folder=module.params['folder'],
                   uuid=module.params['uuid'],
                   name_match=module.params['name_match'])

    # VM already exists
    if vm:

        if module.params['state'] == 'absent':
            # destroy it
            if module.params['force']:
                # has to be poweredoff first
                result = pyv.set_powerstate(vm, 'poweredoff', module.params['force'])
            result = pyv.remove_vm(vm)
        elif module.params['state'] in ['poweredon', 'poweredoff', 'restarted']:
            # set powerstate
            result = pyv.set_powerstate(vm, module.params['state'], module.params['force'])
        elif module.params['snapshot_op']:
            result = pyv.snapshot_vm(vm, module.params['name'], module.params['snapshot_op'])
        else:
            # Run for facts only
            try:
                module.exit_json(instance=pyv.gather_facts(vm))
            except Exception:
                e = get_exception()
                module.fail_json(
                    msg="Fact gather failed with exception %s" % e)

    # VM doesn't exist
    else:
        create_states = ['poweredon', 'poweredoff', 'present', 'restarted']
        if module.params['state'] in create_states:
            poweron = (module.params['state'] != 'poweredoff')
            # Create it ...
            result = pyv.deploy_template(
                        poweron=poweron,
                        wait_for_ip=module.params['wait_for_ip_address']
                     )
            result['changed'] = True
        elif module.params['state'] == 'absent':
            result = {'changed': False, 'failed': False}
        else:
            result = {'changed': False, 'failed': False}

    # FIXME
    if not 'failed' in result:
        result['failed'] = False

    if result['failed']:
        module.fail_json(**result)
    else:
        module.exit_json(**result)

from ansible.module_utils.vmware import *
from ansible.module_utils.basic import *

if __name__ == '__main__':
    main()


text:
<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="shortcut icon" href="../../docs-assets/ico/favicon.png">

    <title>About the John Doe's falls and hearrate report</title>

    <link href="./css/style.css" rel="stylesheet">
    <link href="./css/bootstrap.css" rel="stylesheet">

          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
            Toggle navigation

          </button>
          Falls and HR

Tracking

About

Contact

The report of falls detection, temperature, and heart rate of John Doe has been made by the students of ESIR and EUETIB of biomedical engineering under the supervision of Alfredo Hernandez and Di Ge from the LTSI, University of Rennes 1.

The data used in this program are provided by a Texas Instrument SensorTag (falls and temperature) and by a Polaris belt (heartrate).
The SensorTag part is using a Javascript library by samdeepmistry found on GitHub. The Polaris part is using a selfmade Arduino-Zigbee duo to send data to the computer.

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE html>

		<link rel="stylesheet" href="acsong.css" />
		<title>Web components example</title>


text:
package building.blocks;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;

import javax.imageio.ImageIO;

import org.apache.commons.lang3.tuple.Pair;

/**
 * Legacy Code, which is used during the JDK 6.
 *
 * Since Callable is following the Functional Interface's Specification,
 * it can be used in Lambda Expression without any changes.
 */
public class PictureCrawlingTask implements Callable<String> {

	private static final int RETRY_TIMES = 10;
	private static final int CONNECT_TIMEOUT_MILLIS = 1500;
	private static final int READ_TIMEOUT_MILLIS = 2000;

	private String url;
	private String filePath;

	private final CrawlerTaskStatistics stat;

	private PictureCrawlingTask(CrawlerTaskStatistics stat) {
		this.stat = stat;
	}

	public PictureCrawlingTask(Pair<String, String> tuple,
			CrawlerTaskStatistics stat) {
		this(stat);
		this.url = tuple.getLeft();
		this.filePath = tuple.getRight();
	}

	public PictureCrawlingTask(String url, String filePath,
			CrawlerTaskStatistics stat) {
		this(stat);
		this.url = url;
		this.filePath = filePath;
	}

	@Override
	public String call() {
		URL urlObj;
		try {
			urlObj = new URL(url);
		} catch (MalformedURLException e) {
			String errorMsg = "Malformed URL: " + url;
			System.err.println(errorMsg);
			e.printStackTrace();
			return "";
		}

		String threadName = Thread.currentThread().getName();

		HttpURLConnection conn;
		int retryCount = 0;
		while (retryCount < RETRY_TIMES) {
			try {
				conn = (HttpURLConnection) urlObj.openConnection();
				conn.setInstanceFollowRedirects(false);
				conn.setConnectTimeout(CONNECT_TIMEOUT_MILLIS);
				conn.setReadTimeout(READ_TIMEOUT_MILLIS);

				String msg = String.format("[%s] Reading URL %s, Time %d",
						threadName, url, retryCount + 1);
				System.out.println(msg);
				if (String.valueOf(conn.getResponseCode()).startsWith("3")) {
					msg = String
							.format("%s will result in a redirect operation, abort it.",
									url);
					System.out.println(msg);
					stat.getRedirectURLs().offer(Pair.of(url, filePath));
					return "";
				}

				BufferedImage image = null;
				image = ImageIO.read(conn.getInputStream());
				ImageIO.write(image, "jpg", new File(filePath));

				msg = String.format(
						"[%s] Crawl Image Successful, URL: %s --- Path: %s",
						threadName, url, filePath);
				System.out.println(msg);
				// return directly after saving successfully
				return filePath;
			} catch (IOException e) {
				retryCount++;
				String errorMsg = String
						.format("[%s] IO Exception --- %s, happened when trying to save image from url: %s to file: %s",
								threadName, e.getMessage(), url, filePath);
				System.out.println(errorMsg);
			}
		}

		stat.getFailedURLs().offer(Pair.of(url, filePath));
		return "";
	}

	public static List<PictureCrawlingTask> constructTasks(
			List<Pair<String, String>> taskTuples, CrawlerTaskStatistics stat) {
		List<PictureCrawlingTask> tasks = new LinkedList<PictureCrawlingTask>();
		for (Pair<String, String> t : taskTuples) {
			tasks.add(new PictureCrawlingTask(t, stat));
		}

		return tasks;
	}
}


text:
<?php

namespace DvsaMotTest\Controller;

use DvsaClient\Mapper\VehicleExpiryMapper;
use DvsaCommon\Date\DateTimeDisplayFormat;
use DvsaCommon\Dto\MotTesting\MotTestOptionsDto;
use DvsaCommon\Factory\AutoWire\AutoWireableInterface;
use DvsaCommon\UrlBuilder\UrlBuilder;
use DvsaMotTest\Service\MotChecklistPdfService;
use DvsaMotTest\Presenter\MotTestOptionsPresenter;
use Zend\View\Model\ViewModel;

class MotTestOptionsController extends AbstractDvsaMotTestController implements AutoWireableInterface
{
    const ROUTE_MOT_TEST_OPTIONS = 'mot-test/options';

    const TEMPLATE_MOT_TEST_OPTIONS = 'dvsa-mot-test/mot-test/mot-test-options.phtml';

    const PAGE_TITLE_TEMPLATE = '%s started';

    protected $motChecklistPdfService;
    private $vehicleExpiryMapper;

    public function __construct(
        MotChecklistPdfService $motChecklistPdfService,
        VehicleExpiryMapper $vehicleExpiryMapper
    ) {
        $this->motChecklistPdfService = $motChecklistPdfService;
        $this->vehicleExpiryMapper = $vehicleExpiryMapper;
    }

    public function motTestOptionsAction()
    {
        $motTestNumber = $this->params()->fromRoute('motTestNumber');

        $dto = MotTestOptionsDto::fromArray(
            $this->getRestClient()->get(UrlBuilder::motTestOptions($motTestNumber)->toString())['data']
        );

        $presenter = new MotTestOptionsPresenter($dto);
        $presenter->setMotTestNumber($motTestNumber);

        $pageTitle = sprintf(self::PAGE_TITLE_TEMPLATE, $presenter->getReadableMotTestType());

        $this->layout()->setVariable('pageTitle', $pageTitle);
        $this->layout()->setVariable('pageSubTitle', $presenter->getPageSubTitle());
        $this->layout()->setVariable('bannerPage', true);
        $this->setHeadTitle($pageTitle);
        $this->addMotTestLateInfoToGtmDataLayer($dto->getVehicleId(), $dto->getVehicleRegistrationNumber());

        $viewModel = new ViewModel(['presenter' => $presenter]);
        $viewModel->setTemplate(self::TEMPLATE_MOT_TEST_OPTIONS);

        return $viewModel;
    }

    public function motChecklistAction()
    {
        $motTestNumber = $this->params()->fromRoute('motTestNumber');
        $pdf = $this->motChecklistPdfService->getChecklistPdf($motTestNumber);
        $this->getResponse()
            ->setContent($pdf)
            ->getHeaders()->addHeaders([
                'Content-Length' => strlen($pdf),
                'Content-Type' => 'application/pdf',
                'Content-Disposition' => 'filename=Mot-checklist_'.$motTestNumber.'.pdf',
            ]);

        return $this->getResponse();
    }

    private function addMotTestLateInfoToGtmDataLayer($vehicleId, $vrm)
    {
        $gtmData = [];

        $gtmData['vrm'] = $vrm;
        $today = new \DateTime();
        $expiryDate = $this->vehicleExpiryMapper->getExpiryForVehicle($vehicleId)->getExpiryDate();
        $gtmData['expiryDate'] = DateTimeDisplayFormat::dateTime($expiryDate);

        $gtmData['testLate'] = $today > $expiryDate;

        if ($gtmData['testLate']) {
            $late = $today->diff($expiryDate);
            $gtmData['testLateInDays'] = $late->days;
        }

        $this->gtmDataLayer($gtmData);
    }
}


text:
module Mongo
  module Auth
    class X509

      # Defines behaviour around a single x.509 conversation between the
      # client and server.
      #
      # @since 2.0.0
      class Conversation

        # The login message.
        #
        # @since 2.0.0
        LOGIN = { authenticate: 1 }.freeze

        # @return [ Protocol::Reply ] reply The current reply in the
        #   conversation.
        attr_reader :reply

        # @return [ User ] user The user for the conversation.
        attr_reader :user

        # Finalize the x.509 conversation. This is meant to be iterated until
        # the provided reply indicates the conversation is finished.
        #
        # @example Finalize the conversation.
        #   conversation.finalize(reply)
        #
        # @param [ Protocol::Reply ] reply The reply of the previous
        #   message.
        #
        # @return [ Protocol::Query ] The next message to send.
        #
        # @since 2.0.0
        def finalize(reply)
          validate!(reply)
        end

        # Start the x.509 conversation. This returns the first message that
        # needs to be send to the server.
        #
        # @example Start the conversation.
        #   conversation.start
        #
        # @return [ Protocol::Query ] The first x.509 conversation message.
        #
        # @since 2.0.0
        def start
          login = LOGIN.merge(mechanism: X509::MECHANISM)
          login[:user] = user.name if user.name
          Protocol::Query.new(
            Auth::EXTERNAL,
            Database::COMMAND,
            login,
            limit: -1
          )
        end

        # Create the new conversation.
        #
        # @example Create the new conversation.
        #   Conversation.new(user, "admin")
        #
        # @param [ Auth::User ] user The user to converse about.
        #
        # @since 2.0.0
        def initialize(user)
          @user = user
        end

        private

        def validate!(reply)
          raise Unauthorized.new(user) if reply.documents[0][Operation::Result::OK] != 1
          @reply = reply
        end
      end
    end
  end
end


text:
(function ($) {

  /**
  * Extend MediumEditor with a function for hiding the toolbar
  * @return {void}
  */

  MediumEditor.prototype.hideToolbar = function () {
    if (this.toolbar) {
      this.toolbar.style.display = 'none';
    }
  };

  /**
  * Extend MediumEditor's serialize function to get rid of unnecesarry Medium Editor Insert Plugin stuff
  * @return {object} content Object containing HTML content of each element
  */

  MediumEditor.prototype.serialize = function () {
    var i, j,
        elementid,
        content = {},
        $clone, $inserts, $insert, $insertData, html;
    for (i = 0; i < this.elements.length; i += 1) {
      elementid = (this.elements[i].id !== '') ? this.elements[i].id : 'element-' + i;

      $clone = $(this.elements[i]).clone();
      $inserts = $('.mediumInsert', $clone);
      for (j = 0; j < $inserts.length; j++) {
        $insert = $inserts[j];
        $insertData = $('.mediumInsert-placeholder', $insert).children();console.log($insertData.length);
        if ($insertData.length === 0) {
          $insert.remove();
        } else {
          $insert.removeAttr('contenteditable');
          $('img[draggable]', $insert).removeAttr('draggable');
          if ($insert.hasClass('small')) {
            $insertData.addClass('small');
          }
          $('.mediumInsert-buttons', $insert).remove();
          $insertData.unwrap();
        }
      }

      html = $clone.html().trim();
      content[elementid] = {
        value: html
      };
    }
    return content;
  };

  /**
  * Medium Editor Insert Plugin
  * @param {object} options Options for the plugin
  * @param {void}
  */

  $.fn.mediumInsert = function (options) {

    $.fn.mediumInsert.settings = $.extend($.fn.mediumInsert.settings, options);

    /**
    * Initial plugin loop
    */

    return this.each(function () {

      $('p', this).bind('dragover drop', function (e) {
        e.preventDefault();
        return false;
      });

      $.fn.mediumInsert.insert.init($(this));

      if ($.fn.mediumInsert.settings.images === true) {
        $.fn.mediumInsert.images.init();
      }

      if ($.fn.mediumInsert.settings.maps === true) {
        $.fn.mediumInsert.maps.init();
      }

    });

  };

  /**
  * Settings
  */

  $.fn.mediumInsert.settings = {
    'imagesUploadScript': 'upload.php',
    'images': true,
    'maps': false,
  };

  /**
  * Addon Initialization
  */

  $.fn.mediumInsert.insert = {

    /**
    * Insert initial function
    * @param {element} el Parent container element
    * @return {void}
    */

    init: function ($el) {
      this.$el = $el;
      this.setPlaceholders();
    },

    /**
    * Deselect selected text and hide MediumEditor toolbar
    * @return {void}
    */

    deselect: function () {
      document.getSelection().removeAllRanges();
      $.fn.mediumInsert.settings.editor.hideToolbar();
    },

    /**
    * Method setting placeholders and basic events on them
    * @param {element} el Parent container element
    * @return {void}
    */
    setPlaceholders: function () {
      var that = this,
          $el = $.fn.mediumInsert.insert.$el;

      if ($el.is(':empty')) {
        $el.html('

');
      }

      $el.keyup(function () {
        var i = 0;

        $el.children('p').each(function () {
          if ($(this).next().hasClass('mediumInsert') === false) {
            $(this).after('
'+
              '
'+
                '
→
'+
                'Insert'+
                '
'+
                  ($.fn.mediumInsert.settings.images === true ? '
Image
': '') +
                  ($.fn.mediumInsert.settings.maps === true ? '
Map
': '') +
                '
'+
              '
'+
              '

'+
            '
');
          }
          i++;
        });
      }).keyup();

      $el.on('selectstart', '.mediumInsert', function (e) {
        e.preventDefault();
        return false;
      });

      $el.on('blur', function () {
        var $clone = $(this).clone(),
            cloneHtml;

        $clone.find('.mediumInsert').remove();
        cloneHtml = $clone.html().replace(/^\s+|\s+$/g, '');

        if (cloneHtml === '' || cloneHtml === '

') {
          $(this).addClass('medium-editor-placeholder');
        }
      });

      $el.on('click', '.mediumInsert-buttons a.mediumInsert-buttonsShow', function () {
        var $options = $(this).siblings('.mediumInsert-buttonsOptions'),
            $placeholder = $(this).parent().siblings('.mediumInsert-placeholder');

        if ($(this).hasClass('active')) {
          $(this).removeClass('active');
          $options.hide();

          $('a', $options).show();
        } else {
          $(this).addClass('active');
          $options.show();

          $('a', $options).each(function () {
            var aClass = $(this).attr('class'),
                plugin = aClass.split('-')[0];
            if ($('.mediumInsert-'+ plugin, $placeholder).length > 0) {
              $('a:not(.'+ aClass +')', $options).hide();
            }
          });
        }

        that.deselect();
      });

      $el.on('mouseleave', '.mediumInsert', function () {
        $('a.mediumInsert-buttonsShow', this).removeClass('active');
        $('.mediumInsert-buttonsOptions', this).hide();
      });

      $el.on('click', '.mediumInsert-buttonsOptions a', function () {
        var action = $(this).attr('class').split('-');
        var $placeholder = $(this).parent().parent().parent().siblings('.mediumInsert-placeholder');

        if ($.fn.mediumInsert[action[0]] && $.fn.mediumInsert[action[0]][action[1]]) {
          $.fn.mediumInsert[action[0]][action[1]]($placeholder);
        }

        $(this).parents('.mediumInsert').mouseleave();
      });
    }

  };

}(jQuery));


text:
{-|
Module:      Spec.FunctionsSpec
Copyright:   (C) 2014-2017 Ryan Scott
License:     BSD-style (see the file LICENSE)
Maintainer:  Ryan Scott
Stability:   Provisional
Portability: GHC

@hspec@ test for the orphan 'TextShow' instance for functions.
-}
module Spec.FunctionsSpec (main, spec) where

import Data.Proxy.Compat (Proxy(..))
import Spec.Utils (matchesTextShowSpec)
import Test.Hspec (Spec, describe, hspec, parallel)
import Text.Show.Functions ()
import TextShow.Functions ()

main :: IO ()
main = hspec spec

spec :: Spec
spec = parallel . describe "Int -> Int" $
    matchesTextShowSpec (Proxy :: Proxy (Int -> Int))


text:
/**
 * Package contains code generators for Java.
 */
package eu.sarunas.atf.generators.code.java;


text:
Test that default credentials aren't used when ones are provided to XHR explicitly.

Login: FAIL - Test not run

Default: FAIL - Test not run

Re-login: FAIL - Test not run

New default: FAIL - Test not run


text:
'use strict';

// external deps
var ObjectId = require('mongodb').ObjectId;
require('mongodb-toolkit');
var BaseManager = require('module-toolkit').BaseManager;
var BateeqModels = require('bateeq-models');
var map = BateeqModels.map;
var generateCode = require('../../utils/code-generator');
var moment = require('moment');
var moduleId = "opname-balance";

module.exports = class StockOpnameBalanceManager extends BaseManager {
    constructor(db, user) {
        super(db, user);
        this.collection = this.db.use(map.inventory.StockOpnameBalance)
    }

    create(stockOpnameBalance) {
        return new Promise((resolve, reject) => {

            this.collection.insert(stockOpnameBalance)
                .then((result) => {
                    resolve(result);
                })
                .catch((error) => {
                    reject(error);
                });
        });
    }

    update(stockOpnameBalance) {
        return new Promise((resolve, reject) => {

            this.collection.update(stockOpnameBalance)
                .then((result) => {
                    resolve(result);
                })
                .catch((error) => {
                    reject(error);
                });
        });
    }

    getByStorageCode(storeCode, productCode) {
        return new Promise((resolve, reject) => {

            var query = {
                'storage.code': storeCode,
                'product.code': productCode,
                '_deleted': false
            };

            this.collection.singleOrDefault(query)
                .then((result) => {
                    resolve(result);
                })
                .catch((error) => {
                    reject(error);
                });
        });

    }

    getBalanceByStorageCode(storageCode) {
        return new Promise((resolve, reject) => {

            var query = {
                'storage.code' : storageCode
            };

            this.collection.find(query).toArray()
            .then(result => {
                resolve(result);
            })
            .catch(error => {
                reject(error);
            });
        });
    }

    _getQuery(paging) {
        var _default = {
            _deleted: false
        },
            pagingFilter = paging.filter || {},
            keywordFilter = {},
            query = {};

        if (paging.keyword) {
            var regex = new RegExp(paging.keyword, "i");
            var createdAgentFilter = {
                "_createAgent": {
                    "$regex": regex
                }
            };
            var codeFilter = {
                "code": {
                    "$regex": regex
                }
            };
            var storageFilter = {
                "storage.name": {
                    "$regex": regex
                }
            };
            var stockOpnameDocCodeFilter = {
                "stockOpnameDocCodes": {
                    "$regex": regex
                }
            }

            keywordFilter["$or"] = [createdAgentFilter, codeFilter, storageFilter, stockOpnameDocCodeFilter];
        }
        query["$and"] = [_default, keywordFilter, pagingFilter];
        return query;
    }

    read(paging) {
        var _paging = Object.assign({
            page: 1,
            size: 20,
            order: {},
            filter: {},
            select: ["code", "storage.name", "products"]
        }, paging);
        var query = this._getQuery(_paging);

        return this.collection
            .where(query)
            .select(_paging.select)
            .page(_paging.page, _paging.size)
            .order(_paging.order)
            .execute();
    }
}


text:
var logger = require('pomelo-logger');

/**
 * Configure pomelo logger
 */
module.exports.configure = function(app, filename) {
  var serverId = app.getServerId();
  var base = app.getBase();
  logger.configure(filename, {serverId: serverId, base: base});
};


text:
<?php namespace Odoo\Client;

use Odoo\Client\Connection\Connection;
use Odoo\Client\Transformer\Transformer;
use PhpXmlRpc\Value as xmlrpcval;
use PhpXmlRpc\Request as xmlrpcmsg;
use PhpXmlRpc\Response as xmlrpcresp;

class OdooClient
{
    /**
     * The endpoint provides meta-calls which don't require authentication,
     * such as the authentication itself or fetching version information.
     * @var string $_common
     */
    private static $_common = '/xmlrpc/2/common';

    /**
     * The endpoint is used to call methods of Odoo models
     * via the execute_kw RPC function.
     * @var string $_object
     */
    private static $_object = '/xmlrpc/2/object';

    /**
     * Odoo XML-RPC directly execute custom method
     * @var string $_execute
     */
    private static $_execute = 'execute_kw';

    /**
     * res.user model
     * @var string $_user_model
     */
    private static $_user_model = 'res.users';

    /**
     * Odoo XML-RPC context_get method
     * @var string $_context_get
     */
    private static $_context_get = 'context_get';

    /**
     * Odoo XML-RPC create method
     * @var string $_create
     */
    private static $_create = 'create';

    /**
     * Odoo XML-RPC unlink method
     * @var string $_unlink
     */
    private static $_unlink = 'unlink';

    /**
     * Odoo XML-RPC write method
     * @var string $_write
     */
    private static $_write = 'write';

    /**
     * Odoo XML-RPC search method
     * @var string $_search
     */
    private static $_search = 'search';

    /**
     * Odoo XML-RPC read method
     * @var string $_read
     */
    private static $_read = 'read';

    /**
     * Odoo XML-RPC search_read method
     * @var string $_search_read
     */
    private static $_search_read = 'search_read';

    /**
     * Odoo XML-RPC search_count method
     * @var string $_search_count
     */
    private static $_search_count = 'search_count';

    /**
     * Odoo XML-RPC name_get method
     * @var string $_name_get
     */
    private static $_name_get = 'name_get';

    /**
     * Odoo XML-RPC fields_get method
     * @var string $_fields_get
     */
    private static $_fields_get = 'fields_get';

    /**
     * Odoo XML-RPC check_access_rights method
     * @var string $_check_access_rights
     */
    private static $_check_access_rights = 'check_access_rights';

    /**
     * Odoo XML-RPC product_id_change method
     * @var string $_product_id_change
     */
    private static $_product_id_change = 'product_id_change';

    /**
     * Connection host
     * @var string $_host
     */
    private $_host;

    /**
     * Connection port
     * @var int $_port
     */
    private $_port;

    /**
     * Odoo database name
     * @var string $_db
     */
    private $_db;

    /**
     * Username for login
     * @var string $_username
     */
    private $_username;
    /**
     * Password for login
     * @var string $_password
     */
    private $_password;

    /**
     * The user ID is returned after the login
     * @var int $_uid
     */
    private $_uid;

    /**
     * Connection object
     * @var object $_connection
     */
    private $_connection;

    /**
     * Response transform
     * @var Transformer $_transform
     */
    private $_transform;

    /**
     * OdooClient constructor
     * @param string $host Connection host
     * @param int $port Connection port
     * @param string $db Odoo database name
     * @param string $username Login username
     * @param string $password Login password
     */
    public function __construct($host, $port, $db = NULL, $username = NULL, $password = NULL)
    {
        $this->_host = $host;
        $this->_port = $port;

        $this->_db = $db;
        $this->_username = $username;
        $this->_password = $password;

        $this->_connection = new Connection($this->_host, $this->_port);
        $this->_transform = new Transformer();
    }

    /**
     * Start page of Odoo
     * @return xmlrpcresp|\PhpXmlRpc\Response[]  Odoo XML-RPC response
     * @throws \Exception
     */
    public function start()
    {
        $message = new xmlrpcmsg('start');

        $response = $this->_connection->create('/start')->send($message);
        $response = $this->_checkResponse($response);

        return $response;
    }

    /**
     * Version of Odoo
     * @return array|xmlrpcresp|\PhpXmlRpc\Response[]  Odoo XML-RPC response
     * @throws \Exception
     */
    public function version()
    {
        $message = new xmlrpcmsg('version');

        $response = $this->_connection->create(self::$_common)->send($message);
        $response = $this->_checkResponse($response);
        $response = $this->_transform->toArray($response);

        return $response;
    }

    /**
     * Login with username and password
     * @return xmlrpcresp Odoo XML-RPC response
     * @throws \Exception Throws exception when login fail
     */
    private function _login()
    {
        $message = new xmlrpcmsg('login');

        $message->addParam(new xmlrpcval($this->_db, xmlrpcval::$xmlrpcString));
        $message->addParam(new xmlrpcval($this->_username, xmlrpcval::$xmlrpcString));
        $message->addParam(new xmlrpcval($this->_password, xmlrpcval::$xmlrpcString));

        $response = $this->_connection->create(self::$_common)->send($message);

        return $this->_checkResponse($response);
    }

    /**
     * Retrieves logged user ID
     * @return int Logged user ID
     * @throws \Exception Throws exception when login fail
     */
    private function _uid()
    {
        $response = $this->_login();

        $this->_uid = (int) $response->value()->scalarval();

        return $this->_uid;
    }

    /**
     * Public method to retrieves logged user ID
     * @return int Logged user ID
     * @throws \Exception Throws exception when login fail
     */
    public function getUid()
    {
        return $this->_uid();
    }

    /**
     * Odoo XML-RPC context_get method of logged user
     * @param array $parameters Parameters as context, fields, etc
     * @return array|xmlrpcresp|\PhpXmlRpc\Response[] Odoo XML-RPC reponse
     */
    public function context_get(array $parameters = array())
    {
        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval(self::$_user_model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_context_get, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($parameters, xmlrpcval::$xmlrpcArray));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);
        $response = $this->_transform->toArray($response);

        return $response;
    }

    /**
     * Odoo XML-RPC create method
     * @param string $model Odoo model name
     * @param array $data Request input data
     * @return bool|int Odoo XML-RPC response
     * @throws \Exception Throws exception when request fail
     */
    public function create($model, array $data)
    {
        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_create, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($data, xmlrpcval::$xmlrpcArray));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);

        // Extract new ID inserted
        $response = (int) $response->value()->scalarval();

        return ($response > 0 ? $response : FALSE);
    }

    /**
     * Odoo XML-RPC search method
     * @param string $model Odoo model name
     * @param array $domain Domain filter array
     * @param array $parameters Parameters as context, fields, etc
     * @return array|xmlrpcresp|\PhpXmlRpc\Response[] Odoo XML-RPC response
     * @throws \Exception
     */
    public function search($model, array $domain, array $parameters = array())
    {
        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_search, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($domain, xmlrpcval::$xmlrpcArray));
        $msg->addParam(new xmlrpcval($parameters, xmlrpcval::$xmlrpcStruct));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);
        $response = $this->_transform->toArray($response);

        return $response;
    }

    /**
     * Odoo XML-RPC check access rights method
     * @param string $model Odoo model name
     * @param string $right access to check
     * @return boolean Odoo XML-RPC response
     * @throws \Exception
     */
    public function check_access_rights($model, $right)
    {
        // raise_exception passed by keyword (in order to get a true/false result rather than true/error)
        $parameters = array(
            'raise_exception' => new xmlrpcval(FALSE, xmlrpcval::$xmlrpcBoolean)
        );

        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_check_access_rights, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(array($right), xmlrpcval::$xmlrpcArray));
        $msg->addParam(new xmlrpcval($parameters, xmlrpcval::$xmlrpcStruct));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);
        $response = $response->value()->scalarval();

        return $response;
    }

    /**
     * Odoo XML-RPC read method
     * @param string $model Odoo model name
     * @param array $ids Data IDs
     * @param array $parameters Parameters as context, fields, etc
     * @return array|xmlrpcresp|\PhpXmlRpc\Response[] Odoo XML-RPC response
     * @throws \Exception Throws exception when request fail
     */
    public function read($model, array $ids, array $parameters = array())
    {
        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_read, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($ids, xmlrpcval::$xmlrpcArray));
        $msg->addParam(new xmlrpcval($parameters, xmlrpcval::$xmlrpcStruct));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);
        $response = $this->_transform->toArray($response);

        return $response;
    }

    /**
     * Odoo XML-RPC search_read method
     * @param string $model Odoo model name
     * @param array $domain Domain filter
     * @param array $parameters Parameters as context, fields, etc
     * @return array|xmlrpcresp|\PhpXmlRpc\Response[] Odoo XML-RPC response
     * @throws \Exception Throws exception when request fail
     */
    public function search_read($model, array $domain, array $parameters = array())
    {
        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_search_read, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($domain, xmlrpcval::$xmlrpcArray));
        $msg->addParam(new xmlrpcval($parameters, xmlrpcval::$xmlrpcStruct));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);
        $response = $this->_transform->toArray($response);

        return $response;
    }

    /**
     * Returns the number of records in the current model matching the provided domain.
     * @param string $model Odoo model name
     * @param array $domain Domain filter array
     * @return array|xmlrpcresp|\PhpXmlRpc\Response[] Odoo XML-RPC response
     * @throws \Exception
     */
    public function search_count($model, array $domain)
    {
        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_search_count, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($domain, xmlrpcval::$xmlrpcArray));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);

        return $response->value()->scalarval();
    }

    /**
     * Odoo XML-RPC name_get method
     * @param string $model Odoo model name
     * @param array $ids Data IDs
     * @param array $parameters Parameters as context, fields, etc
     * @return array|xmlrpcresp|\PhpXmlRpc\Response[] Odoo XML-RPC response
     * @throws \Exception Throws exception when request fail
     */
    public function name_get($model, array $ids, array $parameters = array())
    {
        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_name_get, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($ids, xmlrpcval::$xmlrpcArray));
        $msg->addParam(new xmlrpcval($parameters, xmlrpcval::$xmlrpcStruct));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);
        $response = $this->_transform->toArray($response);

        return $response;
    }

    /**
     * Return the definition of each field.
     * @param string $model Odoo model name
     * @param array $fields list of fields to document, all if empty or not provided
     * @param array $attributes list of description attributes to return for each field, all if empty or not provided
     * @return array|xmlrpcresp|\PhpXmlRpc\Response[] Odoo XML-RPC response
     * @throws \Exception Throws exception when request fail
     */
    public function fields_get($model, array $fields, array $attributes = array())
    {
        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_fields_get, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($fields, xmlrpcval::$xmlrpcArray));
        $msg->addParam(new xmlrpcval($attributes, xmlrpcval::$xmlrpcStruct));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);
        $response = $this->_transform->toArray($response);

        return $response;
    }

    /**
     * Odoo XML-RPC unlink method
     * @param string $model Odoo model name
     * @param array $ids Data IDs
     * @return bool Odoo XML-RPC response
     * @throws \Exception Throws exception when request fail
     */
    public function unlink($model, array $ids)
    {
        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_unlink, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($ids, xmlrpcval::$xmlrpcArray));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);

        // Extract response
        $response = (int) $response->value()->scalarval();

        return ($response === 1 ? TRUE : FALSE);
    }

    /**
     * Odoo XML-RPC write method
     * @param string $model Odoo model name
     * @param array $ids Data IDs
     * @param array $values New values
     * @return bool Odoo XML-RPC response
     * @throws \Exception Throws exception when request fail
     */
    public function write($model, array $ids, array $values)
    {
        // Sometimes the model need to wrap data with a key named VALS
        try {
            $response = $this->_write($model, $ids, $values, 'vals');
            // Extract response
            $response = (int) $response->value()->scalarval();
            return ($response === 1 ? TRUE : FALSE);
        } catch (\Exception $e) {
          $writeError = $e;
        }

        // And sometimes the model need to wrap data with a key named VALUES
        try {
            $response = $this->_write($model, $ids, $values, 'values');
            // Extract response
            $response = (int) $response->value()->scalarval();
            return ($response === 1 ? TRUE : FALSE);
        } catch (\Exception $e) {
          $writeError = $e;
        }

        throw $writeError;
        return FALSE;
    }

    /**
     * Create only message for write method
     * @param string $model Odoo model name
     * @param array $ids Data IDs
     * @param array $values New values
     * @param string $key Values wrapper
     * @return xmlrpcmsg
     */
    private function _write($model, array $ids, array $values, $key) {
        // format array which contains values
        $values = array($key => new xmlrpcval($values, xmlrpcval::$xmlrpcStruct));

        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_write, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($ids, xmlrpcval::$xmlrpcArray));
        $msg->addParam(new xmlrpcval($values, xmlrpcval::$xmlrpcStruct));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);

        return $response;
    }

    /**
     * Odoo XML-RPC product_id_change method
     * @param string $model Odoo model name
     * @param array $ids Data IDs
     * @return array|xmlrpcresp|\PhpXmlRpc\Response[] Odoo XML-RPC response
     * @throws \Exception Throws exception when request fail
     */
    public function product_id_change($model, array $ids)
    {
        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval(self::$_product_id_change, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($ids, xmlrpcval::$xmlrpcArray));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);
        $response = $this->_transform->toArray($response);

        return $response;
    }

    /**
     * Odoo XML-RPC execute method
     * @param string $model Odoo model name
     * @param string $method Custom method
     * @param array $data Request input data
     * @return xmlrpcresp|\PhpXmlRpc\Response[] Odoo XML-RPC response
     * @throws \Exception Throws exception when request fail
     */
    public function execute($model, $method, array $data)
    {
        $msg = $this->_createMessageHeader();
        $msg->addParam(new xmlrpcval($model, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($method, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($data, xmlrpcval::$xmlrpcStruct));

        $response = $this->_connection->create(self::$_object)->send($msg);
        $response = $this->_checkResponse($response);

        return $response;
    }

    /**
     * Message creator for XML-RPC request
     * @return xmlrpcmsg Message header
     */
    private function _createMessageHeader()
    {
        $msg = new xmlrpcmsg(self::$_execute);

        $msg->addParam(new xmlrpcval($this->_db, xmlrpcval::$xmlrpcString));
        $msg->addParam(new xmlrpcval($this->_uid(), xmlrpcval::$xmlrpcInt));
        $msg->addParam(new xmlrpcval($this->_password, xmlrpcval::$xmlrpcString));

        return $msg;
    }

    /**
     * Odoo XML-RPC return response
     * @param xmlrpcresp $response
     * @return xmlrpcresp Odoo XML-RPC response
     * @throws \Exception Throws exception when request fail
     */
    private function _checkResponse(xmlrpcresp $response)
    {
        if ($response->errno != 0) {
            throw new \Exception($response->faultString());
        }

        return $response;
    }

}


text:
# Minimizing bundle size

Learn more about the tools you can leverage to reduce the bundle size.

## Bundle size matters

The bundle size of MUI is taken very seriously. Size snapshots are taken
on every commit for every package and critical parts of those packages ([view the latest snapshot](/size-snapshot/)).
Combined with [dangerJS](https://danger.systems/js/) we can inspect
[detailed bundle size changes](https://github.com/mui/material-ui/pull/14638#issuecomment-466658459) on every Pull Request.

## When and how to use tree-shaking?

Tree-shaking of MUI works out of the box in modern frameworks.
MUI exposes its full API on the top-level `@mui` imports.
If you're using ES6 modules and a bundler that supports tree-shaking ([`webpack` >= 2.x](https://webpack.js.org/guides/tree-shaking/), [`parcel` with a flag](https://en.parceljs.org/cli.html#enable-experimental-scope-hoisting/tree-shaking-support)) you can safely use named imports and still get an optimized bundle size automatically:

```js
import { Button, TextField } from '@mui/material';
```

⚠ The following instructions are only needed if you want to optimize your development startup times or if you are using an older bundler
that doesn't support tree-shaking.

## Development environment

Development bundles can contain the full library which can lead to **slower startup times**.
This is especially noticeable if you import from `@mui/icons-material`.
Startup times can be approximately 6x slower than without named imports from the top-level API.

If this is an issue for you, you have various options:

### Option 1

You can use path imports to avoid pulling in unused modules.
For instance, use:

```js
// 🚀 Fast
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
```

instead of top-level imports (without a Babel plugin):

```js
import { Button, TextField } from '@mui/material';
```

This is the option we document in all the demos since it requires no configuration.
It is encouraged for library authors that are extending the components.
Head to [Option 2](#option-2) for the approach that yields the best DX and UX.

While importing directly in this manner doesn't use the exports in [the main file of `@mui/material`](https://unpkg.com/@mui/material), this file can serve as a handy reference as to which modules are public.

Be aware that we only support first and second-level imports.
Anything deeper is considered private and can cause issues, such as module duplication in your bundle.

```js
// ✅ OK
import { Add as AddIcon } from '@mui/icons-material';
import { Tabs } from '@mui/material';
//                         ^^^^^^^^ 1st or top-level

// ✅ OK
import AddIcon from '@mui/icons-material/Add';
import Tabs from '@mui/material/Tabs';
//                              ^^^^ 2nd level

// ❌ NOT OK
import TabIndicator from '@mui/material/Tabs/TabIndicator';
//                                           ^^^^^^^^^^^^ 3rd level
```

If you're using `eslint` you can catch problematic imports with the [`no-restricted-imports` rule](https://eslint.org/docs/rules/no-restricted-imports). The following `.eslintrc` configuration will highlight problematic imports from `@mui` packages:

```json
{
  "rules": {
    "no-restricted-imports": [
      "error",
      {
        "patterns": ["@mui/*/*/*", "!@mui/material/test-utils/*"]
      }
    ]
  }
}
```

### Option 2

This option provides the best User Experience and Developer Experience:

- UX: The Babel plugin enables top-level tree-shaking even if your bundler doesn't support it.
- DX: The Babel plugin makes startup time in dev mode as fast as Option 1.
- DX: This syntax reduces the duplication of code, requiring only a single import for multiple modules.
  Overall, the code is easier to read, and you are less likely to make a mistake when importing a new module.

```js
import { Button, TextField } from '@mui/material';
```

However, you need to apply the two following steps correctly.

#### 1. Configure Babel

Pick one of the following plugins:

- [babel-plugin-import](https://github.com/umijs/babel-plugin-import) with the following configuration:

  `yarn add -D babel-plugin-import`

  Create a `.babelrc.js` file in the root directory of your project:

  ```js
  const plugins = [
    [
      'babel-plugin-import',
      {
        libraryName: '@mui/material',
        libraryDirectory: '',
        camel2DashComponentName: false,
      },
      'core',
    ],
    [
      'babel-plugin-import',
      {
        libraryName: '@mui/icons-material',
        libraryDirectory: '',
        camel2DashComponentName: false,
      },
      'icons',
    ],
  ];

  module.exports = { plugins };
  ```

- [babel-plugin-direct-import](https://github.com/umidbekk/babel-plugin-direct-import) with the following configuration:

  `yarn add -D babel-plugin-direct-import`

  Create a `.babelrc.js` file in the root directory of your project:

  ```js
  const plugins = [
    [
      'babel-plugin-direct-import',
      { modules: ['@mui/material', '@mui/icons-material'] },
    ],
  ];

  module.exports = { plugins };
  ```

If you are using Create React App, you will need to use a couple of projects that let you use `.babelrc` configuration, without ejecting.

`yarn add -D react-app-rewired customize-cra`

Create a `config-overrides.js` file in the root directory:

```js
/* config-overrides.js */
/* eslint-disable react-hooks/rules-of-hooks */
const { useBabelRc, override } = require('customize-cra');

module.exports = override(useBabelRc());
```

If you wish, `babel-plugin-import` can be configured through `config-overrides.js` instead of `.babelrc` by using this [configuration](https://github.com/arackaf/customize-cra/blob/master/api.md#fixbabelimportslibraryname-options).

Modify your `package.json` commands:

```diff
  "scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test",
+   "test": "react-app-rewired test",
    "eject": "react-scripts eject"
}
```

Enjoy significantly faster start times.

#### 2. Convert all your imports

Finally, you can convert your existing codebase to this option with this [top-level-imports codemod](https://www.npmjs.com/package/@mui/codemod#top-level-imports).
It will perform the following diffs:

```diff
-import Button from '@mui/material/Button';
-import TextField from '@mui/material/TextField';
+import { Button, TextField } from '@mui/material';
```

## Available bundles

The package published on npm is **transpiled**, with [Babel](https://github.com/babel/babel), to take into account the [supported platforms](/material-ui/getting-started/supported-platforms/).

⚠ Developers are **strongly discouraged** to import from any of the other bundles directly.
Otherwise it's not guaranteed that dependencies used also use legacy or modern bundles.
Instead, use these bundles at the bundler level with e.g [Webpack's `resolve.alias`](https://webpack.js.org/configuration/resolve/#resolvealias):

```js
{
  resolve: {
    alias: {
      '@mui/base': '@mui/base/legacy',
      '@mui/lab': '@mui/lab/legacy',
      '@mui/material': '@mui/material/legacy',
      '@mui/styled-engine': '@mui/styled-engine/legacy',
      '@mui/system': '@mui/system/legacy',
    }
  }
}
```

### Modern bundle

The modern bundle can be found under the [`/modern` folder](https://unpkg.com/@mui/material/modern/).
It targets the latest released versions of evergreen browsers (Chrome, Firefox, Safari, Edge).
This can be used to make separate bundles targeting different browsers.

### Legacy bundle

If you need to support IE 11 you cannot use the default or modern bundle without transpilation.
However, you can use the legacy bundle found under the [`/legacy` folder](https://unpkg.com/@mui/material/legacy/).
You don't need any additional polyfills.


text:
/* File:     timer.h
 *
 * Purpose:  Define a macro that returns the number of seconds that
 *           have elapsed since some point in the past.  The timer
 *           should return times with microsecond accuracy.
 *
 * Note:     The argument passed to the GET_TIME macro should be
 *           a double, *not* a pointer to a double.
 *
 * Example:
 *    #include "timer.h"
 *    . . .
 *    double start, finish, elapsed;
 *    . . .
 *    GET_TIME(start);
 *    . . .
 *    Code to be timed
 *    . . .
 *    GET_TIME(finish);
 *    elapsed = finish - start;
 *    printf("The code to be timed took %e seconds\n", elapsed);
 *
 * IPP:  Section 3.6.1 (pp. 121 and ff.) and Section 6.1.2 (pp. 273 and ff.)
 */
#ifndef _TIMER_H_
#define _TIMER_H_

#include <sys/time.h>

/* The argument now should be a double (not a pointer to a double) */
#define GET_TIME(now) { \
   struct timeval t; \
   gettimeofday(&t, NULL); \
   now = t.tv_sec + t.tv_usec/1000000.0; \
}

#endif


text:
package org.twak.tweed;

import org.twak.utils.geom.ObjDump;

public interface IDumpObjs {
	public void dumpObj( ObjDump dump );
}


text:
package techreborn.api.recipe;

import com.google.common.collect.ImmutableList;
import net.minecraft.item.ItemStack;

public interface IRecipeCompact {

	ImmutableList<ItemStack> getItems(String name);
}