text:
import logging
from django.core.validators import validate_email
from corehq.apps.commtrack.dbaccessors.supply_point_case_by_domain_external_id import \
    get_supply_point_case_by_domain_external_id
from corehq.apps.products.models import SQLProduct
from custom.ewsghana.utils import TEACHING_HOSPITAL_MAPPING, TEACHING_HOSPITALS
from dimagi.utils.dates import force_to_datetime
from corehq.apps.commtrack.models import SupplyPointCase, CommtrackConfig
from corehq.apps.locations.models import SQLLocation, LocationType
from corehq.apps.users.models import WebUser, UserRole, Permissions
from custom.api.utils import apply_updates
from custom.ewsghana.extensions import ews_product_extension, ews_webuser_extension
from dimagi.ext.jsonobject import JsonObject, StringProperty, BooleanProperty, ListProperty, IntegerProperty, ObjectProperty
from custom.ilsgateway.api import ProductStock, StockTransaction
from custom.logistics.api import LogisticsEndpoint, APISynchronization, MigrationException
from corehq.apps.locations.models import Location as Loc
from django.core.exceptions import ValidationError

class Group(JsonObject):
    id = IntegerProperty()
    name = StringProperty()

class SupplyPoint(JsonObject):
    id = IntegerProperty()
    active = BooleanProperty()
    code = StringProperty()
    groups = ListProperty()
    last_reported = StringProperty()
    name = StringProperty()
    primary_reporter = IntegerProperty()
    supervised_by = IntegerProperty()
    supplied_by = IntegerProperty()
    type = StringProperty()
    location_id = IntegerProperty()
    products = ListProperty()

class SMSUser(JsonObject):
    id = IntegerProperty()
    name = StringProperty()
    role = StringProperty()
    is_active = StringProperty()
    supply_point = ObjectProperty(item_type=SupplyPoint)
    email = StringProperty()
    phone_numbers = ListProperty()
    backend = StringProperty()
    family_name = StringProperty()
    to = StringProperty()
    language = StringProperty()

class EWSUser(JsonObject):
    username = StringProperty()
    first_name = StringProperty()
    last_name = StringProperty()
    email = StringProperty()
    password = StringProperty()
    is_staff = BooleanProperty()
    is_active = BooleanProperty()
    is_superuser = BooleanProperty()
    last_login = StringProperty()
    date_joined = StringProperty()
    location = IntegerProperty()
    supply_point = IntegerProperty()
    sms_notifications = BooleanProperty()
    organization = StringProperty()
    groups = ListProperty(item_type=Group)
    contact = ObjectProperty(item_type=SMSUser)

class Location(JsonObject):
    id = IntegerProperty()
    name = StringProperty()
    type = StringProperty()
    parent_id = IntegerProperty()
    latitude = StringProperty()
    longitude = StringProperty()
    code = StringProperty()
    groups = ListProperty()
    supervised_by = IntegerProperty()
    supply_points = ListProperty(item_type=SupplyPoint)
    is_active = BooleanProperty()

class Program(JsonObject):
    code = StringProperty()
    name = StringProperty()

class Product(JsonObject):
    name = StringProperty()
    units = StringProperty()
    sms_code = StringProperty()
    description = StringProperty()
    is_active = BooleanProperty()
    program = ObjectProperty(item_type=Program)

class GhanaEndpoint(LogisticsEndpoint):
    models_map = {
        'product': Product,
        'webuser': EWSUser,
        'smsuser': SMSUser,
        'location': Location,
        'product_stock': ProductStock,
        'stock_transaction': StockTransaction
    }

    def __init__(self, base_uri, username, password):
        super(GhanaEndpoint, self).__init__(base_uri, username, password)
        self.supply_point_url = self._urlcombine(self.base_uri, '/supplypoints/')

    def get_supply_points(self, **kwargs):
        meta, supply_points = self.get_objects(self.supply_point_url, **kwargs)
        return meta, [SupplyPoint(supply_point) for supply_point in supply_points]

    def get_stocktransactions(self, start_date=None, end_date=None, **kwargs):
        kwargs.get('filters', {}).update({
            'date__gte': start_date,
            'date__lte': end_date
        })
        meta, stock_transactions = self.get_objects(self.stocktransactions_url, **kwargs)
        return meta, [(self.models_map['stock_transaction'])(stock_transaction)
                      for stock_transaction in stock_transactions]

class EWSApi(APISynchronization):
    LOCATION_CUSTOM_FIELDS = [
        {'name': 'created_at'},
        {'name': 'supervised_by'}
    ]
    SMS_USER_CUSTOM_FIELDS = [
        {'name': 'to'},
        {'name': 'backend'},
        {
            'name': 'role',
            'choices': [
                'In Charge', 'Nurse', 'Pharmacist', 'Laboratory Staff', 'Other', 'Facility Manager'
            ]
        }
    ]
    PRODUCT_CUSTOM_FIELDS = []

    def _create_location_from_supply_point(self, supply_point, location):
        try:
            sql_location = SQLLocation.objects.get(domain=self.domain, site_code=supply_point.code)
            return Loc.get(sql_location.location_id)
        except SQLLocation.DoesNotExist:
            parent = location
            if supply_point.code in TEACHING_HOSPITAL_MAPPING:
                parent = self._sync_parent(TEACHING_HOSPITAL_MAPPING[supply_point.code]['parent_external_id'])

            new_location = Loc(parent=parent)
            new_location.domain = self.domain
            new_location.location_type = supply_point.type
            new_location.name = supply_point.name
            new_location.site_code = supply_point.code
            if supply_point.supervised_by:
                new_location.metadata['supervised_by'] = supply_point.supervised_by
            new_location.save()
            sql_loc = new_location.sql_location
            sql_loc.products = SQLProduct.objects.filter(domain=self.domain, code__in=supply_point.products)
            sql_loc.save()
            return new_location

    def _create_supply_point_from_location(self, supply_point, location):
        if not SupplyPointCase.get_by_location(location):
            if supply_point.supervised_by:
                location.metadata['supervised_by'] = supply_point.supervised_by
                location.save()
                sql_loc = location.sql_location
                sql_loc.products = SQLProduct.objects.filter(domain=self.domain, code__in=supply_point.products)
                sql_loc.save()
            return SupplyPointCase.get_or_create_by_location(Loc(_id=location._id,
                                                             name=supply_point.name,
                                                             external_id=str(supply_point.id),
                                                             domain=self.domain))

    def _make_loc_type(self, name, administrative=False, parent_type=None):
        return LocationType.objects.get_or_create(
            domain=self.domain,
            name=name,
            administrative=administrative,
            parent_type=parent_type,
        )[0]

    def prepare_commtrack_config(self):
        for location_type in LocationType.objects.by_domain(self.domain):
            location_type.delete()

        country = self._make_loc_type(name="country", administrative=True)
        self._make_loc_type(name="Central Medical Store", parent_type=country)

        region = self._make_loc_type(name="region", administrative=True,
                                     parent_type=country)
        self._make_loc_type(name="Teaching Hospital", parent_type=region)
        self._make_loc_type(name="Regional Medical Store", parent_type=region)
        self._make_loc_type(name="Regional Hospital", parent_type=region)

        district = self._make_loc_type(name="district", administrative=True,
                                       parent_type=region)
        self._make_loc_type(name="Clinic", parent_type=district)
        self._make_loc_type(name="District Hospital", parent_type=district)
        self._make_loc_type(name="Health Centre", parent_type=district)
        self._make_loc_type(name="CHPS Facility", parent_type=district)
        self._make_loc_type(name="Hospital", parent_type=district)
        self._make_loc_type(name="Psychiatric Hospital", parent_type=district)
        self._make_loc_type(name="Polyclinic", parent_type=district)
        self._make_loc_type(name="facility", parent_type=district)

        config = CommtrackConfig.for_domain(self.domain)
        config.consumption_config.exclude_invalid_periods = True
        config.save()

    def _create_or_edit_facility_manager_role(self):
        facility_manager_role = UserRole.by_domain_and_name(self.domain, 'Facility manager')
        reports_list = [
            "corehq.apps.reports.standard.sms.MessageLogReport",
            "custom.ewsghana.reports.specific_reports.dashboard_report.DashboardReport",
            "custom.ewsghana.reports.specific_reports.stock_status_report.StockStatus",
            "custom.ewsghana.reports.specific_reports.reporting_rates.ReportingRatesReport",
            "custom.ewsghana.reports.maps.EWSMapReport"
        ]
        if facility_manager_role:
            permissions = Permissions(
                edit_web_users=True,
                edit_commcare_users=True,
                view_reports=False,
                view_report_list=reports_list
            )
            facility_manager_role[0].permissions = permissions
            facility_manager_role[0].save()
        else:

            role = UserRole(
                domain=self.domain,
                permissions=Permissions(
                    view_reports=False,
                    edit_web_users=True,
                    edit_commcare_users=True,
                    view_report_list=reports_list
                ),
                name='Facility manager'
            )
            role.save()

    def _create_or_edit_administrator_role(self):
        administrator_role = UserRole.by_domain_and_name(self.domain, 'Administrator')
        reports_list = [
            "corehq.apps.reports.standard.sms.MessageLogReport",
            "custom.ewsghana.reports.specific_reports.dashboard_report.DashboardReport",
            "custom.ewsghana.reports.specific_reports.stock_status_report.StockStatus",
            "custom.ewsghana.reports.specific_reports.reporting_rates.ReportingRatesReport",
            "custom.ewsghana.reports.maps.EWSMapReport",
            "custom.ewsghana.reports.email_reports.CMSRMSReport",
            "custom.ewsghana.reports.email_reports.StockSummaryReport",
            "custom.ewsghana.comparison_report.ProductsCompareReport",
            "custom.ewsghana.comparison_report.LocationsCompareReport",
            "custom.ewsghana.comparison_report.SupplyPointsCompareReport",
            "custom.ewsghana.comparison_report.WebUsersCompareReport",
            "custom.ewsghana.comparison_report.SMSUsersCompareReport"
        ]

        if administrator_role:
            permissions = Permissions(
                edit_web_users=True,
                edit_commcare_users=True,
                view_reports=False,
                view_report_list=reports_list
            )
            administrator_role[0].permissions = permissions
            administrator_role[0].save()
        else:
            role = UserRole(
                domain=self.domain,
                permissions=Permissions(
                    view_reports=False,
                    edit_web_users=True,
                    edit_commcare_users=True,
                    view_report_list=reports_list
                ),
                name='Administrator'
            )
            role.save()

    def _edit_read_only_role(self):
        read_only_role = UserRole.get_read_only_role_by_domain(self.domain)
        read_only_role.permissions.view_report_list = [
            "corehq.apps.reports.standard.sms.MessageLogReport",
            "custom.ewsghana.reports.specific_reports.dashboard_report.DashboardReport",
            "custom.ewsghana.reports.specific_reports.stock_status_report.StockStatus",
            "custom.ewsghana.reports.specific_reports.reporting_rates.ReportingRatesReport",
            "custom.ewsghana.reports.maps.EWSMapReport"
        ]
        read_only_role.permissions.view_reports = False
        read_only_role.save()

    def _create_or_edit_web_reporter_role(self):
        web_reporter_roles = UserRole.by_domain_and_name(self.domain, 'Web Reporter')
        report_list = [
            "corehq.apps.reports.standard.sms.MessageLogReport",
            "custom.ewsghana.reports.specific_reports.dashboard_report.DashboardReport",
            "custom.ewsghana.reports.specific_reports.stock_status_report.StockStatus",
            "custom.ewsghana.reports.specific_reports.reporting_rates.ReportingRatesReport",
            "custom.ewsghana.reports.maps.EWSMapReport"
        ]
        if web_reporter_roles:
            web_reporter_role = web_reporter_roles[0]
            web_reporter_role.permissions.view_reports = False
            web_reporter_role.permissions.view_report_list = report_list
            web_reporter_role.save()
        else:
            role = UserRole(
                domain=self.domain,
                permissions=Permissions(
                    view_reports=False,
                    view_report_list=report_list
                ),
                name='Web Reporter'
            )
            role.save()

    def create_or_edit_roles(self):
        self._create_or_edit_facility_manager_role()
        self._create_or_edit_administrator_role()
        self._create_or_edit_web_reporter_role()
        self._edit_read_only_role()

    def product_sync(self, ews_product):
        product = super(EWSApi, self).product_sync(ews_product)
        ews_product_extension(product, ews_product)
        return product

    def _set_location_properties(self, location, ews_location):
        location.domain = self.domain
        location.name = ews_location.name
        location.metadata = {}
        if ews_location.latitude:
            location.latitude = float(ews_location.latitude)
        if ews_location.longitude:
            location.longitude = float(ews_location.longitude)
        location.location_type = ews_location.type
        location.site_code = ews_location.code
        location.external_id = str(ews_location.id)

    def _set_up_supply_point(self, location, ews_location):
        if location.location_type in ['country', 'region', 'district']:
            supply_point_with_stock_data = filter(
                lambda x: x.last_reported and x.active, ews_location.supply_points
            )
            location.save()
            for supply_point in supply_point_with_stock_data:
                created_location = self._create_location_from_supply_point(supply_point, location)
                fake_location = Loc(
                    _id=created_location._id,
                    name=supply_point.name,
                    external_id=str(supply_point.id),
                    domain=self.domain
                )
                case = SupplyPointCase.get_or_create_by_location(fake_location)
                sql_location = created_location.sql_location
                sql_location.supply_point_id = case.get_id
                sql_location.save()
        elif ews_location.supply_points:
            active_supply_points = filter(lambda sp: sp.active, ews_location.supply_points)
            if active_supply_points:
                supply_point = active_supply_points[0]
            else:
                supply_point = ews_location.supply_points[0]
            location.name = supply_point.name
            location.site_code = supply_point.code
            if supply_point.code in TEACHING_HOSPITALS:
                location.location_type = 'Teaching Hospital'
                location.lineage = location.lineage[1:]
            else:
                location.location_type = supply_point.type
            try:
                sql_location = SQLLocation.objects.get(domain=self.domain, site_code=supply_point.code)
                if not sql_location.location_type.administrative:
                    raise MigrationException(
                        u'Site code {} is already used by {}'.format(supply_point.code, sql_location.name)
                    )
                couch_location = sql_location.couch_location
                couch_location.site_code = None
                couch_location.save()
            except SQLLocation.DoesNotExist:
                pass
            location.save()
            supply_point = self._create_supply_point_from_location(supply_point, location)
            if supply_point:
                sql_location = location.sql_location
                sql_location.supply_point_id = supply_point.get_id
                sql_location.save()
        else:
            location.save()
            fake_location = Loc(
                _id=location.get_id,
                name=location.name,
                external_id=None,
                domain=self.domain
            )
            supply_point = SupplyPointCase.get_or_create_by_location(fake_location)
            sql_location = location.sql_location
            sql_location.supply_point_id = supply_point.get_id
            sql_location.save()
            location.archive()

    def _sync_parent(self, parent_id):
        parent = self.endpoint.get_location(parent_id)
        loc_parent = self.location_sync(Location(parent))
        return loc_parent.get_id

    def location_sync(self, ews_location):
        try:
            sql_loc = SQLLocation.objects.get(
                domain=self.domain,
                external_id=int(ews_location.id)
            )
            location = Loc.get(sql_loc.location_id)
        except SQLLocation.DoesNotExist:
            location = None
        if not location:
            if ews_location.parent_id:
                try:
                    loc_parent = SQLLocation.objects.get(
                        external_id=ews_location.parent_id,
                        domain=self.domain
                    )
                    loc_parent_id = loc_parent.location_id
                except SQLLocation.DoesNotExist:
                    loc_parent_id = self._sync_parent(ews_location.parent_id)

                location = Loc(parent=loc_parent_id)
            else:
                location = Loc()
                location.lineage = []

            self._set_location_properties(location, ews_location)
            self._set_up_supply_point(location, ews_location)
        else:
            location_dict = {}
            if location.sql_location.location_type.administrative:
                location_dict = {
                    'name': ews_location.name,
                    'latitude': float(ews_location.latitude) if ews_location.latitude else None,
                    'longitude': float(ews_location.longitude) if ews_location.longitude else None,
                }
                try:
                    SQLLocation.objects.get(domain=self.domain, site_code=ews_location.code.lower())
                except SQLLocation.DoesNotExist:
                    location_dict['site_code'] = ews_location.code.lower()
            else:
                supply_point_with_stock_data = filter(
                    lambda x: x.last_reported and x.active, ews_location.supply_points
                )
                supply_point = None
                if supply_point_with_stock_data:
                    supply_point = supply_point_with_stock_data[0]
                elif ews_location.supply_points:
                    supply_point = ews_location.supply_points[0]

                if supply_point:
                    location_dict = {
                        'name': supply_point.name,
                        'latitude': float(ews_location.latitude) if ews_location.latitude else None,
                        'longitude': float(ews_location.longitude) if ews_location.longitude else None,
                        'site_code': supply_point.code,
                    }

            if location_dict and apply_updates(location, location_dict):
                location.save()
        for supply_point in ews_location.supply_points:
            sp = get_supply_point_case_by_domain_external_id(self.domain, supply_point.id)
            if sp:
                sql_location = sp.sql_location
                if set(sql_location.products.values_list('code', flat=True)) != supply_point.products:
                    sql_location.products = SQLProduct.objects.filter(
                        domain=self.domain,
                        code__in=supply_point.products
                    )
                    sql_location.save()
        return location

    def web_user_sync(self, ews_webuser):
        username = ews_webuser.email.lower()
        if not username:
            try:
                validate_email(ews_webuser.username)
                username = ews_webuser.username
            except ValidationError:
                return None
        user = WebUser.get_by_username(username)
        user_dict = {
            'first_name': ews_webuser.first_name,
            'last_name': ews_webuser.last_name,
            'is_active': ews_webuser.is_active,
            'last_login': force_to_datetime(ews_webuser.last_login),
            'date_joined': force_to_datetime(ews_webuser.date_joined),
            'password_hashed': True,
        }
        location_id = None
        if ews_webuser.location:
            try:
                location = SQLLocation.objects.get(domain=self.domain, external_id=ews_webuser.location)
                location_id = location.location_id
            except SQLLocation.DoesNotExist:
                pass

        if user is None:
            try:
                user = WebUser.create(domain=None, username=username,
                                      password=ews_webuser.password, email=ews_webuser.email,
                                      **user_dict)
                user.add_domain_membership(self.domain, location_id=location_id)
            except Exception as e:
                logging.error(e)
        else:
            if self.domain not in user.get_domains():
                user.add_domain_membership(self.domain, location_id=location_id)

        ews_webuser_extension(user, ews_webuser)
        dm = user.get_domain_membership(self.domain)

        if dm.location_id != location_id:
            dm.location_id = location_id

        if ews_webuser.is_superuser:
            dm.role_id = UserRole.by_domain_and_name(self.domain, 'Administrator')[0].get_id
        elif ews_webuser.groups and ews_webuser.groups[0].name == 'facility_manager':
            dm.role_id = UserRole.by_domain_and_name(self.domain, 'Facility manager')[0].get_id
        else:
            if ews_webuser.supply_point:
                supply_point = get_supply_point_case_by_domain_external_id(self.domain, ews_webuser.supply_point)
                if supply_point:
                    dm.location_id = supply_point.location_id
                    dm.role_id = UserRole.by_domain_and_name(self.domain, 'Web Reporter')[0].get_id
                else:
                    dm.role_id = UserRole.get_read_only_role_by_domain(self.domain).get_id
            else:
                dm.role_id = UserRole.get_read_only_role_by_domain(self.domain).get_id
        user.save()
        return user

    def sms_user_sync(self, ews_smsuser, **kwargs):
        sms_user = super(EWSApi, self).sms_user_sync(ews_smsuser, **kwargs)
        if not sms_user:
            return None
        sms_user.user_data['to'] = ews_smsuser.to
        sms_user.save()
        if ews_smsuser.supply_point:
            if ews_smsuser.supply_point.id:
                sp = get_supply_point_case_by_domain_external_id(self.domain, ews_smsuser.supply_point.id)
            else:
                sp = None

            if sp:
                couch_location = sp.location
            elif ews_smsuser.supply_point.location_id:
                try:
                    location = SQLLocation.objects.get(domain=self.domain,
                                                       external_id=ews_smsuser.supply_point.location_id)
                    couch_location = location.couch_location
                except SQLLocation.DoesNotExist:
                    couch_location = None
            else:
                couch_location = None
            if couch_location:
                sms_user.set_location(couch_location)
        return sms_user


text:
/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.flowable.cmmn.engine.impl.parser;

import org.apache.commons.lang3.StringUtils;
import org.flowable.cmmn.engine.impl.behavior.CmmnActivityBehavior;
import org.flowable.cmmn.engine.impl.behavior.impl.CaseTaskActivityBehavior;
import org.flowable.cmmn.engine.impl.behavior.impl.DecisionTaskActivityBehavior;
import org.flowable.cmmn.engine.impl.behavior.impl.HumanTaskActivityBehavior;
import org.flowable.cmmn.engine.impl.behavior.impl.MilestoneActivityBehavior;
import org.flowable.cmmn.engine.impl.behavior.impl.PlanItemDelegateExpressionActivityBehavior;
import org.flowable.cmmn.engine.impl.behavior.impl.PlanItemExpressionActivityBehavior;
import org.flowable.cmmn.engine.impl.behavior.impl.ProcessTaskActivityBehavior;
import org.flowable.cmmn.engine.impl.behavior.impl.StageActivityBehavior;
import org.flowable.cmmn.engine.impl.behavior.impl.TaskActivityBehavior;
import org.flowable.cmmn.engine.impl.behavior.impl.TimerEventListenerActivityBehaviour;
import org.flowable.cmmn.engine.impl.delegate.CmmnClassDelegate;
import org.flowable.cmmn.engine.impl.delegate.CmmnClassDelegateFactory;
import org.flowable.cmmn.model.CaseTask;
import org.flowable.cmmn.model.DecisionTask;
import org.flowable.cmmn.model.FieldExtension;
import org.flowable.cmmn.model.HumanTask;
import org.flowable.cmmn.model.Milestone;
import org.flowable.cmmn.model.PlanItem;
import org.flowable.cmmn.model.ProcessTask;
import org.flowable.cmmn.model.ServiceTask;
import org.flowable.cmmn.model.Stage;
import org.flowable.cmmn.model.Task;
import org.flowable.cmmn.model.TimerEventListener;
import org.flowable.engine.common.api.FlowableException;
import org.flowable.engine.common.api.delegate.Expression;
import org.flowable.engine.common.impl.el.ExpressionManager;

/**
 * @author Joram Barrez
 */
public class DefaultCmmnActivityBehaviorFactory implements CmmnActivityBehaviorFactory {

    protected CmmnClassDelegateFactory classDelegateFactory;
    protected ExpressionManager expressionManager;

    @Override
    public StageActivityBehavior createStageActivityBehavoir(PlanItem planItem, Stage stage) {
        return new StageActivityBehavior(stage);
    }

    @Override
    public MilestoneActivityBehavior createMilestoneActivityBehavior(PlanItem planItem, Milestone milestone) {
        String name = null;
        if (!StringUtils.isEmpty(planItem.getName())) {
            name = planItem.getName();
        } else if (StringUtils.isNotEmpty(milestone.getName())) {
            name = milestone.getName();
        }
        return new MilestoneActivityBehavior(expressionManager.createExpression(name));
    }

    @Override
    public TaskActivityBehavior createTaskActivityBehavior(PlanItem planItem, Task task) {
        return new TaskActivityBehavior(task.isBlocking(), task.getBlockingExpression());
    }

    @Override
    public HumanTaskActivityBehavior createHumanTaskActivityBehavior(PlanItem planItem, HumanTask humanTask) {
        return new HumanTaskActivityBehavior(humanTask);
    }

    @Override
    public CaseTaskActivityBehavior createCaseTaskActivityBehavior(PlanItem planItem, CaseTask caseTask) {
        return new CaseTaskActivityBehavior(expressionManager.createExpression(caseTask.getCaseRef()), caseTask);
    }

    @Override
    public ProcessTaskActivityBehavior createProcessTaskActivityBehavior(PlanItem planItem, ProcessTask processTask) {
        Expression processRefExpression = createExpression(processTask.getProcessRefExpression());
        return new ProcessTaskActivityBehavior(processTask.getProcess(), processRefExpression, processTask);
    }

    @Override
    public CmmnClassDelegate createCmmnClassDelegate(PlanItem planItem, ServiceTask task) {
        return classDelegateFactory.create(task.getImplementation(), task.getFieldExtensions());
    }

    @Override
    public PlanItemExpressionActivityBehavior createPlanItemExpressionActivityBehavior(PlanItem planItem, ServiceTask task) {
        return new PlanItemExpressionActivityBehavior(task.getImplementation(), task.getResultVariableName());
    }

    @Override
    public PlanItemDelegateExpressionActivityBehavior createPlanItemDelegateExpressionActivityBehavior(PlanItem planItem, ServiceTask task) {
        return new PlanItemDelegateExpressionActivityBehavior(task.getImplementation(), task.getFieldExtensions());
    }

    @Override
    public TimerEventListenerActivityBehaviour createTimerEventListenerActivityBehavior(PlanItem planItem, TimerEventListener timerEventListener) {
        return new TimerEventListenerActivityBehaviour(timerEventListener);
    }

    @Override
    public DecisionTaskActivityBehavior createDecisionTaskActivityBehavior(PlanItem planItem, DecisionTask decisionTask) {
        return new DecisionTaskActivityBehavior(createExpression(decisionTask.getDecisionRefExpression()), decisionTask);
    }

    @Override
    public CmmnActivityBehavior createHttpActivityBehavior(PlanItem planItem, ServiceTask task) {
        try {
            Class<?> theClass = null;
            FieldExtension behaviorExtension = null;
            for (FieldExtension fieldExtension : task.getFieldExtensions()) {
                if ("httpActivityBehaviorClass".equals(fieldExtension.getFieldName()) && StringUtils.isNotEmpty(fieldExtension.getStringValue())) {
                    theClass = Class.forName(fieldExtension.getStringValue());
                    behaviorExtension = fieldExtension;
                    break;
                }
            }

            if (behaviorExtension != null) {
                task.getFieldExtensions().remove(behaviorExtension);
            }

            // Default Http behavior class
            if (theClass == null) theClass = Class.forName("org.flowable.http.cmmn.impl.CmmnHttpActivityBehaviorImpl");

            return (CmmnActivityBehavior) classDelegateFactory.defaultInstantiateDelegate(theClass, task);

        } catch (ClassNotFoundException e) {
            throw new FlowableException("Could not find org.flowable.http.HttpActivityBehavior: ", e);
        }
    }

    public void setClassDelegateFactory(CmmnClassDelegateFactory classDelegateFactory) {
        this.classDelegateFactory = classDelegateFactory;
    }

    public ExpressionManager getExpressionManager() {
        return expressionManager;
    }

    public void setExpressionManager(ExpressionManager expressionManager) {
        this.expressionManager = expressionManager;
    }

    protected Expression createExpression(String refExpressionString) {
        Expression processRefExpression = null;
        if (StringUtils.isNotEmpty(refExpressionString)) {
            processRefExpression = expressionManager.createExpression(refExpressionString);
        }
        return processRefExpression;
    }

}

redpajama_set_name: RedPajamaGithub


text:
package org.apache.phoenix.mapreduce.index;

import org.apache.hadoop.hbase.Cell;

import org.apache.hadoop.hbase.TableExistsException;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
import org.apache.hadoop.hbase.regionserver.Region;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.coprocessor.IndexToolVerificationResult;
import org.apache.phoenix.coprocessor.MetaDataProtocol;
import org.apache.phoenix.hbase.index.table.HTableFactory;
import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.query.ConnectionQueryServices;
import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.util.ByteUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

public class IndexVerificationResultRepository implements AutoCloseable {
    private static final Logger LOGGER = LoggerFactory.getLogger(IndexVerificationResultRepository.class);

    public static final String RUN_STATUS_SKIPPED = "Skipped";
    public static final String RUN_STATUS_EXECUTED = "Executed";
    private Table resultTable;
    private Table indexTable;
    public static final String ROW_KEY_SEPARATOR = "|";
    public static final byte[] ROW_KEY_SEPARATOR_BYTE = Bytes.toBytes(ROW_KEY_SEPARATOR);
    public final static String RESULT_TABLE_NAME = "PHOENIX_INDEX_TOOL_RESULT";
    public final static byte[] RESULT_TABLE_NAME_BYTES = Bytes.toBytes(RESULT_TABLE_NAME);
    public final static byte[] RESULT_TABLE_COLUMN_FAMILY = QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES;
    public final static String SCANNED_DATA_ROW_COUNT = "ScannedDataRowCount";
    public final static byte[] SCANNED_DATA_ROW_COUNT_BYTES = Bytes.toBytes(SCANNED_DATA_ROW_COUNT);
    public final static String REBUILT_INDEX_ROW_COUNT = "RebuiltIndexRowCount";
    public final static byte[] REBUILT_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(REBUILT_INDEX_ROW_COUNT);
    public final static String SHOULD_RETRY = "ShouldRetry";
    public final static byte[] SHOULD_RETRY_BYTES = Bytes.toBytes(SHOULD_RETRY);
    public final static String BEFORE_REBUILD_VALID_INDEX_ROW_COUNT =
        "BeforeRebuildValidIndexRowCount";
    public final static byte[] BEFORE_REBUILD_VALID_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(BEFORE_REBUILD_VALID_INDEX_ROW_COUNT);
    private static final String INDEX_TOOL_RUN_STATUS = "IndexToolRunStatus";
    public final static byte[] INDEX_TOOL_RUN_STATUS_BYTES = Bytes.toBytes(INDEX_TOOL_RUN_STATUS);
    public final static String BEFORE_REBUILD_EXPIRED_INDEX_ROW_COUNT =
        "BeforeRebuildExpiredIndexRowCount";
    public final static byte[] BEFORE_REBUILD_EXPIRED_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(BEFORE_REBUILD_EXPIRED_INDEX_ROW_COUNT);
    public final static String BEFORE_REBUILD_MISSING_INDEX_ROW_COUNT =
        "BeforeRebuildMissingIndexRowCount";
    public final static byte[] BEFORE_REBUILD_MISSING_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(BEFORE_REBUILD_MISSING_INDEX_ROW_COUNT);
    public final static String BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT =
        "BeforeRebuildInvalidIndexRowCount";
    public final static byte[] BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT);
    public final static String BEFORE_REBUILD_UNVERIFIED_INDEX_ROW_COUNT =
            "BeforeRebuildUnverifiedIndexRowCount";
    public final static byte[] BEFORE_REBUILD_UNVERIFIED_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(BEFORE_REBUILD_UNVERIFIED_INDEX_ROW_COUNT);
    public final static String BEFORE_REBUILD_OLD_INDEX_ROW_COUNT =
            "BeforeRebuildOldIndexRowCount";
    public final static byte[] BEFORE_REBUILD_OLD_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(BEFORE_REBUILD_OLD_INDEX_ROW_COUNT);
    public final static String BEFORE_REBUILD_UNKNOWN_INDEX_ROW_COUNT =
            "BeforeRebuildUnknownIndexRowCount";
    public final static byte[] BEFORE_REBUILD_UNKNOWN_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(BEFORE_REBUILD_UNKNOWN_INDEX_ROW_COUNT);
    public final static String AFTER_REBUILD_VALID_INDEX_ROW_COUNT =
        "AfterRebuildValidIndexRowCount";
    public final static byte[] AFTER_REBUILD_VALID_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(AFTER_REBUILD_VALID_INDEX_ROW_COUNT);
    public final static String AFTER_REBUILD_EXPIRED_INDEX_ROW_COUNT =
        "AfterRebuildExpiredIndexRowCount";
    public final static byte[] AFTER_REBUILD_EXPIRED_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(AFTER_REBUILD_EXPIRED_INDEX_ROW_COUNT);
    public final static String AFTER_REBUILD_MISSING_INDEX_ROW_COUNT =
        "AfterRebuildMissingIndexRowCount";
    public final static byte[] AFTER_REBUILD_MISSING_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(AFTER_REBUILD_MISSING_INDEX_ROW_COUNT);
    public final static String AFTER_REBUILD_INVALID_INDEX_ROW_COUNT =
        "AfterRebuildInvalidIndexRowCount";
    public final static byte[] AFTER_REBUILD_INVALID_INDEX_ROW_COUNT_BYTES = Bytes.toBytes(AFTER_REBUILD_INVALID_INDEX_ROW_COUNT);
    public final static String BEFORE_REBUILD_BEYOND_MAXLOOKBACK_MISSING_INDEX_ROW_COUNT =
        "BeforeRebuildBeyondMaxLookBackMissingIndexRowCount";
    public final static byte[] BEFORE_REBUILD_BEYOND_MAXLOOKBACK_MISSING_INDEX_ROW_COUNT_BYTES =
        Bytes.toBytes(BEFORE_REBUILD_BEYOND_MAXLOOKBACK_MISSING_INDEX_ROW_COUNT);
    public final static String BEFORE_REBUILD_BEYOND_MAXLOOKBACK_INVALID_INDEX_ROW_COUNT =
        "BeforeRebuildBeyondMaxLookBackInvalidIndexRowCount";
    public final static byte[] BEFORE_REBUILD_BEYOND_MAXLOOKBACK_INVALID_INDEX_ROW_COUNT_BYTES =
        Bytes.toBytes(BEFORE_REBUILD_BEYOND_MAXLOOKBACK_INVALID_INDEX_ROW_COUNT);

    public final static String AFTER_REBUILD_BEYOND_MAXLOOKBACK_MISSING_INDEX_ROW_COUNT =
        "AfterRebuildBeyondMaxLookBackMissingIndexRowCount";
    public final static byte[] AFTER_REBUILD_BEYOND_MAXLOOKBACK_MISSING_INDEX_ROW_COUNT_BYTES =
        Bytes.toBytes(AFTER_REBUILD_BEYOND_MAXLOOKBACK_MISSING_INDEX_ROW_COUNT);
    public final static String AFTER_REBUILD_BEYOND_MAXLOOKBACK_INVALID_INDEX_ROW_COUNT =
        "AfterRebuildBeyondMaxLookBackInvalidIndexRowCount";
    public final static byte[] AFTER_REBUILD_BEYOND_MAXLOOKBACK_INVALID_INDEX_ROW_COUNT_BYTES =
        Bytes.toBytes(AFTER_REBUILD_BEYOND_MAXLOOKBACK_INVALID_INDEX_ROW_COUNT);

    public final static String BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_EXTRA_CELLS = "BeforeRebuildInvalidIndexRowCountCozExtraCells";
    public final static byte[] BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_EXTRA_CELLS_BYTES = Bytes.toBytes(BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_EXTRA_CELLS);
    public final static String BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_MISSING_CELLS = "BeforeRebuildInvalidIndexRowCountCozMissingCells";
    public final static byte[] BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_MISSING_CELLS_BYTES = Bytes.toBytes(BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_MISSING_CELLS);

    public final static String AFTER_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_EXTRA_CELLS = "AfterRebuildInvalidIndexRowCountCozExtraCells";
    public final static byte[] AFTER_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_EXTRA_CELLS_BYTES = Bytes.toBytes(AFTER_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_EXTRA_CELLS);
    public final static String AFTER_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_MISSING_CELLS = "AfterRebuildInvalidIndexRowCountCozMissingCells";
    public final static byte[] AFTER_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_MISSING_CELLS_BYTES = Bytes.toBytes(AFTER_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_MISSING_CELLS);

    public final static String BEFORE_REPAIR_EXTRA_VERIFIED_INDEX_ROW_COUNT = "BeforeRepairExtraVerifiedIndexRowCount";
    public final static byte[] BEFORE_REPAIR_EXTRA_VERIFIED_INDEX_ROW_COUNT_BYTES =
        Bytes.toBytes(BEFORE_REPAIR_EXTRA_VERIFIED_INDEX_ROW_COUNT);
    public final static String BEFORE_REPAIR_EXTRA_UNVERIFIED_INDEX_ROW_COUNT = "BeforeRepairExtraUnverifiedIndexRowCount";
    public final static byte[] BEFORE_REPAIR_EXTRA_UNVERIFIED_INDEX_ROW_COUNT_BYTES =
        Bytes.toBytes(BEFORE_REPAIR_EXTRA_UNVERIFIED_INDEX_ROW_COUNT);

    public final static String AFTER_REPAIR_EXTRA_VERIFIED_INDEX_ROW_COUNT = "AfterRepairExtraVerifiedIndexRowCount";
    public final static byte[] AFTER_REPAIR_EXTRA_VERIFIED_INDEX_ROW_COUNT_BYTES =
        Bytes.toBytes(AFTER_REPAIR_EXTRA_VERIFIED_INDEX_ROW_COUNT);
    public final static String AFTER_REPAIR_EXTRA_UNVERIFIED_INDEX_ROW_COUNT = "AfterRepairExtraUnverifiedIndexRowCount";
    public final static byte[] AFTER_REPAIR_EXTRA_UNVERIFIED_INDEX_ROW_COUNT_BYTES =
        Bytes.toBytes(AFTER_REPAIR_EXTRA_UNVERIFIED_INDEX_ROW_COUNT);

    /***
     * Only usable for read / create methods. To write use setResultTable and setIndexTable first
     */
    public IndexVerificationResultRepository(){

    }

    public IndexVerificationResultRepository(Connection conn, byte[] indexNameBytes) throws SQLException {
        resultTable = getTable(conn, RESULT_TABLE_NAME_BYTES);
        indexTable = getTable(conn, indexNameBytes);
    }

    public IndexVerificationResultRepository(byte[] indexName,
                                             HTableFactory hTableFactory) throws IOException {
        resultTable = hTableFactory.getTable(new ImmutableBytesPtr(RESULT_TABLE_NAME_BYTES));
        indexTable = hTableFactory.getTable(new ImmutableBytesPtr(indexName));
    }

    public void createResultTable(Connection connection) throws IOException, SQLException {
        ConnectionQueryServices queryServices = connection.unwrap(PhoenixConnection.class).getQueryServices();
        try (Admin admin = queryServices.getAdmin()) {
            TableName resultTableName = TableName.valueOf(RESULT_TABLE_NAME);
            if (!admin.tableExists(resultTableName)) {
                ColumnFamilyDescriptor columnDescriptor =
                    ColumnFamilyDescriptorBuilder
                        .newBuilder(RESULT_TABLE_COLUMN_FAMILY)
                        .setTimeToLive(MetaDataProtocol.DEFAULT_LOG_TTL)
                        .build();
                TableDescriptor tableDescriptor =
                    TableDescriptorBuilder.newBuilder(resultTableName)
                        .setColumnFamily(columnDescriptor).build();
                try {
                    admin.createTable(tableDescriptor);
                } catch (TableExistsException e) {
                    LOGGER.warn("Table exists, ignoring", e);
                }
                resultTable = admin.getConnection().getTable(resultTableName);
            }
        }
    }

    private static byte[] generatePartialResultTableRowKey(long ts, byte[] indexTableName) {
        byte[] keyPrefix = Bytes.toBytes(Long.toString(ts));
        int targetOffset = 0;
        // The row key for the result table : timestamp | index table name | datable table region name |
        //                                    scan start row | scan stop row
        byte[] partialRowKey = new byte[keyPrefix.length + ROW_KEY_SEPARATOR_BYTE.length
            + indexTableName.length];
        Bytes.putBytes(partialRowKey, targetOffset, keyPrefix, 0, keyPrefix.length);
        targetOffset += keyPrefix.length;
        Bytes.putBytes(partialRowKey, targetOffset, ROW_KEY_SEPARATOR_BYTE, 0, ROW_KEY_SEPARATOR_BYTE.length);
        targetOffset += ROW_KEY_SEPARATOR_BYTE.length;
        Bytes.putBytes(partialRowKey, targetOffset, indexTableName, 0, indexTableName.length);
        return partialRowKey;
    }

    private static byte[] generateResultTableRowKey(long ts, byte[] indexTableName,  byte [] regionName,
                                                    byte[] startRow, byte[] stopRow) {
        byte[] keyPrefix = Bytes.toBytes(Long.toString(ts));
        int targetOffset = 0;
        // The row key for the result table : timestamp | index table name | datable table region name |
        //                                    scan start row | scan stop row
        byte[] rowKey = new byte[keyPrefix.length + ROW_KEY_SEPARATOR_BYTE.length + indexTableName.length +
            ROW_KEY_SEPARATOR_BYTE.length + regionName.length + ROW_KEY_SEPARATOR_BYTE.length +
            startRow.length + ROW_KEY_SEPARATOR_BYTE.length + stopRow.length];
        Bytes.putBytes(rowKey, targetOffset, keyPrefix, 0, keyPrefix.length);
        targetOffset += keyPrefix.length;
        Bytes.putBytes(rowKey, targetOffset, ROW_KEY_SEPARATOR_BYTE, 0, ROW_KEY_SEPARATOR_BYTE.length);
        targetOffset += ROW_KEY_SEPARATOR_BYTE.length;
        Bytes.putBytes(rowKey, targetOffset, indexTableName, 0, indexTableName.length);
        targetOffset += indexTableName.length;
        Bytes.putBytes(rowKey, targetOffset, ROW_KEY_SEPARATOR_BYTE, 0, ROW_KEY_SEPARATOR_BYTE.length);
        targetOffset += ROW_KEY_SEPARATOR_BYTE.length;
        Bytes.putBytes(rowKey, targetOffset, regionName, 0, regionName.length);
        targetOffset += regionName.length;
        Bytes.putBytes(rowKey, targetOffset, ROW_KEY_SEPARATOR_BYTE, 0, ROW_KEY_SEPARATOR_BYTE.length);
        targetOffset += ROW_KEY_SEPARATOR_BYTE.length;
        Bytes.putBytes(rowKey, targetOffset, startRow, 0, startRow.length);
        targetOffset += startRow.length;
        Bytes.putBytes(rowKey, targetOffset, ROW_KEY_SEPARATOR_BYTE, 0, ROW_KEY_SEPARATOR_BYTE.length);
        targetOffset += ROW_KEY_SEPARATOR_BYTE.length;
        Bytes.putBytes(rowKey, targetOffset, stopRow, 0, stopRow.length);
        return rowKey;
    }

    public void logToIndexToolResultTable(IndexToolVerificationResult verificationResult,
            IndexTool.IndexVerifyType verifyType, byte[] region) throws IOException {
            logToIndexToolResultTable(verificationResult, verifyType, region, false, false);
    }

    public void logToIndexToolResultTable(IndexToolVerificationResult verificationResult,
                                          IndexTool.IndexVerifyType verifyType, byte[] region, boolean skipped, boolean shouldRetry) throws IOException {
        long scanMaxTs = verificationResult.getScanMaxTs();
        byte[] rowKey = generateResultTableRowKey(scanMaxTs, indexTable.getName().toBytes(),
            region, verificationResult.getStartRow(),
            verificationResult.getStopRow());
        Put put = new Put(rowKey);
        put.addColumn(RESULT_TABLE_COLUMN_FAMILY, SCANNED_DATA_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getScannedDataRowCount())));
        put.addColumn(RESULT_TABLE_COLUMN_FAMILY, REBUILT_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getRebuiltIndexRowCount())));

        put.addColumn(RESULT_TABLE_COLUMN_FAMILY, SHOULD_RETRY_BYTES, Bytes.toBytes(shouldRetry));
        put.addColumn(RESULT_TABLE_COLUMN_FAMILY, INDEX_TOOL_RUN_STATUS_BYTES,
                Bytes.toBytes(skipped ? RUN_STATUS_SKIPPED : RUN_STATUS_EXECUTED));
        if (verifyType == IndexTool.IndexVerifyType.BEFORE || verifyType == IndexTool.IndexVerifyType.BOTH ||
            verifyType == IndexTool.IndexVerifyType.ONLY) {
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REBUILD_VALID_INDEX_ROW_COUNT_BYTES,
                    Bytes.toBytes(Long.toString(verificationResult.getBeforeRebuildValidIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REBUILD_EXPIRED_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getBeforeRebuildExpiredIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REBUILD_MISSING_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getBeforeRebuildMissingIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getBeforeRebuildInvalidIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REBUILD_BEYOND_MAXLOOKBACK_MISSING_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getBefore().getBeyondMaxLookBackMissingIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REBUILD_BEYOND_MAXLOOKBACK_INVALID_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getBefore().getBeyondMaxLookBackInvalidIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_EXTRA_CELLS_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getBeforeIndexHasExtraCellsCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_MISSING_CELLS_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getBeforeIndexHasMissingCellsCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REBUILD_UNVERIFIED_INDEX_ROW_COUNT_BYTES,
                    Bytes.toBytes(Long.toString(verificationResult.getBeforeRebuildUnverifiedIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REBUILD_OLD_INDEX_ROW_COUNT_BYTES,
                    Bytes.toBytes(Long.toString(verificationResult.getBeforeRebuildOldIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REBUILD_UNKNOWN_INDEX_ROW_COUNT_BYTES,
                    Bytes.toBytes(Long.toString(verificationResult.getBeforeRebuildUnknownIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REPAIR_EXTRA_VERIFIED_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getBeforeRepairExtraVerifiedIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, BEFORE_REPAIR_EXTRA_UNVERIFIED_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getBeforeRepairExtraUnverifiedIndexRowCount())));
        }
        if (verifyType == IndexTool.IndexVerifyType.AFTER || verifyType == IndexTool.IndexVerifyType.BOTH) {
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, AFTER_REBUILD_VALID_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getAfterRebuildValidIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, AFTER_REBUILD_EXPIRED_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getAfterRebuildExpiredIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, AFTER_REBUILD_MISSING_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getAfterRebuildMissingIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, AFTER_REBUILD_INVALID_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getAfterRebuildInvalidIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, AFTER_REBUILD_BEYOND_MAXLOOKBACK_MISSING_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getAfter().getBeyondMaxLookBackMissingIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, AFTER_REBUILD_BEYOND_MAXLOOKBACK_INVALID_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getAfter().getBeyondMaxLookBackInvalidIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, AFTER_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_EXTRA_CELLS_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getAfterIndexHasExtraCellsCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, AFTER_REBUILD_INVALID_INDEX_ROW_COUNT_COZ_MISSING_CELLS_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getAfterIndexHasMissingCellsCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, AFTER_REPAIR_EXTRA_VERIFIED_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getAfterRepairExtraVerifiedIndexRowCount())));
            put.addColumn(RESULT_TABLE_COLUMN_FAMILY, AFTER_REPAIR_EXTRA_UNVERIFIED_INDEX_ROW_COUNT_BYTES,
                Bytes.toBytes(Long.toString(verificationResult.getAfterRepairExtraUnverifiedIndexRowCount())));
        }
        resultTable.put(put);
    }

    public Table getTable(Connection conn, byte[] tableName) throws SQLException {
        return conn.unwrap(PhoenixConnection.class).getQueryServices()
                .getTable(tableName);
    }

    /**
     * Get aggregated verification results from
     * {@link #aggregateVerificationResult(Table, IndexToolVerificationResult,
     * Scan)}
     * Provided Table reference should be closed by caller.
     *
     * @param htable Table reference. It is caller's responsibility to close
     *     this reference.
     * @param ts timestamp used for Scan's startRow
     * @return Verification result
     * @throws IOException if something goes wrong while retrieving verification
     *     results.
     */
    public IndexToolVerificationResult getVerificationResult(Table htable, long ts)
        throws IOException {
        byte[] startRowKey = Bytes.toBytes(Long.toString(ts));
        byte[] stopRowKey = ByteUtil.calculateTheClosestNextRowKeyForPrefix(startRowKey);
        IndexToolVerificationResult verificationResult = new IndexToolVerificationResult(ts);
        Scan scan = new Scan();
        scan.withStartRow(startRowKey);
        scan.withStopRow(stopRowKey);
        return aggregateVerificationResult(htable, verificationResult, scan);
    }

    private IndexToolVerificationResult aggregateVerificationResult(
            Table hTable, IndexToolVerificationResult verificationResult,
            Scan scan) throws IOException {
        try (ResultScanner scanner = hTable.getScanner(scan)) {
            for (Result result = scanner.next(); result != null;
                    result = scanner.next()) {
                boolean isFirst = true;
                for (Cell cell : result.rawCells()) {
                    if (isFirst) {
                        byte[][] rowKeyParts = ByteUtil.splitArrayBySeparator(
                            result.getRow(), ROW_KEY_SEPARATOR_BYTE[0]);
                        verificationResult.setStartRow(rowKeyParts[3]);
                        verificationResult.setStopRow(rowKeyParts[4]);
                        isFirst = false;
                    }
                    verificationResult.update(cell);
                }
            }
        }
        return verificationResult;
    }

    public IndexToolVerificationResult getVerificationResult(Connection conn,
            long ts, byte[] indexTableName) throws IOException, SQLException {
        try (Table hTable = getTable(conn, RESULT_TABLE_NAME_BYTES)) {
            byte[] startRowKey = generatePartialResultTableRowKey(ts,
                indexTableName);
            byte[] stopRowKey = ByteUtil.calculateTheClosestNextRowKeyForPrefix(
                startRowKey);
            IndexToolVerificationResult verificationResult =
                new IndexToolVerificationResult(ts);
            Scan scan = new Scan();
            scan.withStartRow(startRowKey);
            scan.withStopRow(stopRowKey);
            return aggregateVerificationResult(hTable, verificationResult,
                scan);
        }
    }

    private IndexToolVerificationResult getVerificationResult(Table htable, byte [] oldRowKey, Scan scan )
            throws IOException {
        IndexToolVerificationResult verificationResult = null;
        Result result = htable.get(new Get(oldRowKey));
        if(!result.isEmpty()) {
            byte[][] rowKeyParts = ByteUtil.splitArrayBySeparator(result.getRow(), ROW_KEY_SEPARATOR_BYTE[0]);
            verificationResult = new IndexToolVerificationResult(scan);
            verificationResult.setStartRow(rowKeyParts[3]);
            verificationResult.setStopRow(rowKeyParts[4]);
            for (Cell cell : result.rawCells()) {
                verificationResult.update(cell);
            }
        }
        return verificationResult;
    }

    public void close() throws IOException {
        if (resultTable != null) {
            resultTable.close();
        }
        if (indexTable != null) {
            indexTable.close();
        }
    }

    public void setResultTable(Table resultTable) {
        this.resultTable = resultTable;
    }

    public void setIndexTable(Table indexTable) {
        this.indexTable = indexTable;
    }

    public IndexToolVerificationResult getVerificationResult(Long ts, Scan scan, Region region, byte[] indexTableName) throws IOException {
        byte [] rowKey = generateResultTableRowKey(ts,
                indexTableName, region.getRegionInfo().getRegionName(),
                scan.getStartRow(), scan.getStopRow());
         return getVerificationResult(resultTable, rowKey, scan);

    }
}


text:
import React from "react";
import { render, mount } from "enzyme";
import { Switch, Size } from "..";

describe("Switch", () => {
  test("handle 'size' properly", () => {
    const acceptableSizes: Size[] = ["normal", "small"];
    acceptableSizes.forEach(size => {
      const wrapper = render(<Switch size={size} />);
      expect(wrapper.hasClass(`c-switch--${size}`));
    });
  });

  test("won't add additional class for incorrect 'size'", () => {
    const size: string = "a";
    // @ts-ignore
    const wrapper = render(<Switch size={size} />);
    expect(wrapper.hasClass(`.c-switch--${size}`)).toBe(false);
  });

  test("handle 'disabled' properly", () => {
    const wrapper = mount(<Switch />);

    expect(wrapper.render().find("input").is(":not([disabled])")).toBe(true);
    wrapper.setProps({ disabled: true });
    expect(wrapper.render().find("input").is("[disabled]")).toBe(true);
  });

  test("props.checked should be work first", () => {
    const checked: boolean = false;
    const wrapper = render(<Switch defaultChecked checked={checked} />);

    expect(wrapper.find("input").is(":not([checked])")).toBe(true);
  });

  test("should render correctly with (un)checkedChildren", () => {
    const props = {
      checkedChildren: "开",
      unCheckedChildren: "关"
    };
    const wrapperChecked = render(<Switch defaultChecked {...props} />);
    const wrapperUnChecked = render(<Switch {...props} />);
    expect(wrapperChecked.find(".c-switch__label").text()).toBe("开");
    expect(wrapperUnChecked.find(".c-switch__label").text()).toBe("关");
  });

  test("should render correctly with (un)checkedColor", () => {
    const wrapperUnChecked = render(<Switch unCheckedColor="#52B818" />);
    expect((wrapperUnChecked.html() || "").includes("background:#52B818")).toBe(
      true
    );
    const wrapperChecked = render(<Switch defaultChecked checkedColor="red" />);
    expect((wrapperChecked.html() || "").includes("background")).toBe(false);
  });

  test("should render correctly with labelId", () => {
    const wrapper = mount(
      <Switch checkedChildren="开" unCheckedChildren="关" />
    );
    expect(wrapper.find(".c-switch__label").getDOMNode()).toHaveProperty("id");
    wrapper.setProps({ unCheckedChildren: "" });
    expect(wrapper.find(".c-switch__label").getDOMNode()).toHaveProperty(
      "id",
      ""
    );
  });

  test("handle change trigger correctly", () => {
    const onChange = jest.fn();
    const wrapper = mount(<Switch onChange={onChange} />);

    wrapper.find("input").simulate("change");
    expect(onChange).toHaveBeenCalled();
  });
});


text:
jest.unmock( 'chalk' )
jest.unmock( 'marked' )
jest.unmock( 'cli-table' )
jest.unmock( 'cardinal' )
jest.unmock( 'node-emoji' )
jest.unmock( '../dist/class/SolidObject' )
jest.unmock( '../dist/lib/SolidText' )
jest.unmock( '../dist/class/TTYRender' )
jest.unmock( '../dist/class/SolidRender' )

var colors = require( 'chalk' )
var SolidRender = void 0

describe( 'lib/solidrender', function () {
  describe( 'constructor', function () {
    beforeEach( function () {
      SolidRender = require( '../dist/class/SolidRender' )
    })

    it( 'should initialize props', function () {
      var solidRender = new SolidRender()
      expect( solidRender.props ).toBeDefined()
    })

    it( 'should update props after initialization', function () {
      var solidRender = new SolidRender()
      var testProps = {
        columns: 60,
        wordwrap: false
      }
      solidRender.setProps( testProps )
      expect( solidRender.props ).toBeDefined()
      expect( solidRender.props.columns ).toEqual( testProps.columns )
      expect( solidRender.props.wordwrap ).toEqual( testProps.wordwrap )
    })

  })

  describe( 'header', function () {
    beforeEach( function () {
      SolidRender = require( '../dist/class/SolidRender' )
    })

    it( 'should render header', function () {
      var solidRender = new SolidRender()
      var TEXT = 'Test'
      solidRender.setProps({
        columns: 23,
        headerColor: 'cyan',
        wordwrap: true
      })
      var expected = '\n' + colors.cyan( '==== ERROR: Test =====' ) + '\n'
      var actual = solidRender.header( TEXT )
      expect( expected ).toEqual( actual )
    })

    it( 'should render header without readableName', function () {
      var solidRender = new SolidRender()
      solidRender.setProps({
        columns: 23,
        headerColor: 'cyan',
        wordwrap: true
      })
      var expected = '\n' + colors.cyan( '==== ERROR ===========' ) + '\n'
      var actual = solidRender.header( )
      expect( expected ).toEqual( actual )
    })
  })

  describe( 'message', function () {
    beforeEach( function () {
      SolidRender = require( '../dist/class/SolidRender' )
    })

    it( 'should render message', function () {
      var renderProps = { messageColor: 'reset', wordwrap: false }
      var solidRender = new SolidRender( renderProps )
      var TEXT = 'test'
      var EXPECTED_TEXT = 'Test'

      var actual = solidRender.message( TEXT )
      var expected = '\n' + colors.reset( EXPECTED_TEXT ) + '\n'

      expect( expected ).toEqual( actual )
    })

    it( 'should strip error codes from message', function () {
      var renderProps = { messageColor: 'reset', wordwrap: true }
      var solidRender = new SolidRender( renderProps )
      var TEXT = 'Error: ENOENT: no such file or directory.'
      var EXPECTED_TEXT = 'No such file or directory.'

      var actual = solidRender.message( TEXT )
      var expected = '\n' + colors.reset( EXPECTED_TEXT ) + '\n'

      expect( expected ).toEqual( actual )
    })
  })

  describe( 'explain', function () {
    beforeEach( function () {
      SolidRender = require( '../dist/class/SolidRender' )
    })

    it( 'should render explain', function () {
      var renderProps = {
        explain: 'reset',
        wordwrap: true,
        markdown: false
      }
      var solidRender = new SolidRender( renderProps )
      var TEXT = 'test'
      var EXPECTED_TEXT = 'Test'

      var expected = '\n' + colors.reset( EXPECTED_TEXT )
      var actual = solidRender.explain( TEXT )

      expect( expected ).toEqual( actual )
    })

    it( 'should format markdown in explain section', function () {
      var renderProps = { markdown: true }
      var solidRender = new SolidRender( renderProps )
      var TEXT = 'bold text'
      var MD_TEXT = '**' + TEXT + '**'

      var expected = '\n' + colors.bold( TEXT ) + '\n'
      var actual = solidRender.explain( MD_TEXT )

      expect( expected).toEqual( actual )
    })
  })

  describe( 'trace', function () {
    beforeEach( function () {
      SolidRender = require( '../dist/class/SolidRender' )
    })

    it( 'should format trace', function () {
      var TEXT = 'Test'

      var renderProps = {
        columns: 22,
        traceColor: 'reset',
        traceTitle: 'STACKTRACE',
        wordwrap: false,
      }
      var solidRender = new SolidRender( renderProps )

      var expected = '\n' + colors.reset( '---- STACKTRACE -----' )
        + '\n\n' + TEXT
      var actual = solidRender.trace( TEXT )

      expect( expected ).toEqual( actual )
    })
  })

  describe( 'hints', function () {
    beforeEach( function () {
      SolidRender = require( '../dist/class/SolidRender' )
    })

    it( 'should render hints', function () {
      var renderProps = {
        columns: 22,
        hintsColor: 'reset',
        hintsTitle: 'HINTS',
        markdown: false,
        wordwrap: false,
      }
      var solidRender = new SolidRender( renderProps )
      var TEXT = 'example text'
      var EXPECTED_TEXT = 'Example text'
      var expected =
        '\n' + colors.reset( '---- HINTS ----------' ) + '\n\n' + EXPECTED_TEXT + '\n'
      var actual = solidRender.hints( TEXT )
      expect( expected ).toEqual( actual )
    })

    it( 'should format markdown in hints section', function () {
      var renderProps = {
        columns: 22,
        hintsColor: 'reset',
        hintsTitle: 'HINTS',
        markdown: true,
        wordwrap: false,
      }
      var solidRender = new SolidRender( renderProps )

      var TEXT = 'example text'
      var MD_TEXT = '_' + TEXT + '_'

      var coloredDivider = colors.reset( '---- HINTS ----------' )
      var markdownContent = colors.italic( TEXT )
      var expected = `\n${coloredDivider}\n\n${markdownContent}\n`
      var actual = solidRender.hints( MD_TEXT )

      expect( expected ).toEqual( actual )
    })
  })

  describe( 'footer', function () {
    beforeEach( function () {
      SolidRender = require( '../dist/class/SolidRender' )
    })

    it( 'should render footer', function () {
      var ECODE = 'ETEST'
      var EPATH = '/path/to/test'
      var renderProps = {
        columns: 22,
        footerColor: 'blue',
        markdown: false,
        wordwrap: true,
      }
      var solidRender = new SolidRender( renderProps )

      var DIVIDER = '---------------------'
      var expected = '\n' + colors.blue(
        DIVIDER + '\n'
        + 'Code: ' + ECODE + '\n'
        + 'Path: ' + EPATH
        + '\n' + DIVIDER
      ) + '\n'
      var actual = solidRender.footer( ECODE, EPATH )

      expect( expected ).toEqual( actual )
    })

    it( 'should format "footer" section without Path', function () {
      var ECODE = 'ETEST'
      var renderProps = {
        columns: 22,
        footerColor: 'blue',
        markdown: false,
        wordwrap: true,
      }
      var solidRender = new SolidRender( renderProps )

      var DIVIDER = '---------------------'
      var expected = '\n' + colors.blue(
        DIVIDER + '\n'
        + 'Code: ' + ECODE
        + '\n' + DIVIDER
      ) + '\n'

      var actual = solidRender.footer( ECODE, null )

      expect( expected ).toEqual( actual )
    })

    it( 'should render footer section wihout code', function () {
      var EPATH = '/path/to/test'
      var renderProps = {
        columns: 22,
        footerColor: 'blue',
        markdown: false,
        wordwrap: true,
      }
      var solidRender = new SolidRender( renderProps )

      var DIVIDER = '---------------------'
      var expected = '\n' + colors.blue(
        DIVIDER + '\n'
        + 'Path: ' + EPATH
        + '\n' + DIVIDER
      ) + '\n'

      var actual = solidRender.footer( null, EPATH )
      expect( expected ).toEqual( actual )
    })

    it( 'should return nothing if parameters are missing', function () {
      var renderProps = {
        columns: 22,
        footerColor: 'blue',
        markdown: false,
        wordwrap: true,
      }
      var solidRender = new SolidRender( renderProps )

      var actual = solidRender.footer( null, null )
      expect( '' ).toEqual( actual )
    })
  })
})


text:
using std::cout;
using std::endl;
AppIcon::AppIcon(BScreen &scr, unsigned int app_num, FbExt::Application &app):
		Focusable(scr),
		m_app_num(app_num),
		m_app(app),
		m_rc_icontheme(scr.resourceManager(), "", "taskbar.iconTheme", "Taskbar.IconTheme") {
}

void AppIcon::setFocusFlag(bool flag) {
	m_focused = flag;
	notifyFocusChanged();
}

bool AppIcon::focus() {
	JumpToAppCmd(m_app_num).execute();
}

bool AppIcon::window_of(WinClient *client) {
	return(m_app.window_of(client));
}

Taskbar::Taskbar(const FbTk::FbWindow &parent, IconbarTheme &theme,
                         FbTk::ThemeProxy<IconbarTheme> &focused_theme,
                         FbTk::ThemeProxy<IconbarTheme> &unfocused_theme,
                         BScreen &screen, FbTk::Menu &menu, FbExt::ApplicationsList &app_list):
	IconbarTool(parent, theme, focused_theme, unfocused_theme, screen, menu,
			ToolbarItem::FIXED,
			IconbarTool::taskbar),
	m_parent(parent),
	m_applications_list(app_list) {
	FbExt::ApplicationsList::iterator it;
	for(it = m_applications_list.begin(); it != m_applications_list.end(); it++) {
    		// IconButton *button = insertItem(AppIcon(screen, *(*it)), std::distance(m_applications_list.begin(), it));
		unsigned int index = std::distance(m_applications_list.begin(), it);
		AppIcon *app_icon = new AppIcon(screen, index, *(*it));
		m_icons[index] = app_icon;
        	IconButton *button = makeButton(*app_icon);
		cout << "button=" << button << endl;
		m_icon_container.insertItem(button, index);
	}
        m_tracker.join(screen.focusedWindowSig(),
             FbTk::MemFun(*this, &Taskbar::focusedWindowChanged));
}

void Taskbar::focusedWindowChanged(BScreen &screen,
                                         FluxboxWindow *focused_win,
                                         WinClient *client) {
	cout << "focus changed" << endl;
	AppIconMap::iterator it;
	for(it = m_icons.begin(); it != m_icons.end(); it++) {
		AppIcon *app = it->second;
		app->setFocusFlag(app->window_of(client));
	}
}

unsigned int Taskbar::width() const {
	unsigned int w = m_applications_list.size();
	if(!w) w = 3;
	return(m_parent.height() * w);
}

Taskbar::~Taskbar() {
}

void Taskbar::handle_update(UpdateReason reason, Focusable *win) {
    cout << "reason=" << reason << endl;
    if(reason == LIST_ADD || reason == LIST_ORDER) {
    }
}


text:
typedef boost::asio::buffered_stream<
    boost::asio::ip::tcp::socket> stream_type;

void test_sync_operations()
{
  using namespace std; // For memcmp.

  boost::asio::io_service io_service;

  boost::asio::ip::tcp::acceptor acceptor(io_service,
      boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 0));
  boost::asio::ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
  server_endpoint.address(boost::asio::ip::address_v4::loopback());

  stream_type client_socket(io_service);
  client_socket.lowest_layer().connect(server_endpoint);

  stream_type server_socket(io_service);
  acceptor.accept(server_socket.lowest_layer());

  const char write_data[]
    = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  const boost::asio::const_buffer write_buf = boost::asio::buffer(write_data);

  std::size_t bytes_written = 0;
  while (bytes_written < sizeof(write_data))
  {
    bytes_written += client_socket.write_some(
        boost::asio::buffer(write_buf + bytes_written));
    client_socket.flush();
  }

  char read_data[sizeof(write_data)];
  const boost::asio::mutable_buffer read_buf = boost::asio::buffer(read_data);

  std::size_t bytes_read = 0;
  while (bytes_read < sizeof(read_data))
  {
    bytes_read += server_socket.read_some(
        boost::asio::buffer(read_buf + bytes_read));
  }

  BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
  BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
  BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);

  bytes_written = 0;
  while (bytes_written < sizeof(write_data))
  {
    bytes_written += server_socket.write_some(
        boost::asio::buffer(write_buf + bytes_written));
    server_socket.flush();
  }

  bytes_read = 0;
  while (bytes_read < sizeof(read_data))
  {
    bytes_read += client_socket.read_some(
        boost::asio::buffer(read_buf + bytes_read));
  }

  BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
  BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
  BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);

  server_socket.close();
  boost::system::error_code error;
  bytes_read = client_socket.read_some(
      boost::asio::buffer(read_buf), error);

  BOOST_ASIO_CHECK(bytes_read == 0);
  BOOST_ASIO_CHECK(error == boost::asio::error::eof);

  client_socket.close(error);
}

void handle_accept(const boost::system::error_code& e)
{
  BOOST_ASIO_CHECK(!e);
}

void handle_write(const boost::system::error_code& e,
    std::size_t bytes_transferred,
    std::size_t* total_bytes_written)
{
  BOOST_ASIO_CHECK(!e);
  if (e)
    throw boost::system::system_error(e); // Terminate test.
  *total_bytes_written += bytes_transferred;
}

void handle_flush(const boost::system::error_code& e)
{
  BOOST_ASIO_CHECK(!e);
}

void handle_read(const boost::system::error_code& e,
    std::size_t bytes_transferred,
    std::size_t* total_bytes_read)
{
  BOOST_ASIO_CHECK(!e);
  if (e)
    throw boost::system::system_error(e); // Terminate test.
  *total_bytes_read += bytes_transferred;
}

void handle_read_eof(const boost::system::error_code& e,
    std::size_t bytes_transferred)
{
  BOOST_ASIO_CHECK(e == boost::asio::error::eof);
  BOOST_ASIO_CHECK(bytes_transferred == 0);
}

void test_async_operations()
{
  using namespace std; // For memcmp.

#if defined(BOOST_ASIO_HAS_BOOST_BIND)
  namespace bindns = boost;
#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
  namespace bindns = std;
  using std::placeholders::_1;
  using std::placeholders::_2;
#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)

  boost::asio::io_service io_service;

  boost::asio::ip::tcp::acceptor acceptor(io_service,
      boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 0));
  boost::asio::ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
  server_endpoint.address(boost::asio::ip::address_v4::loopback());

  stream_type client_socket(io_service);
  client_socket.lowest_layer().connect(server_endpoint);

  stream_type server_socket(io_service);
  acceptor.async_accept(server_socket.lowest_layer(), &handle_accept);
  io_service.run();
  io_service.reset();

  const char write_data[]
    = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  const boost::asio::const_buffer write_buf = boost::asio::buffer(write_data);

  std::size_t bytes_written = 0;
  while (bytes_written < sizeof(write_data))
  {
    client_socket.async_write_some(
        boost::asio::buffer(write_buf + bytes_written),
        bindns::bind(handle_write, _1, _2, &bytes_written));
    io_service.run();
    io_service.reset();
    client_socket.async_flush(
        bindns::bind(handle_flush, _1));
    io_service.run();
    io_service.reset();
  }

  char read_data[sizeof(write_data)];
  const boost::asio::mutable_buffer read_buf = boost::asio::buffer(read_data);

  std::size_t bytes_read = 0;
  while (bytes_read < sizeof(read_data))
  {
    server_socket.async_read_some(
        boost::asio::buffer(read_buf + bytes_read),
        bindns::bind(handle_read, _1, _2, &bytes_read));
    io_service.run();
    io_service.reset();
  }

  BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
  BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
  BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);

  bytes_written = 0;
  while (bytes_written < sizeof(write_data))
  {
    server_socket.async_write_some(
        boost::asio::buffer(write_buf + bytes_written),
        bindns::bind(handle_write, _1, _2, &bytes_written));
    io_service.run();
    io_service.reset();
    server_socket.async_flush(
        bindns::bind(handle_flush, _1));
    io_service.run();
    io_service.reset();
  }

  bytes_read = 0;
  while (bytes_read < sizeof(read_data))
  {
    client_socket.async_read_some(
        boost::asio::buffer(read_buf + bytes_read),
        bindns::bind(handle_read, _1, _2, &bytes_read));
    io_service.run();
    io_service.reset();
  }

  BOOST_ASIO_CHECK(bytes_written == sizeof(write_data));
  BOOST_ASIO_CHECK(bytes_read == sizeof(read_data));
  BOOST_ASIO_CHECK(memcmp(write_data, read_data, sizeof(write_data)) == 0);

  server_socket.close();
  client_socket.async_read_some(boost::asio::buffer(read_buf), handle_read_eof);
}

BOOST_ASIO_TEST_SUITE
(
  "buffered_stream",
  BOOST_ASIO_TEST_CASE(test_sync_operations)
  BOOST_ASIO_TEST_CASE(test_async_operations)
)


text:
require_relative '../test_helper'

##Add an exercise:
#In order to keep all my workouts straight I want to create a workout and add it to my list.

# Usage Example:
# > ./workout-generator
# 1. Add a workout
# 2. List all exercises
# 3. Create Workout
# 4. Exit

# > 1
# Please Enter the Name of Your First Exercise:
# > Push Ups
# Please Enter the number of reps:
# > 15
# Would you like to Add another exercise? (y/n)
# > n
# Exit

class AddingANewExerciseTest < Minitest::Test
  def test_happy_path_adding_an_exercise
    shell_output = ""
    expected_output = main_menu
    test_exercise = "run"
    IO.popen('./workout_generator manage', 'r+') do |pipe|
      pipe.puts "1"
      expected_output << "\nWhat exercise would you like to add?\n"
      pipe.puts test_exercise
      expected_output << "\"#{test_exercise}\" has been added\n"
      expected_output << main_menu
      pipe.puts "2"
      expected_output << "\n1. #{test_exercise}\n"
      expected_output << "2. Exit\n"
      expected_output << "Select an exercise by list number:\n"
      expected_output << exit_from(pipe)
      shell_output = pipe.read
      pipe.close_write
      pipe.close_read
    end
    assert_equal expected_output, shell_output
  end

  def test_sad_path_adding_a_scenario
    shell_output = ""
    happy_exercise = "throwing a knife"
    expected_output = main_menu
    IO.popen('./workout_generator manage', 'r+') do |pipe|
      pipe.puts "1"
      expected_output << "\nWhat exercise would you like to add?\n"
      pipe.puts ""
      expected_output << "\"\" is not a valid exercise name.\n"
      expected_output << "What exercise would you like to add?\n"
      pipe.puts happy_exercise
      expected_output << "\"#{happy_exercise}\" has been added\n"
      expected_output << main_menu
      pipe.puts "2"
      expected_output << "\n1. #{happy_exercise}\n"
      expected_output << "2. Exit\n"
      expected_output << "Select an exercise by list number:\n"
      expected_output << exit_from(pipe)
      shell_output = pipe.read
      pipe.close_write
      pipe.close_read
    end
    assert_equal expected_output, shell_output
  end
end