text:
from unittest import mock

import oslo_policy.policy
from oslo_utils.fixture import uuidsentinel as uuids

from glance.api import policy
from glance.tests import functional

class TestImagesPolicy(functional.SynchronousAPIBase):
    def setUp(self):
        super(TestImagesPolicy, self).setUp()
        self.policy = policy.Enforcer(suppress_deprecation_warnings=True)

    def set_policy_rules(self, rules):
        self.policy.set_rules(
            oslo_policy.policy.Rules.from_dict(rules),
            overwrite=True)

    def start_server(self):
        with mock.patch.object(policy, 'Enforcer') as mock_enf:
            mock_enf.return_value = self.policy
            super(TestImagesPolicy, self).start_server()

    def test_image_update_basic(self):
        self.start_server()
        image_id = self._create_and_upload()

        # First make sure image update works with the default policy
        resp = self.api_patch('/v2/images/%s' % image_id,
                              {'op': 'add',
                               'path': '/mykey1',
                               'value': 'foo'})
        self.assertEqual(200, resp.status_code, resp.text)
        self.assertEqual(
            'foo',
            self.api_get('/v2/images/%s' % image_id).json['mykey1'])

        # Now disable modify_image permissions and make sure any other
        # attempts fail
        self.set_policy_rules({'get_image': '',
                               'modify_image': '!'})

        # Add should fail
        resp = self.api_patch('/v2/images/%s' % image_id,
                              {'op': 'add',
                               'path': '/mykey2',
                               'value': 'foo'})
        self.assertEqual(403, resp.status_code)
        self.assertNotIn(
            'mykey2',
            self.api_get('/v2/images/%s' % image_id).json)

        # Replace should fail, old value should persist
        resp = self.api_patch('/v2/images/%s' % image_id,
                              {'op': 'replace',
                               'path': '/mykey1',
                               'value': 'bar'})
        self.assertEqual(403, resp.status_code)
        self.assertEqual(
            'foo',
            self.api_get('/v2/images/%s' % image_id).json['mykey1'])

        # Remove should fail, old value should persist
        resp = self.api_patch('/v2/images/%s' % image_id,
                              {'op': 'remove',
                               'path': '/mykey1'})
        self.assertEqual(403, resp.status_code)
        self.assertEqual(
            'foo',
            self.api_get('/v2/images/%s' % image_id).json['mykey1'])

        # Now disable get_image permissions and we should get a 404
        # instead of a 403 when trying to do the same operation as above.
        # Remove should fail, old value should persist
        self.set_policy_rules({'get_image': '!',
                               'modify_image': '!'})
        resp = self.api_patch('/v2/images/%s' % image_id,
                              {'op': 'remove',
                               'path': '/mykey1'})
        self.assertEqual(404, resp.status_code)

    @mock.patch('glance.location._check_image_location', new=lambda *a: 0)
    @mock.patch('glance.location.ImageRepoProxy._set_acls', new=lambda *a: 0)
    def test_image_update_locations(self):
        self.config(show_multiple_locations=True)
        self.start_server()
        image_id = self._create_and_upload()

        # First make sure we can add and delete locations
        resp = self.api_patch('/v2/images/%s' % image_id,
                              {'op': 'add',
                               'path': '/locations/0',
                               'value': {'url': 'http://foo.bar',
                                         'metadata': {}}})
        self.assertEqual(200, resp.status_code, resp.text)
        self.assertEqual(2,
                         len(self.api_get(
                             '/v2/images/%s' % image_id).json['locations']))
        self.assertEqual(
            'http://foo.bar',
            self.api_get(
                '/v2/images/%s' % image_id).json['locations'][1]['url'])

        resp = self.api_patch('/v2/images/%s' % image_id,
                              {'op': 'remove',
                               'path': '/locations/0'})
        self.assertEqual(200, resp.status_code, resp.text)
        self.assertEqual(1,
                         len(self.api_get(
                             '/v2/images/%s' % image_id).json['locations']))

        # Add another while we still can so we can try to delete it below
        resp = self.api_patch('/v2/images/%s' % image_id,
                              {'op': 'add',
                               'path': '/locations/0',
                               'value': {'url': 'http://foo.baz',
                                         'metadata': {}}})
        self.assertEqual(200, resp.status_code, resp.text)
        self.assertEqual(2,
                         len(self.api_get(
                             '/v2/images/%s' % image_id).json['locations']))

        # Now disable set/delete_image_location permissions and make
        # sure any other attempts fail
        self.set_policy_rules({'get_image': '',
                               'get_image_location': '',
                               'set_image_location': '!',
                               'delete_image_location': '!'})

        # Make sure we cannot delete the above or add another
        resp = self.api_patch('/v2/images/%s' % image_id,
                              {'op': 'remove',
                               'path': '/locations/0'})
        self.assertEqual(403, resp.status_code, resp.text)
        self.assertEqual(2,
                         len(self.api_get(
                             '/v2/images/%s' % image_id).json['locations']))

        resp = self.api_patch('/v2/images/%s' % image_id,
                              {'op': 'add',
                               'path': '/locations/0',
                               'value': {'url': 'http://foo.baz',
                                         'metadata': {}}})
        self.assertEqual(403, resp.status_code, resp.text)
        self.assertEqual(2,
                         len(self.api_get(
                             '/v2/images/%s' % image_id).json['locations']))

    def test_image_get(self):
        self.start_server()

        image_id = self._create_and_upload()

        # Make sure we can get the image
        image = self.api_get('/v2/images/%s' % image_id).json
        self.assertEqual(image_id, image['id'])

        # Make sure we can list the image
        images = self.api_get('/v2/images').json['images']
        self.assertEqual(1, len(images))
        self.assertEqual(image_id, images[0]['id'])

        # Now disable get_images but allow get_image
        self.set_policy_rules({'get_images': '!',
                               'get_image': ''})

        # We should not be able to list, but still fetch the image by id
        resp = self.api_get('/v2/images')
        self.assertEqual(403, resp.status_code)
        image = self.api_get('/v2/images/%s' % image_id).json
        self.assertEqual(image_id, image['id'])

        # Now disable get_image but allow get_images
        self.set_policy_rules({'get_images': '',
                               'get_image': '!'})

        # We should be able to list, but not actually see the image in the list
        images = self.api_get('/v2/images').json['images']
        self.assertEqual(0, len(images))
        resp = self.api_get('/v2/images/%s' % image_id)
        self.assertEqual(404, resp.status_code)

        # Now disable both get_image and get_images
        self.set_policy_rules({'get_images': '!',
                               'get_image': '!'})

        # We should not be able to list or fetch by id
        resp = self.api_get('/v2/images')
        self.assertEqual(403, resp.status_code)
        resp = self.api_get('/v2/images/%s' % image_id)
        self.assertEqual(404, resp.status_code)

    def test_image_create(self):
        self.start_server()

        # Make sure we can create an image
        self.assertEqual(201, self._create().status_code)

        # Now disable add_image and make sure we get 403
        self.set_policy_rules({'add_image': '!'})

        self.assertEqual(403, self._create().status_code)

    def test_image_create_by_another(self):
        self.start_server()

        # NOTE(danms): There is no policy override in this test,
        # specifically to test that the defaults (for rbac and
        # non-rbac) properly catch the attempt by a non-admin to
        # create an image owned by someone else.

        image = {'name': 'foo',
                 'container_format': 'bare',
                 'disk_format': 'raw',
                 'owner': 'someoneelse'}
        resp = self.api_post('/v2/images',
                             json=image,
                             headers={'X-Roles': 'member'})
        # Make sure we get the expected owner-specific error message
        self.assertIn("You are not permitted to create images "
                      "owned by 'someoneelse'", resp.text)

    def test_image_delete(self):
        self.start_server()

        image_id = self._create_and_upload()

        # Make sure we can delete the image
        resp = self.api_delete('/v2/images/%s' % image_id)
        self.assertEqual(204, resp.status_code)

        # Make sure it is really gone
        resp = self.api_get('/v2/images/%s' % image_id)
        self.assertEqual(404, resp.status_code)

        # Make sure we get a 404 trying to delete a non-existent image
        resp = self.api_delete('/v2/images/%s' % image_id)
        self.assertEqual(404, resp.status_code)

        image_id = self._create_and_upload()

        # Now disable delete permissions, but allow get_image
        self.set_policy_rules({'get_image': '',
                               'delete_image': '!'})

        # Make sure delete returns 403 because we can see the image,
        # just not delete it
        resp = self.api_delete('/v2/images/%s' % image_id)
        self.assertEqual(403, resp.status_code)

        # Now disable delete permissions, including get_image
        self.set_policy_rules({'get_image': '!',
                               'delete_image': '!'})

        # Make sure delete returns 404 because we can not see nor
        # delete it
        resp = self.api_delete('/v2/images/%s' % image_id)
        self.assertEqual(404, resp.status_code)

        # Now allow delete, but disallow get_image, just to prove that
        # you do not need get_image in order to be granted delete, and
        # that we only use it for error code determination if
        # permission is denied.
        self.set_policy_rules({'get_image': '!',
                               'delete_image': ''})

        # Make sure delete returns 204 because even though we can not
        # see the image, we can delete it
        resp = self.api_delete('/v2/images/%s' % image_id)
        self.assertEqual(204, resp.status_code)

    def test_image_upload(self):
        self.start_server()

        # Make sure we can upload the image
        self._create_and_upload(expected_code=204)

        # Now disable upload permissions, but allow get_image
        self.set_policy_rules({
            'add_image': '',
            'get_image': '',
            'upload_image': '!'
        })

        # Make sure upload returns 403 because we can see the image,
        # just not upload data to it
        self._create_and_upload(expected_code=403)

        # Now disable upload permissions, including get_image
        self.set_policy_rules({
            'add_image': '',
            'get_image': '!',
            'upload_image': '!',
        })

        # Make sure upload returns 404 because we can not see nor
        # upload data to it
        self._create_and_upload(expected_code=404)

        # Now allow upload, but disallow get_image, just to prove that
        # you do not need get_image in order to be granted upload, and
        # that we only use it for error code determination if
        # permission is denied.
        self.set_policy_rules({
            'add_image': '',
            'get_image': '!',
            'upload_image': ''})

        # Make sure upload returns 204 because even though we can not
        # see the image, we can upload data to it
        self._create_and_upload(expected_code=204)

    def test_image_download(self):
        # NOTE(abhishekk): These tests are running without cache middleware
        self.start_server()
        image_id = self._create_and_upload()

        # First make sure we can download image
        path = '/v2/images/%s/file' % image_id
        response = self.api_get(path)
        self.assertEqual(200, response.status_code)
        self.assertEqual('IMAGEDATA', response.text)

        # Now disable download permissions, but allow get_image
        self.set_policy_rules({
            'get_image': '',
            'download_image': '!'
        })

        # Make sure download returns 403 because we can see the image,
        # just not download it
        response = self.api_get(path)
        self.assertEqual(403, response.status_code)

        # Now disable download permissions, including get_image
        self.set_policy_rules({
            'get_image': '!',
            'download_image': '!',
        })

        # Make sure download returns 404 because we can not see nor
        # download it
        response = self.api_get(path)
        self.assertEqual(404, response.status_code)

        # Now allow download, but disallow get_image, just to prove that
        # you do not need get_image in order to be granted download, and
        # that we only use it for error code determination if
        # permission is denied.
        self.set_policy_rules({
            'get_image': '!',
            'download_image': ''})

        # Make sure download returns 200 because even though we can not
        # see the image, we can download it
        response = self.api_get(path)
        self.assertEqual(200, response.status_code)
        self.assertEqual('IMAGEDATA', response.text)

    def test_image_stage(self):
        self.start_server()
        # First make sure we can perform staging operation
        self._create_and_stage(expected_code=204)

        # Now disable get_image permissions, but allow modify_image
        # should return 204 as well, means even if we can not see
        # image details, we can stage data for it.
        self.set_policy_rules({
            'get_image': '!',
            'modify_image': '',
            'add_image': ''
        })
        self._create_and_stage(expected_code=204)

        # Now allow get_image and disable modify_image should return 403
        self.set_policy_rules({
            'get_image': '',
            'modify_image': '!',
            'add_image': ''
        })
        self._create_and_stage(expected_code=403)

        # Now disabling both permissions will return 404
        self.set_policy_rules({
            'get_image': '!',
            'modify_image': '!',
            'add_image': ''
        })
        self._create_and_stage(expected_code=404)

        # create shared visibility image and stage by 2nd project should
        # return 404 until it is actually shared with that project.
        self.set_policy_rules({
            'get_image': '',
            'modify_image': '!',
            'add_image': '',
            'add_member': ''
        })
        resp = self.api_post('/v2/images',
                             json={'name': 'foo',
                                   'container_format': 'bare',
                                   'disk_format': 'raw',
                                   'visibility': 'shared'})
        self.assertEqual(201, resp.status_code, resp.text)
        image = resp.json
        # Now stage data using another project details
        headers = self._headers({
            'X-Project-Id': 'fake-tenant-id',
            'Content-Type': 'application/octet-stream'
        })
        resp = self.api_put(
            '/v2/images/%s/stage' % image['id'],
            headers=headers,
            data=b'IMAGEDATA')
        self.assertEqual(404, resp.status_code)

        # Now share image with another project and then staging
        # data by that project should return 403
        path = '/v2/images/%s/members' % image['id']
        data = {
            'member': uuids.random_member
        }
        response = self.api_post(path, json=data)
        member = response.json
        self.assertEqual(200, response.status_code)
        self.assertEqual(image['id'], member['image_id'])

        # Now stage data using another project details
        headers = self._headers({
            'X-Project-Id': uuids.random_member,
            'X-Roles': 'member',
            'Content-Type': 'application/octet-stream'
        })
        resp = self.api_put(
            '/v2/images/%s/stage' % image['id'],
            headers=headers,
            data=b'IMAGEDATA')
        self.assertEqual(403, resp.status_code)

    def test_image_deactivate(self):
        self.start_server()

        image_id = self._create_and_upload()

        # Make sure we can deactivate the image
        resp = self.api_post('/v2/images/%s/actions/deactivate' % image_id)
        self.assertEqual(204, resp.status_code)

        # Make sure it is really deactivated
        resp = self.api_get('/v2/images/%s' % image_id)
        self.assertEqual('deactivated', resp.json['status'])

        # Create another image
        image_id = self._create_and_upload()

        # Now disable deactivate permissions, but allow get_image
        self.set_policy_rules({'get_image': '',
                               'deactivate': '!'})

        # Make sure deactivate returns 403 because we can see the image,
        # just not deactivate it
        resp = self.api_post('/v2/images/%s/actions/deactivate' % image_id)
        self.assertEqual(403, resp.status_code)

        # Now disable deactivate permissions, including get_image
        self.set_policy_rules({'get_image': '!',
                               'deactivate': '!'})

        # Make sure deactivate returns 404 because we can not see nor
        # reactivate it
        resp = self.api_post('/v2/images/%s/actions/deactivate' % image_id)
        self.assertEqual(404, resp.status_code)

        # Now allow deactivate, but disallow get_image, just to prove that
        # you do not need get_image in order to be granted deactivate, and
        # that we only use it for error code determination if
        # permission is denied.
        self.set_policy_rules({'get_image': '!',
                               'deactivate': ''})

        # Make sure deactivate returns 204 because even though we can not
        # see the image, we can deactivate it
        resp = self.api_post('/v2/images/%s/actions/deactivate' % image_id)
        self.assertEqual(204, resp.status_code)

        # Make sure you can not deactivate image using non-admin role of
        # different project
        self.set_policy_rules({
            'get_image': '',
            'modify_image': '',
            'add_image': '',
            'upload_image': '',
            'add_member': '',
            'deactivate': '',
            'publicize_image': '',
            'communitize_image': ''
        })
        headers = self._headers({
            'X-Project-Id': 'fake-project-id',
            'X-Roles': 'member'
        })
        for visibility in ('community', 'shared', 'private', 'public'):
            image_id = self._create_and_upload(visibility=visibility)
            resp = self.api_post(
                '/v2/images/%s/actions/deactivate' % image_id, headers=headers)
            # 'shared' image will return 404 until it is not shared with
            # project accessing it
            if visibility == 'shared':
                self.assertEqual(404, resp.status_code)
                # Now lets share the image and try to deactivate it
                share_path = '/v2/images/%s/members' % image_id
                data = {
                    'member': 'fake-project-id'
                }
                response = self.api_post(share_path, json=data)
                member = response.json
                self.assertEqual(200, response.status_code)
                self.assertEqual(image_id, member['image_id'])

                # Now ensure deactivating image by another tenant will
                # return 403
                resp = self.api_post(
                    '/v2/images/%s/actions/deactivate' % image_id,
                    headers=headers)
                self.assertEqual(403, resp.status_code)
            elif visibility == 'private':
                # private image will also return 404 as it is not visible
                self.assertEqual(404, resp.status_code)
            else:
                # public and community visibility will return 403
                self.assertEqual(403, resp.status_code)

    def test_image_reactivate(self):
        self.start_server()

        image_id = self._create_and_upload()

        # deactivate the image
        resp = self.api_post('/v2/images/%s/actions/deactivate' % image_id)
        self.assertEqual(204, resp.status_code)

        # Make sure it is really deactivated
        resp = self.api_get('/v2/images/%s' % image_id)
        self.assertEqual('deactivated', resp.json['status'])

        # Make sure you can reactivate the image
        resp = self.api_post('/v2/images/%s/actions/reactivate' % image_id)
        self.assertEqual(204, resp.status_code)

        # Make sure it is really reactivated
        resp = self.api_get('/v2/images/%s' % image_id)
        self.assertEqual('active', resp.json['status'])

        # Deactivate it again to test further scenarios
        resp = self.api_post('/v2/images/%s/actions/deactivate' % image_id)
        self.assertEqual(204, resp.status_code)

        # Now disable reactivate permissions, but allow get_image
        self.set_policy_rules({'get_image': '',
                               'reactivate': '!'})

        # Make sure reactivate returns 403 because we can see the image,
        # just not reactivate it
        resp = self.api_post('/v2/images/%s/actions/reactivate' % image_id)
        self.assertEqual(403, resp.status_code)

        # Now disable reactivate permissions, including get_image
        self.set_policy_rules({'get_image': '!',
                               'reactivate': '!'})

        # Make sure reactivate returns 404 because we can not see nor
        # reactivate it
        resp = self.api_post('/v2/images/%s/actions/reactivate' % image_id)
        self.assertEqual(404, resp.status_code)

        # Now allow reactivate, but disallow get_image, just to prove that
        # you do not need get_image in order to be granted reactivate, and
        # that we only use it for error code determination if
        # permission is denied.
        self.set_policy_rules({'get_image': '!',
                               'reactivate': ''})

        # Make sure reactivate returns 204 because even though we can not
        # see the image, we can reactivate it
        resp = self.api_post('/v2/images/%s/actions/reactivate' % image_id)
        self.assertEqual(204, resp.status_code)

        # Make sure you can not reactivate image using non-admin role of
        # different project
        self.set_policy_rules({
            'get_image': '',
            'modify_image': '',
            'add_image': '',
            'upload_image': '',
            'add_member': '',
            'deactivate': '',
            'reactivate': '',
            'publicize_image': '',
            'communitize_image': ''
        })
        headers = self._headers({
            'X-Project-Id': 'fake-project-id',
            'X-Roles': 'member'
        })
        for visibility in ('public', 'community', 'shared', 'private'):
            image_id = self._create_and_upload(visibility=visibility)
            # deactivate the image
            resp = self.api_post(
                '/v2/images/%s/actions/deactivate' % image_id)
            self.assertEqual(204, resp.status_code)

            # try to reactivate the image
            resp = self.api_post(
                '/v2/images/%s/actions/reactivate' % image_id, headers=headers)

            # 'shared' image will return 404 until it is not shared with
            # project accessing it
            if visibility == 'shared':
                self.assertEqual(404, resp.status_code)
                # Now lets share the image and try to reactivate it
                share_path = '/v2/images/%s/members' % image_id
                data = {
                    'member': 'fake-project-id'
                }
                response = self.api_post(share_path, json=data)
                member = response.json
                self.assertEqual(200, response.status_code)
                self.assertEqual(image_id, member['image_id'])

                # Now ensure reactivating image by another tenant will
                # return 403
                resp = self.api_post(
                    '/v2/images/%s/actions/reactivate' % image_id,
                    headers=headers)
                self.assertEqual(403, resp.status_code)
            elif visibility == 'private':
                # private image will also return 404 as it is not visible
                self.assertEqual(404, resp.status_code)
            else:
                # public and community visibility will return 403
                self.assertEqual(403, resp.status_code)

    def test_delete_from_store(self):
        self.start_server()
        # First create image in multiple stores
        image_id = self._create_and_import(stores=['store1', 'store2',
                                                   'store3'])

        # Make sure we are able to delete image from the specific store
        path = "/v2/stores/store1/%s" % image_id
        response = self.api_delete(path)
        self.assertEqual(204, response.status_code)

        # Disable get_image_location and verify you will get 403
        self.set_policy_rules({
            'get_image': '',
            'delete_image_location': '',
            'get_image_location': '!'
        })
        path = "/v2/stores/store2/%s" % image_id
        response = self.api_delete(path)
        self.assertEqual(403, response.status_code)

        # Disable delete_image_location and verify you will get 403
        self.set_policy_rules({
            'get_image': '',
            'delete_image_location': '!',
            'get_image_location': ''
        })
        path = "/v2/stores/store2/%s" % image_id
        response = self.api_delete(path)
        self.assertEqual(403, response.status_code)

        # Disabling all, you will get 404
        self.set_policy_rules({
            'get_image': '!',
            'delete_image_location': '!',
            'get_image_location': '!'
        })
        path = "/v2/stores/store2/%s" % image_id
        response = self.api_delete(path)
        self.assertEqual(404, response.status_code)

        # Now allow delete_image_location and get_image_location, but disallow
        # get_image, just to prove that you do not need get_image in order
        # to be granted delete image from particular store, and
        # that we only use it for error code determination if
        # permission is denied.
        self.set_policy_rules({
            'get_image': '!',
            'delete_image_location': '',
            'get_image_location': ''
        })
        path = "/v2/stores/store2/%s" % image_id
        response = self.api_delete(path)
        self.assertEqual(204, response.status_code)

        # deleting image with non-admin will get 403
        self.set_policy_rules({
            'get_image': '',
            'delete_image_location': '',
            'get_image_location': ''
        })
        headers = self._headers({
            'X-Roles': 'member'
        })

        path = "/v2/stores/store2/%s" % image_id
        response = self.api_delete(path, headers=headers)
        self.assertEqual(403, response.status_code)

    def test_copy_image(self):
        self.start_server()
        # create image using import
        image_id = self._create_and_import(
            stores=['store1'], visibility='public')

        # Make sure you can copy image to another store
        self.set_policy_rules({
            'copy_image': 'role:admin',
            'get_image': '',
            'modify_image': ''
        })
        store_to_copy = ["store2"]
        response = self._import_copy(image_id, store_to_copy)
        self.assertEqual(202, response.status_code)
        self._wait_for_import(image_id)
        self.assertEqual('success', self._get_latest_task(image_id)['status'])

        # Now disable copy image and see you will get 403 Forbidden
        store_to_copy = ["store3"]
        self.set_policy_rules({
            'copy_image': '!',
            'get_image': '',
            'modify_image': ''
        })
        response = self._import_copy(image_id, store_to_copy)
        self.assertEqual(403, response.status_code)

        # Verify that non-admin but member of same project can not copy image
        self.set_policy_rules({
            'copy_image': 'role:admin',
            'get_image': '',
            'modify_image': ''
        })
        headers = self._headers({'X-Roles': 'member'})
        response = self._import_copy(image_id, store_to_copy,
                                     headers=headers)
        self.assertEqual(403, response.status_code)

        # Verify that non-owner can not copy image
        self.set_policy_rules({
            'copy_image': 'role:admin',
            'get_image': '',
            'modify_image': ''
        })
        headers = self._headers({
            'X-Roles': 'member',
            'X-Project-Id': 'fake-project-id'
        })
        response = self._import_copy(image_id, store_to_copy,
                                     headers=headers)
        self.assertEqual(403, response.status_code)

        # Now disable copy image and get_image and see you will get
        # 404 NotFound
        self.set_policy_rules({
            'copy_image': '!',
            'get_image': '!',
            'modify_image': ''
        })
        store_to_copy = ["store3"]
        print(self.policy.rules.items())
        response = self._import_copy(image_id, store_to_copy)
        self.assertEqual(404, response.status_code)

    def test_import_glance_direct(self):
        self.start_server()
        # create image and stage data to it
        image_id = self._create_and_stage(visibility='public')

        # Make sure you can import using glance-direct
        self.set_policy_rules({
            'get_image': '',
            'communitize_image': '',
            'add_image': '',
            'modify_image': ''
        })
        store_to_import = ['store1']
        response = self._import_direct(image_id, store_to_import)
        self.assertEqual(202, response.status_code)
        self._wait_for_import(image_id)
        self.assertEqual('success', self._get_latest_task(image_id)['status'])

        # Make sure you can import data to image using non-admin role
        image_id = self._create_and_stage(visibility='community')
        headers = self._headers({'X-Roles': 'member'})
        response = self._import_direct(image_id, store_to_import,
                                       headers=headers)
        self.assertEqual(202, response.status_code)
        self._wait_for_import(image_id)
        self.assertEqual('success', self._get_latest_task(image_id)['status'])

        # Make sure you can not import data to image using non-admin role of
        # different project
        image_id = self._create_and_stage(visibility='community')
        # Make sure you will get 403 Forbidden
        self.set_policy_rules({
            'get_image': '',
            'modify_image': '!'
        })
        headers = self._headers({
            'X-Roles': 'member',
            'X-Project-Id': 'fake-project-id'
        })
        response = self._import_direct(image_id, store_to_import,
                                       headers=headers)
        self.assertEqual(403, response.status_code)

        # disabling both get_image and modify_image should return 404 NotFound
        self.set_policy_rules({
            'get_image': '!',
            'modify_image': '!'
        })
        headers = self._headers({
            'X-Roles': 'member',
            'X-Project-Id': 'fake-project-id'
        })
        response = self._import_direct(image_id, store_to_import,
                                       headers=headers)
        self.assertEqual(404, response.status_code)

    def _test_image_ownership(self, headers, method):
        self.set_policy_rules({
            'get_image': '',
            'add_image': '',
            'publicize_image': '',
            'communitize_image': '',
            'add_member': '',
        })

        for visibility in ('community', 'public', 'shared'):
            path = "/v2/images"
            data = {
                'name': '%s-image' % visibility,
                'visibility': visibility,
            }
            # create image
            response = self.api_post(path, json=data)
            image = response.json
            self.assertEqual(201, response.status_code)
            self.assertEqual(visibility, image['visibility'])

            # share the image if visibility is shared
            if visibility == 'shared':
                path = '/v2/images/%s/members' % image['id']
                data = {
                    'member': 'fake-project-id'
                }
                response = self.api_post(path,
                                         json=data)
                self.assertEqual(200, response.status_code)

            # Add/Delete tag
            path = '/v2/images/%s/tags/Test_Tag_2' % image['id']
            response = self.api_request(method, path, headers=headers)
            self.assertEqual(403, response.status_code)

    def test_image_tag_update(self):
        self.start_server()
        # Create image
        image_id = self._create_and_upload()

        # Make sure we will be able to add tags for the image
        path = '/v2/images/%s/tags/Test_Tag' % image_id
        response = self.api_put(path)
        self.assertEqual(204, response.status_code)
        # Make sure tag is added to image
        path = '/v2/images/%s' % image_id
        response = self.api_get(path)
        image = response.json
        self.assertEqual(['Test_Tag'], image['tags'])

        # Disable get_image and modify_image should give us 404 Not Found
        self.set_policy_rules({
            'get_image': '!',
            'modify_image': '!'
        })
        path = '/v2/images/%s/tags/Test_Tag_2' % image_id
        response = self.api_put(path)
        self.assertEqual(404, response.status_code)

        # Allow get_image and disable modify_image should give us
        # 403 Forbidden
        self.set_policy_rules({
            'get_image': '',
            'modify_image': '!'
        })
        path = '/v2/images/%s/tags/Test_Tag_2' % image_id
        response = self.api_put(path)
        self.assertEqual(403, response.status_code)

        # Adding tag by another project (non-admin user) should return
        # 404 Not Found for private image
        self.set_policy_rules({
            'get_image': '',
            'modify_image': ''
        })
        # Note for other reviewers, these tests runs by default using
        # admin role, to test this scenario we need image
        # of current project to be accessed by other projects non-admin
        # user.
        headers = self._headers({
            'X-Project-Id': 'fake-project-id',
            'X-Roles': 'member',
        })
        path = '/v2/images/%s/tags/Test_Tag_2' % image_id
        response = self.api_put(path, headers=headers)
        self.assertEqual(404, response.status_code)

        # Adding tag by another project (non-admin user) should return
        # 403 Not Found for other than private image
        self._test_image_ownership(headers, 'PUT')

    def test_image_tag_delete(self):
        self.start_server()
        # Create image
        image_id = self._create_and_upload()

        # Make sure we will be able to add tags for the image
        path = '/v2/images/%s/tags/Test_Tag_1' % image_id
        response = self.api_put(path)
        self.assertEqual(204, response.status_code)
        # add another tag while we can
        path = '/v2/images/%s/tags/Test_Tag_2' % image_id
        response = self.api_put(path)
        self.assertEqual(204, response.status_code)

        # Make sure tags are added to image
        path = '/v2/images/%s' % image_id
        response = self.api_get(path)
        image = response.json
        self.assertItemsEqual(['Test_Tag_1', 'Test_Tag_2'], image['tags'])

        # Now delete tag from image
        path = '/v2/images/%s/tags/Test_Tag_1' % image_id
        response = self.api_delete(path)
        self.assertEqual(204, response.status_code)

        # Make sure tag is deleted
        path = '/v2/images/%s' % image_id
        response = self.api_get(path)
        image = response.json
        self.assertNotIn('Test_Tag_1', image['tags'])

        # Disable get_image and modify_image should give us 404 Not Found
        self.set_policy_rules({
            'get_image': '!',
            'modify_image': '!'
        })
        path = '/v2/images/%s/tags/Test_Tag_2' % image_id
        response = self.api_delete(path)
        self.assertEqual(404, response.status_code)

        # Allow get_image and disable modify_image should give us
        # 403 Forbidden
        self.set_policy_rules({
            'get_image': '',
            'modify_image': '!'
        })
        path = '/v2/images/%s/tags/Test_Tag_2' % image_id
        response = self.api_delete(path)
        self.assertEqual(403, response.status_code)

        # Deleting tag by another project (non-admin user) should return
        # 404 Not Found for private image
        self.set_policy_rules({
            'get_image': '',
            'modify_image': ''
        })
        # Note for other reviewers, these tests runs by default using
        # admin role, to test this scenario we need image
        # of current project to be accessed by other projects non-admin
        # user.
        headers = self._headers({
            'X-Project-Id': 'fake-project-id',
            'X-Roles': 'member',
        })
        path = '/v2/images/%s/tags/Test_Tag_2' % image_id
        response = self.api_delete(path, headers=headers)
        self.assertEqual(404, response.status_code)

        # Deleting tag by another project (non-admin user) should return
        # 403 Not Found for other than private image
        self._test_image_ownership(headers, 'DELETE')

    def test_get_task_info(self):
        self.start_server()
        image_id = self._create_and_import(
            stores=['store1'], visibility='public')

        # Make sure you can get task information of that image
        path = '/v2/images/%s/tasks' % image_id
        response = self.api_get(path)
        self.assertEqual(200, response.status_code)

        # Disable get_image should give us 404 Not Found
        self.set_policy_rules({'get_image': '!'})
        path = '/v2/images/%s/tasks' % image_id
        response = self.api_get(path)
        self.assertEqual(404, response.status_code)


text:
package ca.dotapps.radar.ui.main;

import android.content.Context;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;

import java.util.Collections;
import java.util.List;

import javax.inject.Inject;

import butterknife.Bind;
import butterknife.ButterKnife;
import ca.dotapps.radar.R;
import ca.dotapps.radar.data.model.Trend;
import ca.dotapps.radar.databinding.ActivityMainBinding;
import ca.dotapps.radar.ui.base.BaseActivity;
import ca.dotapps.radar.util.DialogFactory;

public class MainActivity extends BaseActivity implements MainMvpView {

    private static final String EXTRA_TRIGGER_SYNC_FLAG =
            "ca.dotapps.radar.ui.main.MainActivity.EXTRA_TRIGGER_SYNC_FLAG";

    @Inject
    MainPresenter mMainPresenter;
    @Inject
    TrendAdapter mTrendsAdapter;

    @Bind(R.id.swipe_container)
    SwipeRefreshLayout mSwipeRefresh;
    @Bind(R.id.recycler_view)
    RecyclerView mRecyclerView;

    public static Intent getStartIntent(Context context, boolean triggerDataSyncOnCreate) {
        Intent intent = new Intent(context, MainActivity.class);
        intent.putExtra(EXTRA_TRIGGER_SYNC_FLAG, triggerDataSyncOnCreate);
        return intent;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getActivityComponent().inject(this);
        ActivityMainBinding binding =  DataBindingUtil.setContentView(this, R.layout.activity_main);

        ButterKnife.bind(this);

        setupRecycler();
        setupSwipeToRefresh();

        mMainPresenter.attachView(this);
        mMainPresenter.loadTrends();

        if (getIntent().getBooleanExtra(EXTRA_TRIGGER_SYNC_FLAG, true)) {
            mMainPresenter.reloadTrends(MainActivity.this);
        }
    }

    private void setupRecycler() {
        mRecyclerView.setAdapter(mTrendsAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    }

    private void setupSwipeToRefresh() {
        mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                mMainPresenter.reloadTrends(MainActivity.this);
            }
        });
        mSwipeRefresh.setColorSchemeResources(android.R.color.holo_blue_bright,
                android.R.color.holo_green_light,
                android.R.color.holo_orange_light,
                android.R.color.holo_red_light);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        mMainPresenter.detachView();
    }

    /*****
     * MVP View methods implementation
     *****/

    @Override
    public void showTrends(List<Trend> trends) {
        mTrendsAdapter.setTrends(trends);
        mTrendsAdapter.notifyDataSetChanged();
        hideLoading();
    }

    private void hideLoading() {
        mSwipeRefresh.setRefreshing(false);
    }

    @Override
    public void showError() {
        DialogFactory.createGenericErrorDialog(this, getString(R.string.error_loading_data))
                .show();
        hideLoading();
    }

    @Override
    public void showTrendsEmpty() {
        mTrendsAdapter.setTrends(Collections.<Trend>emptyList());
        mTrendsAdapter.notifyDataSetChanged();
        Toast.makeText(this, R.string.empty_content, Toast.LENGTH_LONG).show();
    }
}

redpajama_set_name: RedPajamaGithub


text:
package net.zhanghc.nlp.base;

import net.zhanghc.nlp.annotation.Relation;

public class Dependency {
	protected int govIdx;
	protected int depIdx;

	protected Relation relation;

}


text:
@INCLUDE_COMMON@

echo
echo RUN ALL TESTS
echo

check_version
echo

cd "@CMAKE_INSTALL_PREFIX@/@TARGET_TOOL_EXEC_FOLDER@"

nbTests="0"
nbFailed=""

cleanup() {
	rm -rf "$EXPORT_DIR"
}

EXPORT_DIR="$(mktempdir_elektra)"
export_config "$EXPORT_DIR"

# Parse optional argument `-v`
OPTIND=1
while getopts "v" option; do
	case "$option" in
	v)
		verbose=0
		;;
	esac
done
shift "$((OPTIND - 1))"

for t in test* check*; do
	if [ $t = "testmod_zeromqsend" ]; then
		echo
		printf "Skipping $t, see 'doc/todo/TESTING'\n"
		echo
		continue
	fi

	echo "Running $t"

	OUTPUT="$("$KDB" $t 2>&1)"
	status=$?

	if [ $status != 0 ] || [ $verbose ]; then
		echo
		printf '%s' "$OUTPUT"
		echo
	fi

	if [ $status != "0" ]; then
		nbError=$((nbError + 1))
		nbFailed="$nbFailed\n$t"
		echo error: $t
		echo
	fi
	nbTests=$((nbTests + 1))

	export_check "$EXPORT_DIR" "$t"
done

if [ $nbError != "0" ]; then
	echo
	printf "Following test cases failed: $nbFailed\n"
	echo
fi

# fake the number of tests:
nbTest=$nbTests

end_script all


text:
package com.flaptor.indextank.index.scorer;

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

import com.flaptor.indextank.index.DocId;

/**
 * Device that holds special score boosts for every document.
 * Each {@link BoostsManager} is defined with a specific number of
 * boosts per document. No document can be updated for more boosts
 * than that number
 *
 * @author iperez
 *
 */
public interface BoostsManager {
	/**
	 * Specify the values of the boosts for a document, including its timestamp.
	 * This is accomplished by passing the dynamicBoosts parameter with a Map from the boost index (zero based) to the boost value (a double).
	 * In this map, no index can be larger than the number of available boosts the {@link BoostsManager} minus one (since it is zero based).
	 * If no boost was ever set for the document, all non-specified available boost indexes values are defaulted to zero
	 *
	 * @param documentId external (customer) identifier of the document
	 * @param boosts a Map from the boost index (zero based) to the boost value (a double).
	 * @param timestamp the document timestamp as used for boosting purposes (null if the current timestamp for the document shouldn't be overriden)
	 * @throws {@link IllegalArgumentException} if an invalid index is passed for a boost
	 */
	public void setBoosts(String documentId, Integer timestamp,  Map<Integer, Float> boosts);

	/**
	 * Specify the values of the boosts for a document.
	 * This is accomplished by passing the dynamicBoosts parameter with a Map from the boost index (zero based) to the boost value (a double).
	 * In this map, no index can be larger than the number of available boosts the {@link BoostsManager} minus one (since it is zero based).
	 * If no boost was ever set for the document, all non-specified available boost indexes values are defaulted to zero
	 *
	 * @param documentId external (customer) identifier of the document
	 * @param boosts a Map from the boost index (zero based) to the boost value (a double).
	 * @throws {@link IllegalArgumentException} if an invalid index is passed for a boost
	 */
	public void setBoosts(String documentId, Map<Integer, Float> boosts);

	/**
	 * Clean the boosts for a specific document.
	 *
	 * @param documentId external (customer) identifier of the document
	 */
	public void removeBoosts(String documentId);

	/**
	 * Retrieve the boosts for a specific document
	 *
	 * @param documentId external (customer) identifier of the document
	 * @return an array of doubles with the boosts' values
	 */
	public Boosts getBoosts(DocId documentId);

	/**
	 * @return the number of document identifiers with boosts associated to them
	 */
	public int getDocumentCount();

    /*
     * Dumps the state of the manager to disk
     */
    public void dump() throws IOException;

    /**
     * Returns a map with docId's document variables
     */
    public Map<Integer, Double> getVariablesAsMap(DocId docId);

    /**
     * Returns a map with docId's document categories
     */
    public Map<String, String> getCategoryValues(DocId docId);

    /**
     * Returns a map with docId's document categories (returns empty)
     */
    Map<String, String> getCategoriesAsMap(DocId documentId);

}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Exrin.Abstraction
{
    public enum InsightCategory
    {

        Metric = 1,
        Exception = 2,
        Event = 4
    }
}


text:
package com.ickstream.controller.browse;

import com.ickstream.controller.service.ServiceController;
import com.ickstream.protocol.common.data.ContentItem;
import com.ickstream.protocol.service.content.AbstractPreferredMenu;

public class PreferredContentMenuItem extends ContentMenuItem implements AbstractPreferredMenuItem {
    private AbstractPreferredMenu preferredMenuItem;

    public PreferredContentMenuItem(AbstractPreferredMenu preferredMenuItem, ServiceController service, String contextId, ContentItem contentItem) {
        super(service, contextId, contentItem);
        this.preferredMenuItem = preferredMenuItem;
    }

    public PreferredContentMenuItem(AbstractPreferredMenu preferredMenuItem, ServiceController service, String contextId, ContentItem contentItem, MenuItem parent) {
        super(service, contextId, contentItem, parent);
        this.preferredMenuItem = preferredMenuItem;
    }

    public AbstractPreferredMenu getPreferredMenuItem() {
        return preferredMenuItem;
    }
}


text:
import unittest
from panda import Panda
from panda.tests.safety import libpandasafety_py
import panda.tests.safety.common as common
from panda.tests.safety.common import CANPackerPanda

class TestChryslerSafety(common.PandaSafetyTest, common.MotorTorqueSteeringSafetyTest):
  TX_MSGS = [[571, 0], [658, 0], [678, 0]]
  STANDSTILL_THRESHOLD = 0
  RELAY_MALFUNCTION_ADDR = 0x292
  RELAY_MALFUNCTION_BUS = 0
  FWD_BLACKLISTED_ADDRS = {2: [658, 678]}
  FWD_BUS_LOOKUP = {0: 2, 2: 0}

  MAX_RATE_UP = 3
  MAX_RATE_DOWN = 3
  MAX_TORQUE = 261
  MAX_RT_DELTA = 112
  RT_INTERVAL = 250000
  MAX_TORQUE_ERROR = 80

  DAS_BUS = 0

  def setUp(self):
    self.packer = CANPackerPanda("chrysler_pacifica_2017_hybrid_generated")
    self.safety = libpandasafety_py.libpandasafety
    self.safety.set_safety_hooks(Panda.SAFETY_CHRYSLER, 0)
    self.safety.init_tests()

  def _button_msg(self, cancel=False, resume=False):
    values = {"ACC_Cancel": cancel, "ACC_Resume": resume}
    return self.packer.make_can_msg_panda("CRUISE_BUTTONS", self.DAS_BUS, values)

  def _pcm_status_msg(self, enable):
    values = {"ACC_ACTIVE": enable}
    return self.packer.make_can_msg_panda("DAS_3", self.DAS_BUS, values)

  def _speed_msg(self, speed):
    values = {"SPEED_LEFT": speed, "SPEED_RIGHT": speed}
    return self.packer.make_can_msg_panda("SPEED_1", 0, values)

  def _user_gas_msg(self, gas):
    values = {"Accelerator_Position": gas}
    return self.packer.make_can_msg_panda("ECM_5", 0, values)

  def _user_brake_msg(self, brake):
    values = {"Brake_Pedal_State": 1 if brake else 0}
    return self.packer.make_can_msg_panda("ESP_1", 0, values)

  def _torque_meas_msg(self, torque):
    values = {"EPS_TORQUE_MOTOR": torque}
    return self.packer.make_can_msg_panda("EPS_2", 0, values)

  def _torque_cmd_msg(self, torque, steer_req=1):
    values = {"STEERING_TORQUE": torque}
    return self.packer.make_can_msg_panda("LKAS_COMMAND", 0, values)

  def test_buttons(self):
    for controls_allowed in (True, False):
      self.safety.set_controls_allowed(controls_allowed)

      # resume only while controls allowed
      self.assertEqual(controls_allowed, self._tx(self._button_msg(resume=True)))

      # can always cancel
      self.assertTrue(self._tx(self._button_msg(cancel=True)))

      # only one button at a time
      self.assertFalse(self._tx(self._button_msg(cancel=True, resume=True)))
      self.assertFalse(self._tx(self._button_msg(cancel=False, resume=False)))

class TestChryslerRamDTSafety(TestChryslerSafety):
  TX_MSGS = [[177, 2], [166, 0], [250, 0]]
  RELAY_MALFUNCTION_ADDR = 166
  FWD_BLACKLISTED_ADDRS = {2: [166, 250]}

  MAX_RATE_UP = 6
  MAX_RATE_DOWN = 6

  DAS_BUS = 2

  def setUp(self):
    self.packer = CANPackerPanda("chrysler_ram_dt_generated")
    self.safety = libpandasafety_py.libpandasafety
    self.safety.set_safety_hooks(Panda.SAFETY_CHRYSLER, Panda.FLAG_CHRYSLER_RAM_DT)
    self.safety.init_tests()

  def _speed_msg(self, speed):
    values = {"Vehicle_Speed": speed}
    return self.packer.make_can_msg_panda("ESP_8", 0, values)

class TestChryslerRamHDSafety(TestChryslerSafety):
  TX_MSGS = [[629, 0], [630, 0], [570, 2]]
  RELAY_MALFUNCTION_ADDR = 630
  FWD_BLACKLISTED_ADDRS = {2: [629, 630]}

  MAX_TORQUE = 361
  MAX_RATE_UP = 14
  MAX_RATE_DOWN = 14
  MAX_RT_DELTA = 182

  DAS_BUS = 2

  def setUp(self):
    self.packer = CANPackerPanda("chrysler_ram_hd_generated")
    self.safety = libpandasafety_py.libpandasafety
    self.safety.set_safety_hooks(Panda.SAFETY_CHRYSLER, Panda.FLAG_CHRYSLER_RAM_HD)
    self.safety.init_tests()

  def _speed_msg(self, speed):
    values = {"Vehicle_Speed": speed}
    return self.packer.make_can_msg_panda("ESP_8", 0, values)

if __name__ == "__main__":
  unittest.main()


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">

<TITLE>
Log4js.HtmlLayout
</TITLE>
<LINK REL ="stylesheet" TYPE="text/css" HREF="../stylesheet.css" TITLE="Style">

      Overview
    File
   Class
      Tree

      Index
      Help

Log4js 1.0-RC1

</TD

 PREV CLASS
 NEXT CLASS

  FRAMES
 NO FRAMES

All Classes

  SUMMARY: FIELD | CONSTR | METHOD

DETAIL: FIELD | CONSTR | METHOD

Class Log4js.HtmlLayout

Object
   |
   +--Log4js.Layout
         |
         +--Log4js.HtmlLayout

class
   Log4js.HtmlLayout

extends Log4js.Layout

   Defined in log4js.js

Author: Stephan Strittmatter

Constructor Summary

	    Log4js.HtmlLayout()

      HtmlLayout write the logs in Html format.

Methods inherited from class Log4js.Layout

format, getContentType, getHeader, getFooter

      Constructor Detail

Log4js.HtmlLayout

Log4js.HtmlLayout()

   HtmlLayout write the logs in Html format.

Author: Stephan Strittmatter

      Overview
    File
    Class
      Tree

      Index
      Help

Log4js 1.0-RC1

</TD

 PREV CLASS
 NEXT CLASS

  FRAMES
 NO FRAMES

All Classes

  SUMMARY: FIELD | CONSTR | METHOD

DETAIL: FIELD | CONSTR | METHOD

Log4js - Logging API for JavaScript

Documentation generated by JSDoc on Fri Aug  3 15:20:29 2007


text:
(function() {
  var Behavior, combineArray, combineWithFunction,
    __slice = [].slice;

  Behavior = require('./behavior');

  exports.combine = function() {
    var args;
    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
    if (args.length === 1 && Array.isArray(args[0])) {
      return combineArray(args[0]);
    } else if (typeof args[args.length - 1] === 'function') {
      return combineWithFunction(args);
    } else {
      throw new Error("Invalid object type");
    }
  };

  combineArray = function(array) {
    var behavior;
    return behavior = new Behavior(function() {
      var element, i, outputArray, ready, _i, _len,
        _this = this;
      outputArray = array.slice();
      ready = false;
      for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) {
        element = array[i];
        if (element.constructor.name === 'Behavior') {
          (function(element, i) {
            return _this.subscribe(element.onValue(function(value, metadata) {
              if (ready) {
                outputArray = outputArray.slice();
              }
              outputArray[i] = value;
              if (ready) {
                return _this.emitValue(outputArray, metadata);
              }
            }));
          })(element, i);
        }
      }
      ready = true;
      return this.emitValue(outputArray);
    });
  };

  combineWithFunction = function(args) {
    var fn;
    fn = args.pop();
    return combineArray(args).map(function(argsArray) {
      return fn.apply(null, argsArray);
    });
  };

}).call(this);


text:
package hoten.voronoi.nodename.as3delaunay;

import java.util.HashMap;
import java.util.Stack;

import hoten.geom.Point;
import hoten.geom.Rectangle;

/**
 * The line segment connecting the two Sites is part of the Delaunay
 * triangulation; the line segment connecting the two Vertices is part of the
 * Voronoi diagram
 *
 * @author ashaw
 *
 */
public final class Edge {

    final private static Stack<Edge> _pool = new Stack<>();

    /**
     * This is the only way to create a new Edge
     *
     * @param site0
     * @param site1
     * @return
     *
     */
    public static Edge createBisectingEdge(Site site0, Site site1) {
        double dx, dy, absdx, absdy;
        double a, b, c;

        dx = site1.get_x() - site0.get_x();
        dy = site1.get_y() - site0.get_y();
        absdx = dx > 0 ? dx : -dx;
        absdy = dy > 0 ? dy : -dy;
        c = site0.get_x() * dx + site0.get_y() * dy + (dx * dx + dy * dy) * 0.5;
        if (absdx > absdy) {
            a = 1.0;
            b = dy / dx;
            c /= dx;
        } else {
            b = 1.0;
            a = dx / dy;
            c /= dy;
        }

        Edge edge = Edge.create();

        edge.set_leftSite(site0);
        edge.set_rightSite(site1);
        site0.addEdge(edge);
        site1.addEdge(edge);

        edge._leftVertex = null;
        edge._rightVertex = null;

        edge.a = a;
        edge.b = b;
        edge.c = c;
        //trace("createBisectingEdge: a ", edge.a, "b", edge.b, "c", edge.c);

        return edge;
    }

    private static Edge create() {
        Edge edge;
        if (_pool.size() > 0) {
            edge = _pool.pop();
            edge.init();
        } else {
            edge = new Edge();
        }
        return edge;
    }

    /*final private static LINESPRITE:Sprite = new Sprite();
     final private static GRAPHICS:Graphics = LINESPRITE.graphics;

     private var _delaunayLineBmp:BitmapData;
     internal function get delaunayLineBmp():BitmapData
     {
     if (!_delaunayLineBmp)
     {
     _delaunayLineBmp = makeDelaunayLineBmp();
     }
     return _delaunayLineBmp;
     }

     // making this available to Voronoi; running out of memory in AIR so I cannot cache the bmp
     internal function makeDelaunayLineBmp():BitmapData
     {
     var p0:Point = leftSite.coord;
     var p1:Point = rightSite.coord;

     GRAPHICS.clear();
     // clear() resets line style back to undefined!
     GRAPHICS.lineStyle(0, 0, 1.0, false, LineScaleMode.NONE, CapsStyle.NONE);
     GRAPHICS.moveTo(p0.x, p0.y);
     GRAPHICS.lineTo(p1.x, p1.y);

     var w:int = int(Math.ceil(Math.max(p0.x, p1.x)));
     if (w < 1)
     {
     w = 1;
     }
     var h:int = int(Math.ceil(Math.max(p0.y, p1.y)));
     if (h < 1)
     {
     h = 1;
     }
     var bmp:BitmapData = new BitmapData(w, h, true, 0);
     bmp.draw(LINESPRITE);
     return bmp;
     }*/
    public LineSegment delaunayLine() {
        // draw a line connecting the input Sites for which the edge is a bisector:
        return new LineSegment(get_leftSite().get_coord(), get_rightSite().get_coord());
    }

    public LineSegment voronoiEdge() {
        if (!get_visible()) {
            return new LineSegment(null, null);
        }
        return new LineSegment(_clippedVertices.get(LR.LEFT),
                _clippedVertices.get(LR.RIGHT));
    }
    private static int _nedges = 0;
    final public static Edge DELETED = new Edge();
    // the equation of the edge: ax + by = c
    public double a, b, c;
    // the two Voronoi vertices that the edge connects
    //		(if one of them is null, the edge extends to infinity)
    private Vertex _leftVertex;

    public Vertex get_leftVertex() {
        return _leftVertex;
    }
    private Vertex _rightVertex;

    public Vertex get_rightVertex() {
        return _rightVertex;
    }

    public Vertex vertex(LR leftRight) {
        return (leftRight == LR.LEFT) ? _leftVertex : _rightVertex;
    }

    public void setVertex(LR leftRight, Vertex v) {
        if (leftRight == LR.LEFT) {
            _leftVertex = v;
        } else {
            _rightVertex = v;
        }
    }

    public boolean isPartOfConvexHull() {
        return (_leftVertex == null || _rightVertex == null);
    }

    public double sitesDistance() {
        return Point.distance(get_leftSite().get_coord(), get_rightSite().get_coord());
    }

    public static double compareSitesDistances_MAX(Edge edge0, Edge edge1) {
        double length0 = edge0.sitesDistance();
        double length1 = edge1.sitesDistance();
        if (length0 < length1) {
            return 1;
        }
        if (length0 > length1) {
            return -1;
        }
        return 0;
    }

    public static double compareSitesDistances(Edge edge0, Edge edge1) {
        return -compareSitesDistances_MAX(edge0, edge1);
    }
    // Once clipVertices() is called, this Dictionary will hold two Points
    // representing the clipped coordinates of the left and right ends...
    private HashMap<LR, Point> _clippedVertices;

    public HashMap<LR, Point> get_clippedEnds() {
        return _clippedVertices;
    }
    // unless the entire Edge is outside the bounds.
    // In that case visible will be false:

    public boolean get_visible() {
        return _clippedVertices != null;
    }
    // the two input Sites for which this Edge is a bisector:
    private HashMap<LR, Site> _sites;

    public void set_leftSite(Site s) {
        _sites.put(LR.LEFT, s);
    }

    public Site get_leftSite() {
        return _sites.get(LR.LEFT);
    }

    public void set_rightSite(Site s) {
        _sites.put(LR.RIGHT, s);
    }

    public Site get_rightSite() {
        return _sites.get(LR.RIGHT);
    }

    public Site site(LR leftRight) {
        return _sites.get(leftRight);
    }
    private int _edgeIndex;

    public void dispose() {
        /*if (_delaunayLineBmp)
         {
         _delaunayLineBmp.dispose();
         _delaunayLineBmp = null;
         }*/
        _leftVertex = null;
        _rightVertex = null;
        if (_clippedVertices != null) {
            _clippedVertices.clear();
            _clippedVertices = null;
        }
        _sites.clear();
        _sites = null;

        _pool.push(this);
    }

    private Edge() {
        _edgeIndex = _nedges++;
        init();
    }

    private void init() {
        _sites = new HashMap<>();
    }

    public String toString() {
        return "Edge " + _edgeIndex + "; sites " + _sites.get(LR.LEFT) + ", " + _sites.get(LR.RIGHT)
                + "; endVertices " + (_leftVertex != null ? _leftVertex.get_vertexIndex() : "null") + ", "
                + (_rightVertex != null ? _rightVertex.get_vertexIndex() : "null") + "::";
    }

    /**
     * Set _clippedVertices to contain the two ends of the portion of the
     * Voronoi edge that is visible within the bounds. If no part of the Edge
     * falls within the bounds, leave _clippedVertices null.
     *
     * @param bounds
     *
     */
    public void clipVertices(Rectangle bounds) {
        double xmin = bounds.x;
        double ymin = bounds.y;
        double xmax = bounds.right;
        double ymax = bounds.bottom;

        Vertex vertex0, vertex1;
        double x0, x1, y0, y1;

        if (a == 1.0 && b >= 0.0) {
            vertex0 = _rightVertex;
            vertex1 = _leftVertex;
        } else {
            vertex0 = _leftVertex;
            vertex1 = _rightVertex;
        }

        if (a == 1.0) {
            y0 = ymin;
            if (vertex0 != null && vertex0.get_y() > ymin) {
                y0 = vertex0.get_y();
            }
            if (y0 > ymax) {
                return;
            }
            x0 = c - b * y0;

            y1 = ymax;
            if (vertex1 != null && vertex1.get_y() < ymax) {
                y1 = vertex1.get_y();
            }
            if (y1 < ymin) {
                return;
            }
            x1 = c - b * y1;

            if ((x0 > xmax && x1 > xmax) || (x0 < xmin && x1 < xmin)) {
                return;
            }

            if (x0 > xmax) {
                x0 = xmax;
                y0 = (c - x0) / b;
            } else if (x0 < xmin) {
                x0 = xmin;
                y0 = (c - x0) / b;
            }

            if (x1 > xmax) {
                x1 = xmax;
                y1 = (c - x1) / b;
            } else if (x1 < xmin) {
                x1 = xmin;
                y1 = (c - x1) / b;
            }
        } else {
            x0 = xmin;
            if (vertex0 != null && vertex0.get_x() > xmin) {
                x0 = vertex0.get_x();
            }
            if (x0 > xmax) {
                return;
            }
            y0 = c - a * x0;

            x1 = xmax;
            if (vertex1 != null && vertex1.get_x() < xmax) {
                x1 = vertex1.get_x();
            }
            if (x1 < xmin) {
                return;
            }
            y1 = c - a * x1;

            if ((y0 > ymax && y1 > ymax) || (y0 < ymin && y1 < ymin)) {
                return;
            }

            if (y0 > ymax) {
                y0 = ymax;
                x0 = (c - y0) / a;
            } else if (y0 < ymin) {
                y0 = ymin;
                x0 = (c - y0) / a;
            }

            if (y1 > ymax) {
                y1 = ymax;
                x1 = (c - y1) / a;
            } else if (y1 < ymin) {
                y1 = ymin;
                x1 = (c - y1) / a;
            }
        }

        _clippedVertices = new HashMap<>();
        if (vertex0 == _leftVertex) {
            _clippedVertices.put(LR.LEFT, new Point(x0, y0));
            _clippedVertices.put(LR.RIGHT, new Point(x1, y1));
        } else {
            _clippedVertices.put(LR.RIGHT, new Point(x0, y0));
            _clippedVertices.put(LR.LEFT, new Point(x1, y1));
        }
    }
}


text:
package nl.homeserver.energie.verbruikkosten;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Objects;

import javax.annotation.Nullable;

class VerbruikenEnKosten {

    private final Collection<VerbruikKosten> all;

    VerbruikenEnKosten(final Collection<VerbruikKosten> all) {
        this.all = all;
    }

    @Nullable
    private BigDecimal getTotaalVerbruik() {
        return all.stream()
                  .map(VerbruikKosten::getVerbruik)
                  .filter(Objects::nonNull)
                  .reduce(BigDecimal::add)
                  .orElse(null);
    }

    @Nullable
    private BigDecimal getTotaalKosten() {
        return all.stream()
                  .map(VerbruikKosten::getKosten)
                  .filter(Objects::nonNull)
                  .reduce(BigDecimal::add)
                  .orElse(null);
    }

    VerbruikKosten sumToSingle() {
        return  new VerbruikKosten(getTotaalVerbruik(), getTotaalKosten());
    }
}