text:
require 'spec_helper'

class AddressSanitizer < InputSanitizer::V2::PayloadSanitizer
  string :city
  string :zip
end

class TagSanitizer < InputSanitizer::V2::PayloadSanitizer
  integer :id
  string :name
  nested :addresses, :sanitizer => AddressSanitizer, :collection => true
end

class TestedPayloadSanitizer < InputSanitizer::V2::PayloadSanitizer
  integer :array, :collection => true
  integer :array_nil, :collection => true, :allow_nil => true
  string :status, :allow => ['current', 'past']
  string :status_with_empty, :allow => ['', 'current', 'past']
  string :regexp_string, :regexp => /^#?([a-f0-9]{6}|[a-f0-9]{3})$/
  string :utf8mb4_string, :strip_4byte_chars => true
  string :value_restricted_utf8mb4_string, :strip_4byte_chars => true, :allow => ['test']
  string :non_blank_utf8mb4_string, :strip_4byte_chars => true, :allow_blank => false
  string :size_restricted_utf8mb4_string, :strip_4byte_chars => true, :minimum => 2, :maximum => 4
  nested :address, :sanitizer => AddressSanitizer
  nested :nullable_address, :sanitizer => AddressSanitizer, :allow_nil => true
  nested :tags, :sanitizer => TagSanitizer, :collection => true

  float :float_attribute, :minimum => 1, :maximum => 100
  integer :integer_attribute, :minimum => 1, :maximum => 100
  string :string_attribute
  boolean :bool_attribute
  datetime :datetime_attribute
  date :date_attribute, :minimum => Date.new(-2015, 01, 01), :maximum => Date.new(2015, 12, 31)

  url :website
  string :limited_collection, :collection => { :minimum => 1, :maximum => 2 }, :minimum => 2, :maximum => 12
  string :allow_collection, :collection => true, :allow => ['yes', 'no']
end

class BlankValuesPayloadSanitizer < InputSanitizer::V2::PayloadSanitizer
  string :required_string, :required => true
  datetime :non_nil_datetime, :allow_nil => false
  url :non_blank_url, :allow_blank => false
end

class CustomConverterWithProvidedValue < InputSanitizer::V2::PayloadSanitizer
  integer :from
  custom :to, :provide => :from, :converter => lambda { |value, options|
    InputSanitizer::V2::Types::IntegerCheck.new.call(value)
    raise InputSanitizer::ValueError.new(value, options[:provided][:from], nil) if options[:provided][:from] > value
    value
  }
end

describe InputSanitizer::V2::PayloadSanitizer do
  let(:sanitizer) { TestedPayloadSanitizer.new(@params) }
  let(:cleaned) { sanitizer.cleaned }

  describe "collections" do
    it "is invalid if collection is not an array" do
      @params = { :array => {} }
      sanitizer.should_not be_valid
    end

    it "is valid if collection is an array" do
      @params = { :array => [] }
      sanitizer.should be_valid
    end

    it "is valid if collection is an nil and allow_nil is passed" do
      @params = { :array_nil => nil }
      sanitizer.should be_valid
    end

    it "is invalid if there are too few elements" do
      @params = { :limited_collection => [] }
      sanitizer.should_not be_valid
    end

    it "is invalid if there are too many elements" do
      @params = { :limited_collection => ['bear', 'bear', 'bear'] }
      sanitizer.should_not be_valid
    end

    it "is valid when there are just enough elements" do
      @params = { :limited_collection => ['goldilocks'] }
      sanitizer.should be_valid
    end

    it "is invalid when any of the elements are too long" do
      @params = { :limited_collection => ['more_than_the_limit'] }
      sanitizer.should_not be_valid
    end

    it "is invalid when any of the elements are too short" do
      @params = { :limited_collection => ['a'] }
      sanitizer.should_not be_valid
    end

    it "is invalid when given disallowed value in a collection" do
      @params = { :allow_collection => ['yes', 'no', 'whoa'] }
      sanitizer.should_not be_valid
    end

    it "is valid when given allowed values in a collection" do
      @params = { :allow_collection => ['yes', 'no'] }
      sanitizer.should be_valid
    end
  end

  describe "allow option" do
    it "is valid when given an allowed string" do
      @params = { :status => 'past' }
      sanitizer.should be_valid
    end

    it "is invalid when given an empty string" do
      @params = { :status => '' }
      sanitizer.should_not be_valid
      sanitizer.errors[0].field.should eq('/status')
    end

    it "is valid when given an allowed empty string" do
      @params = { :status_with_empty => '' }
      sanitizer.should be_valid
    end

    it "is invalid when given a disallowed string" do
      @params = { :status => 'current bad string' }
      sanitizer.should_not be_valid
      sanitizer.errors[0].field.should eq('/status')
    end
  end

  describe "minimum and maximum options" do
    it "is invalid if integer is lower than the minimum" do
      @params = { :integer_attribute => 0 }
      sanitizer.should_not be_valid
    end

    it "is invalid if integer is greater than the maximum" do
      @params = { :integer_attribute => 101 }
      sanitizer.should_not be_valid
    end

    it "is valid when integer is within given range" do
      @params = { :limited_collection => ['goldilocks'] }
      sanitizer.should be_valid
    end

    it "is invalid if float is lower than the minimum" do
      @params = { :float_attribute => 0.0 }
      sanitizer.should_not be_valid
    end

    it "is invalid if float is greater than the maximum" do
      @params = { :float_attribute => 101.0 }
      sanitizer.should_not be_valid
    end
  end

  describe "strip_4byte_chars option" do
    it "is valid when given a string with 4-byte chars" do
      @params = { :utf8mb4_string => "test \u{1F435} value" }
      sanitizer.should be_valid
    end

    it "returns sanitized string without 4-byte chars" do
      @params = { :utf8mb4_string => "test\u{1F435}" }
      sanitizer[:utf8mb4_string].should eq "test"
    end

    it "properly handles string with 4-byte char at the beginning" do
      @params = { :utf8mb4_string => "\u{1F435} 4-byte char at the beginning" }
      sanitizer[:utf8mb4_string].should eq ' 4-byte char at the beginning'
    end

    it "properly handles string with 4-byte char in the middle" do
      @params = { :utf8mb4_string => "4-byte char\u{1F435} in the middle" }
      sanitizer[:utf8mb4_string].should eq '4-byte char in the middle'
    end

    it "properly handles string with 4-byte char at the end" do
      @params = { :utf8mb4_string => "4-byte char at the end \u{1F435}" }
      sanitizer[:utf8mb4_string].should eq '4-byte char at the end '
    end

    it "does not strip 3-byte chars" do
      @params = { :utf8mb4_string => "Test \u{270A}" }
      sanitizer[:utf8mb4_string].should eq "Test \u{270A}"
    end

    describe "when used with other options" do
      describe "allow" do
        it "is valid when string matches any value in allowlist before stripping 4-byte chars" do
          @params = { :value_restricted_utf8mb4_string => "test" }
          sanitizer.should be_valid
        end

        it "is invalid when string doesn't match any value in allowlist before stripping 4-byte chars" do
          @params = { :value_restricted_utf8mb4_string => "test\u{1F435}" }
          sanitizer.should_not be_valid
        end
      end

      describe "allow_blank=false" do
        it "is invalid when string is already blank before stripping 4-byte chars" do
          @params = { :non_blank_utf8mb4_string => " " }
          sanitizer.should_not be_valid
        end

        it "is invalid when string becomes blank as a result of stripping 4-byte chars" do
          @params = { :non_blank_utf8mb4_string => " \u{1F435} " }
          sanitizer.should_not be_valid
        end
      end

      describe "minimum and maximum" do
        it "is invalid when string is already too long before stripping 4-byte chars" do
          @params = { :size_restricted_utf8mb4_string => "1234\u{1F435}" }
          sanitizer.should_not be_valid
        end

        it "is invalid when string becomes too short as a result of stripping 4-byte chars" do
          @params = { :size_restricted_utf8mb4_string => "1\u{1F435}" }
          sanitizer.should_not be_valid
        end
      end
    end
  end

  describe "strict param checking" do
    it "is invalid when given extra params" do
      @params = { :extra => 'test', :extra2 => 1 }
      sanitizer.should_not be_valid
      sanitizer.errors.count.should eq(2)
    end

    it "is invalid when given extra params in a nested sanitizer" do
      @params = { :address => { :extra => 0 }, :tags => [ { :extra2 => 1 } ] }
      sanitizer.should_not be_valid
      sanitizer.errors.map(&:field).should contain_exactly('/address/extra', '/tags/0/extra2')
    end
  end

  describe "converters with provided values" do
    let(:sanitizer) { CustomConverterWithProvidedValue.new(@params) }

    it "is valid when converter passes check with provided value" do
      @params = {from: 1, to: 3}
      sanitizer.should be_valid
    end

    it "is invalid when converter does not pass check with provided value" do
      @params = {from: 3, to: 1}
      sanitizer.should_not be_valid
    end
  end

  describe "strict type checking" do
    it "is invalid when given string instead of integer" do
      @params = { :integer_attribute => '1' }
      sanitizer.should_not be_valid
      sanitizer.errors[0].field.should eq('/integer_attribute')
    end

    it "is valid when given an integer" do
      @params = { :integer_attribute => 50 }
      sanitizer.should be_valid
      sanitizer[:integer_attribute].should eq(50)
    end

    it "is invalid when given a float" do
      @params = { :integer_attribute => 50.99 }
      sanitizer.should_not be_valid
    end

    it "is valid when given nil for an integer" do
      @params = { :integer_attribute => nil }
      sanitizer.should be_valid
      sanitizer[:integer_attribute].should be_nil
    end

    it "is invalid when given string instead of float" do
      @params = { :float_attribute => '1' }
      sanitizer.should_not be_valid
      sanitizer.errors[0].field.should eq('/float_attribute')
    end

    it "is valid when given a float" do
      @params = { :float_attribute => 50.0 }
      sanitizer.should be_valid
      sanitizer[:float_attribute].should eq(50.0)
    end

    it "is valid when given nil for a float" do
      @params = { :float_attribute => nil }
      sanitizer.should be_valid
      sanitizer[:float_attribute].should be_nil
    end

    it "is valid when given string is matching regexp" do
      @params = { :regexp_string => "#8bd635" }
      sanitizer.should be_valid
      sanitizer[:regexp_string].should eq('#8bd635')
    end

    it "is invalid when given string is not matching regexp" do
      @params = { :regexp_string => "not a hex value" }
      sanitizer.should_not be_valid
      sanitizer.errors[0].field.should eq('/regexp_string')
    end

    it "is invalid when given integer instead of string" do
      @params = { :string_attribute => 0 }
      sanitizer.should_not be_valid
      sanitizer.errors[0].field.should eq('/string_attribute')
    end

    it "is invalid when given float instead of string" do
      @params = { :string_attribute => 3.1415 }
      sanitizer.should_not be_valid
      sanitizer.errors[0].field.should eq('/string_attribute')
    end

    it "is valid when given a string" do
      @params = { :string_attribute => '#@!#%#$@#ad' }
      sanitizer.should be_valid
      sanitizer[:string_attribute].should eq('#@!#%#$@#ad')
    end

    it "is invalid when given 'yes' as a bool" do
      @params = { :bool_attribute => 'yes' }
      sanitizer.should_not be_valid
      sanitizer.errors[0].field.should eq('/bool_attribute')
    end

    it "is valid when given true as a bool" do
      @params = { :bool_attribute => true }
      sanitizer.should be_valid
    end

    it "is valid when given false as a bool" do
      @params = { :bool_attribute => false }
      sanitizer.should be_valid
    end

    it "is invalid when given an incorrect datetime" do
      @params = { :datetime_attribute => "2014-08-2716:32:56Z" }
      sanitizer.should_not be_valid
      sanitizer.errors[0].field.should eq('/datetime_attribute')
    end

    it "is valid when given a correct datetime" do
      @params = { :datetime_attribute => "2014-08-27T16:32:56Z" }
      sanitizer.should be_valid
    end

    it "is valid when given a 'forever' timestamp" do
      @params = { :datetime_attribute => "9999-12-31T00:00:00Z" }
      sanitizer.should be_valid
    end

    it "is invalid when given an incorrect date" do
      @params = { :date_attribute => "invalid" }
      sanitizer.should_not be_valid
      sanitizer.errors[0].field.should eq('/date_attribute')
    end

    it "is valid when given a correct date" do
      @params = { :date_attribute => "2015-08-27" }
      sanitizer.should be_valid
    end

    it "is valid when given a correct negative date" do
      @params = { :date_attribute => "-2014-08-27" }
      sanitizer.should be_valid
    end

    it "is valid when given a correct URL" do
      @params = { :website => "https://google.com" }
      sanitizer.should be_valid
      sanitizer[:website].should eq("https://google.com")
    end

    it "is invalid when given an invalid URL" do
      @params = { :website => "ht:/google.com" }
      sanitizer.should_not be_valid
    end

    it "is invalid when given an invalid URL that contains a valid URL" do
      @params = { :website => "watwat http://google.com wat" }
      sanitizer.should_not be_valid
    end

    describe "blank and required values" do
      let(:sanitizer) { BlankValuesPayloadSanitizer.new(@params) }
      let(:defaults) { { :required_string => 'zz' } }

      it "is invalid if required string is missing" do
        @params = {}
        sanitizer.should_not be_valid
        sanitizer.errors[0].should be_an_instance_of(InputSanitizer::ValueMissingError)
        sanitizer.errors[0].field.should eq('/required_string')
      end

      it "is invalid if required string is nil" do
        @params = { :required_string => nil }
        sanitizer.should_not be_valid
        sanitizer.errors[0].should be_an_instance_of(InputSanitizer::BlankValueError)
        sanitizer.errors[0].field.should eq('/required_string')
      end

      it "is invalid if required string is blank" do
        @params = { :required_string => ' ' }
        sanitizer.should_not be_valid
        sanitizer.errors[0].should be_an_instance_of(InputSanitizer::BlankValueError)
        sanitizer.errors[0].field.should eq('/required_string')
      end

      it "is invalid if non-nil datetime is null" do
        @params = defaults.merge({ :non_nil_datetime => nil })
        sanitizer.should_not be_valid
        sanitizer.errors[0].should be_an_instance_of(InputSanitizer::BlankValueError)
        sanitizer.errors[0].field.should eq('/non_nil_datetime')
      end

      it "is valid if non-nil datetime is blank" do
        @params = defaults.merge({ :non_nil_datetime => '' })
        sanitizer.should be_valid
      end

      it "is invalid if non-blank url is nil" do
        @params = defaults.merge({ :non_blank_url => nil })
        sanitizer.should_not be_valid
        sanitizer.errors[0].should be_an_instance_of(InputSanitizer::BlankValueError)
        sanitizer.errors[0].field.should eq('/non_blank_url')
      end

      it "is invalid if non-blank url is blank" do
        @params = defaults.merge({ :non_blank_url => '' })
        sanitizer.should_not be_valid
        sanitizer.errors[0].should be_an_instance_of(InputSanitizer::BlankValueError)
        sanitizer.errors[0].field.should eq('/non_blank_url')
      end
    end

    describe "nested checking" do
      describe "simple array" do
        it "returns JSON pointer for invalid fields" do
          @params = { :array => [1, 'z', '3', 4] }
          sanitizer.errors.length.should eq(2)
          sanitizer.errors.map(&:field).should contain_exactly('/array/1', '/array/2')
        end
      end

      describe "nested object" do
        it "returns an error when given a nil for a nested value" do
          @params = { :address => nil }
          sanitizer.should_not be_valid
        end

        it "returns an error when given a string for a nested value" do
          @params = { :address => 'nope' }
          sanitizer.should_not be_valid
        end

        it "returns an error when given an array for a nested value" do
          @params = { :address => ['a'] }
          sanitizer.should_not be_valid
        end

        it "returns JSON pointer for invalid fields" do
          @params = { :address => { :city => 0, :zip => 1 } }
          sanitizer.errors.length.should eq(2)
          sanitizer.errors.map(&:field).should contain_exactly('/address/city', '/address/zip')
        end

        it "allows nil with `allow_nil` flag" do
          @params = { :nullable_address => nil }
          sanitizer.should be_valid
          sanitizer.cleaned.fetch(:nullable_address).should eq(nil)
        end
      end

      describe "array of nested objects" do
        it "returns an error when given a nil for a collection" do
          @params = { :tags => nil }
          sanitizer.should_not be_valid
        end

        it "returns an error when given a string for a collection" do
          @params = { :tags => 'nope' }
          sanitizer.should_not be_valid
        end

        it "returns an error when given a hash for a collection" do
          @params = { :tags => { :a => 1 } }
          sanitizer.should_not be_valid
        end

        it "returns JSON pointer for invalid fields" do
          @params = { :tags => [ { :id => 'n', :name => 1 }, { :id => 10, :name => 2 } ] }
          sanitizer.errors.length.should eq(3)
          sanitizer.errors.map(&:field).should contain_exactly(
            '/tags/0/id',
            '/tags/0/name',
            '/tags/1/name'
          )
        end
      end

      describe "array of nested objects that have array of nested objects" do
        it "returns JSON pointer for invalid fields" do
          @params = { :tags => [
            { :id => 'n', :addresses => [ { :city => 0 }, { :city => 1 } ] },
            { :name => 2, :addresses => [ { :city => 3 } ] },
          ] }
          sanitizer.errors.length.should eq(5)
          sanitizer.errors.map(&:field).should contain_exactly(
            '/tags/0/id',
            '/tags/0/addresses/0/city',
            '/tags/0/addresses/1/city',
            '/tags/1/name',
            '/tags/1/addresses/0/city'
          )

          ec = sanitizer.error_collection
          ec.length.should eq(5)
        end
      end
    end
  end
end


text:
DELETE FROM KRCR_DRVD_CMPNT_T
/
DELETE FROM KRCR_CMPNT_SET_T
/

redpajama_set_name: RedPajamaGithub


text:
layout: default
---

{{ site.author.job }}

{{ site.author.bio }}

        Say hello
        Know More

  {% if site.posts.size > 0 %}
    {% for post in site.posts %}

      {% if post.image %}

      {% endif %}

          {{post.title}}

          Published <time datetime="{{ post.date | date_to_xmlschema }}">{% assign date_format = site.minima.date_format | default: "%B %-d, %Y" %}{{ post.date | date: date_format }}</time>

{% if post.description %}{{ post.description }}{% else %}{{ post.content | strip_html | truncate: 130 }}{% endif %}

        Read the rest

    {% endfor %}
  {% endif %}


text:
class UserStructure < ActiveRecord::Base
  belongs_to :structure
  belongs_to :user
end


text:
package im.vector.fragments;

import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;

import org.matrix.androidsdk.MXSession;
import org.matrix.androidsdk.core.BingRulesManager;
import org.matrix.androidsdk.core.Log;
import org.matrix.androidsdk.core.callback.ApiCallback;
import org.matrix.androidsdk.core.callback.SimpleApiCallback;
import org.matrix.androidsdk.core.model.MatrixError;
import org.matrix.androidsdk.data.Room;
import org.matrix.androidsdk.data.RoomSummary;
import org.matrix.androidsdk.data.RoomTag;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import im.vector.Matrix;
import im.vector.R;
import im.vector.activity.CommonActivityUtils;
import im.vector.activity.VectorHomeActivity;
import im.vector.activity.VectorRoomActivity;
import im.vector.adapters.AbsAdapter;
import im.vector.ui.badge.BadgeProxy;
import im.vector.util.HomeRoomsViewModel;
import im.vector.util.RoomUtils;

/**
 * Abstract fragment providing the universal search
 */
public abstract class AbsHomeFragment extends VectorBaseFragment implements
        AbsAdapter.RoomInvitationListener,
        AbsAdapter.MoreRoomActionListener,
        RoomUtils.MoreActionListener {

    private static final String LOG_TAG = AbsHomeFragment.class.getSimpleName();
    private static final String CURRENT_FILTER = "CURRENT_FILTER";

    VectorHomeActivity mActivity;

    String mCurrentFilter;

    MXSession mSession;
    OnRoomChangedListener mOnRoomChangedListener;

    final RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            // warn only if there is dy i.e the list has been really scrolled not refreshed
            if ((null != mActivity) && (0 != dy)) {
                mActivity.hideFloatingActionButton(getTag());
            }
        }
    };

    int mPrimaryColor = -1;
    int mSecondaryColor = -1;
    int mFabColor = -1;
    int mFabPressedColor = -1;

    /*
     * *********************************************************************************************
     * Fragment lifecycle
     * *********************************************************************************************
     */

    @Override
    @CallSuper
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    @CallSuper
    public void onActivityCreated(final Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (getActivity() instanceof VectorHomeActivity) {
            mActivity = (VectorHomeActivity) getActivity();
        }
        mSession = Matrix.getInstance(getActivity()).getDefaultSession();
        if (savedInstanceState != null && savedInstanceState.containsKey(CURRENT_FILTER)) {
            mCurrentFilter = savedInstanceState.getString(CURRENT_FILTER);
        }
    }

    @Override
    @CallSuper
    public void onResume() {
        super.onResume();
        if (mActivity != null) {
            mActivity.updateTabStyle(mPrimaryColor, mSecondaryColor, mFabColor, mFabPressedColor);

            final HomeRoomsViewModel.Result result = mActivity.getRoomsViewModel().getResult();
            onRoomResultUpdated(result);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.ic_action_mark_all_as_read:
                Log.d(LOG_TAG, "onOptionsItemSelected mark all as read");
                onMarkAllAsRead();
                return true;
        }
        return false;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(CURRENT_FILTER, mCurrentFilter);
    }

    @Override
    @CallSuper
    public void onDestroyView() {
        super.onDestroyView();
        mCurrentFilter = null;
    }

    @Override
    @CallSuper
    public void onDetach() {
        super.onDetach();
        mActivity = null;
    }

    /*
     * *********************************************************************************************
     * Listeners
     * *********************************************************************************************
     */

    @Override
    public void onPreviewRoom(MXSession session, String roomId) {
        Log.i(LOG_TAG, "onPreviewRoom " + roomId);
        mActivity.onPreviewRoom(session, roomId);
    }

    @Override
    public void onRejectInvitation(MXSession session, String roomId) {
        Log.i(LOG_TAG, "onRejectInvitation " + roomId);
        mActivity.onRejectInvitation(roomId, null);
    }

    @Override
    public void onMoreActionClick(View itemView, Room room) {
        // User clicked on the "more actions" area
        final Set<String> tags = room.getAccountData().getKeys();
        final boolean isFavorite = tags != null && tags.contains(RoomTag.ROOM_TAG_FAVOURITE);
        final boolean isLowPriority = tags != null && tags.contains(RoomTag.ROOM_TAG_LOW_PRIORITY);
        RoomUtils.displayPopupMenu(mActivity, mSession, room, itemView, isFavorite, isLowPriority, this);
    }

    @Override
    public void onUpdateRoomNotificationsState(MXSession session, String roomId, BingRulesManager.RoomNotificationState state) {
        mActivity.showWaitingView();
        session.getDataHandler().getBingRulesManager().updateRoomNotificationState(roomId, state, new BingRulesManager.onBingRuleUpdateListener() {
            @Override
            public void onBingRuleUpdateSuccess() {
                onRequestDone(null);
            }

            @Override
            public void onBingRuleUpdateFailure(final String errorMessage) {
                onRequestDone(errorMessage);
            }
        });
    }

    @Override
    public void onToggleDirectChat(MXSession session, final String roomId) {
        mActivity.showWaitingView();
        RoomUtils.toggleDirectChat(session, roomId, new ApiCallback<Void>() {
            @Override
            public void onSuccess(Void info) {
                onRequestDone(null);
                if (mOnRoomChangedListener != null) {
                    mOnRoomChangedListener.onToggleDirectChat(roomId, RoomUtils.isDirectChat(mSession, roomId));
                }
            }

            @Override
            public void onNetworkError(Exception e) {
                onRequestDone(e.getLocalizedMessage());
            }

            @Override
            public void onMatrixError(MatrixError e) {
                onRequestDone(e.getLocalizedMessage());
            }

            @Override
            public void onUnexpectedError(Exception e) {
                onRequestDone(e.getLocalizedMessage());
            }
        });
    }

    @Override
    public void moveToFavorites(MXSession session, String roomId) {
        updateTag(roomId, null, RoomTag.ROOM_TAG_FAVOURITE);
    }

    @Override
    public void moveToConversations(MXSession session, String roomId) {
        updateTag(roomId, null, null);
    }

    @Override
    public void moveToLowPriority(MXSession session, String roomId) {
        updateTag(roomId, null, RoomTag.ROOM_TAG_LOW_PRIORITY);
    }

    @Override
    public void onLeaveRoom(final MXSession session, final String roomId) {
        RoomUtils.showLeaveRoomDialog(getActivity(), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (mActivity != null && !mActivity.isFinishing()) {
                    mActivity.onRejectInvitation(roomId, new SimpleApiCallback<Void>() {
                        @Override
                        public void onSuccess(Void info) {
                            if (mOnRoomChangedListener != null) {
                                mOnRoomChangedListener.onRoomLeft(roomId);
                            }
                        }
                    });
                }
            }
        });
    }

    @Override
    public void onForgetRoom(final MXSession session, final String roomId) {
        mActivity.onForgetRoom(roomId, new SimpleApiCallback<Void>() {
            @Override
            public void onSuccess(Void info) {
                if (mOnRoomChangedListener != null) {
                    mOnRoomChangedListener.onRoomForgot(roomId);
                }
            }
        });
    }

    @Override
    public void addHomeScreenShortcut(MXSession session, String roomId) {
        RoomUtils.addHomeScreenShortcut(getActivity(), session, roomId);
    }

    /*
     * *********************************************************************************************
     * Public methods
     * *********************************************************************************************
     */

    /**
     * Apply the filter
     *
     * @param pattern
     */
    public void applyFilter(final String pattern) {
        if (TextUtils.isEmpty(pattern)) {
            if (mCurrentFilter != null) {
                onResetFilter();
                mCurrentFilter = null;
            }
        } else if (!TextUtils.equals(mCurrentFilter, pattern)) {
            onFilter(pattern, new OnFilterListener() {
                @Override
                public void onFilterDone(int nbItems) {
                    mCurrentFilter = pattern;
                }
            });
        }
    }

    /**
     * A room summary has been updated
     *
     * @param result
     */
    public void onRoomResultUpdated(final HomeRoomsViewModel.Result result) {
        //no-op
    }

    /**
     * Open the selected room
     *
     * @param room
     */
    protected void openRoom(final Room room) {
        // sanity checks
        // reported by GA
        if ((null == mSession.getDataHandler()) || (null == mSession.getDataHandler().getStore())) {
            return;
        }

        final String roomId;
        // cannot join a leaving room
        if (room == null || room.isLeaving()) {
            roomId = null;
        } else {
            roomId = room.getRoomId();
        }

        if (roomId != null) {
            final RoomSummary roomSummary = mSession.getDataHandler().getStore().getSummary(roomId);

            if (null != roomSummary) {
                room.sendReadReceipt();
            }

            // Update badge unread count in case device is offline
            BadgeProxy.INSTANCE.specificUpdateBadgeUnreadCount(mSession, getContext());

            // Launch corresponding room activity
            Map<String, Object> params = new HashMap<>();
            params.put(VectorRoomActivity.EXTRA_MATRIX_ID, mSession.getMyUserId());
            params.put(VectorRoomActivity.EXTRA_ROOM_ID, roomId);

            CommonActivityUtils.goToRoomPage(getActivity(), mSession, params);
        }
    }

    /**
     * Manage the fab actions
     *
     * @return true if the fragment has a dedicated action.
     */
    public boolean onFabClick() {
        return false;
    }

    /*
     * *********************************************************************************************
     * Private methods
     * *********************************************************************************************
     */

    /**
     * Change the tag of the given room with the provided one
     *
     * @param roomId
     * @param newTagOrder
     * @param newTag
     */
    private void updateTag(final String roomId, Double newTagOrder, final String newTag) {
        mActivity.showWaitingView();
        RoomUtils.updateRoomTag(mSession, roomId, newTagOrder, newTag, new ApiCallback<Void>() {
            @Override
            public void onSuccess(Void info) {
                onRequestDone(null);
            }

            @Override
            public void onNetworkError(Exception e) {
                onRequestDone(e.getLocalizedMessage());
            }

            @Override
            public void onMatrixError(MatrixError e) {
                onRequestDone(e.getLocalizedMessage());
            }

            @Override
            public void onUnexpectedError(Exception e) {
                onRequestDone(e.getLocalizedMessage());
            }
        });
    }

    /**
     * Handle the end of any request : hide loading wheel and display error message if there is any
     *
     * @param errorMessage
     */
    private void onRequestDone(final String errorMessage) {
        if (mActivity != null && !mActivity.isFinishing()) {
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mActivity.hideWaitingView();
                    if (!TextUtils.isEmpty(errorMessage)) {
                        Toast.makeText(mActivity, errorMessage, Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }

    /**
     * Mark all the fragment rooms as read
     */
    private void onMarkAllAsRead() {
        mActivity.showWaitingView();

        mSession.markRoomsAsRead(getRooms(), new ApiCallback<Void>() {
            @Override
            public void onSuccess(Void info) {
                // check if the activity is still attached
                if ((null != mActivity) && !mActivity.isFinishing()) {
                    mActivity.hideWaitingView();
                    mActivity.refreshUnreadBadges();
                    mActivity.onRoomDataUpdated();
                }
            }

            private void onError(String errorMessage) {
                Log.e(LOG_TAG, "## markAllMessagesAsRead() failed " + errorMessage);
                onSuccess(null);
            }

            @Override
            public void onNetworkError(Exception e) {
                onError(e.getMessage());
            }

            @Override
            public void onMatrixError(MatrixError e) {
                onError(e.getMessage());
            }

            @Override
            public void onUnexpectedError(Exception e) {
                onError(e.getMessage());
            }
        });
    }

    /*
     * *********************************************************************************************
     * Abstract methods
     * *********************************************************************************************
     */

    protected abstract List<Room> getRooms();

    protected abstract void onFilter(final String pattern, final OnFilterListener listener);

    protected abstract void onResetFilter();

    /*
     * *********************************************************************************************
     * Listener
     * *********************************************************************************************
     */

    public interface OnFilterListener {
        void onFilterDone(final int nbItems);
    }

    public interface OnRoomChangedListener {

        void onToggleDirectChat(final String roomId, final boolean isDirectChat);

        void onRoomLeft(final String roomId);

        void onRoomForgot(final String roomId);
    }
}


text:
"""Support for Daikin AC sensors."""
from homeassistant.components.sensor import SensorEntity
from homeassistant.const import (
    CONF_DEVICE_CLASS,
    CONF_ICON,
    CONF_NAME,
    CONF_TYPE,
    CONF_UNIT_OF_MEASUREMENT,
)

from . import DOMAIN as DAIKIN_DOMAIN, DaikinApi
from .const import (
    ATTR_COOL_ENERGY,
    ATTR_HEAT_ENERGY,
    ATTR_HUMIDITY,
    ATTR_INSIDE_TEMPERATURE,
    ATTR_OUTSIDE_TEMPERATURE,
    ATTR_TARGET_HUMIDITY,
    ATTR_TOTAL_POWER,
    SENSOR_TYPE_ENERGY,
    SENSOR_TYPE_HUMIDITY,
    SENSOR_TYPE_POWER,
    SENSOR_TYPE_TEMPERATURE,
    SENSOR_TYPES,
)

async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
    """Old way of setting up the Daikin sensors.

    Can only be called when a user accidentally mentions the platform in their
    config. But even in that case it would have been ignored.
    """

async def async_setup_entry(hass, entry, async_add_entities):
    """Set up Daikin climate based on config_entry."""
    daikin_api = hass.data[DAIKIN_DOMAIN].get(entry.entry_id)
    sensors = [ATTR_INSIDE_TEMPERATURE]
    if daikin_api.device.support_outside_temperature:
        sensors.append(ATTR_OUTSIDE_TEMPERATURE)
    if daikin_api.device.support_energy_consumption:
        sensors.append(ATTR_TOTAL_POWER)
        sensors.append(ATTR_COOL_ENERGY)
        sensors.append(ATTR_HEAT_ENERGY)
    if daikin_api.device.support_humidity:
        sensors.append(ATTR_HUMIDITY)
        sensors.append(ATTR_TARGET_HUMIDITY)
    async_add_entities([DaikinSensor.factory(daikin_api, sensor) for sensor in sensors])

class DaikinSensor(SensorEntity):
    """Representation of a Sensor."""

    @staticmethod
    def factory(api: DaikinApi, monitored_state: str):
        """Initialize any DaikinSensor."""
        cls = {
            SENSOR_TYPE_TEMPERATURE: DaikinClimateSensor,
            SENSOR_TYPE_HUMIDITY: DaikinClimateSensor,
            SENSOR_TYPE_POWER: DaikinPowerSensor,
            SENSOR_TYPE_ENERGY: DaikinPowerSensor,
        }[SENSOR_TYPES[monitored_state][CONF_TYPE]]
        return cls(api, monitored_state)

    def __init__(self, api: DaikinApi, monitored_state: str) -> None:
        """Initialize the sensor."""
        self._api = api
        self._sensor = SENSOR_TYPES[monitored_state]
        self._name = f"{api.name} {self._sensor[CONF_NAME]}"
        self._device_attribute = monitored_state

    @property
    def unique_id(self):
        """Return a unique ID."""
        return f"{self._api.device.mac}-{self._device_attribute}"

    @property
    def name(self):
        """Return the name of the sensor."""
        return self._name

    @property
    def state(self):
        """Return the state of the sensor."""
        raise NotImplementedError

    @property
    def device_class(self):
        """Return the class of this device."""
        return self._sensor.get(CONF_DEVICE_CLASS)

    @property
    def icon(self):
        """Return the icon of this device."""
        return self._sensor.get(CONF_ICON)

    @property
    def unit_of_measurement(self):
        """Return the unit of measurement."""
        return self._sensor[CONF_UNIT_OF_MEASUREMENT]

    async def async_update(self):
        """Retrieve latest state."""
        await self._api.async_update()

    @property
    def device_info(self):
        """Return a device description for device registry."""
        return self._api.device_info

class DaikinClimateSensor(DaikinSensor):
    """Representation of a Climate Sensor."""

    @property
    def state(self):
        """Return the internal state of the sensor."""
        if self._device_attribute == ATTR_INSIDE_TEMPERATURE:
            return self._api.device.inside_temperature
        if self._device_attribute == ATTR_OUTSIDE_TEMPERATURE:
            return self._api.device.outside_temperature

        if self._device_attribute == ATTR_HUMIDITY:
            return self._api.device.humidity
        if self._device_attribute == ATTR_TARGET_HUMIDITY:
            return self._api.device.target_humidity
        return None

class DaikinPowerSensor(DaikinSensor):
    """Representation of a power/energy consumption sensor."""

    @property
    def state(self):
        """Return the state of the sensor."""
        if self._device_attribute == ATTR_TOTAL_POWER:
            return round(self._api.device.current_total_power_consumption, 3)
        if self._device_attribute == ATTR_COOL_ENERGY:
            return round(self._api.device.last_hour_cool_energy_consumption, 3)
        if self._device_attribute == ATTR_HEAT_ENERGY:
            return round(self._api.device.last_hour_heat_energy_consumption, 3)
        return None


text:
require 'squirrell/version'
require 'squirrell/class_methods'
require 'squirrell/instance_methods'

# Including this module gives a few convenience methods for query objects.
module Squirrell
  class << self
    attr_accessor :requires
    attr_accessor :permits
    attr_reader :executor

    def executor=(e)
      unless e.respond_to? :call
        fail ExecutorError, 'Executor must respond to `#call`'
      end
      @executor = e
    end
  end

  def self.configure
    yield self
  end

  # Errors raised when the executor doesn't respond to call.
  class ExecutorError < ArgumentError; end

  # Error raised when result of `arel` doesn't respond to `to_sql`
  class InvalidArelError < ArgumentError; end

  # Error raised when a required parameter is not passed.
  class MissingParameterError < ArgumentError; end

  # Error raised when a parameter passed into `.find` is not included in either
  # requires or permits.
  class UnusedParameter < ArgumentError; end

  def self.included(klass)
    Squirrell.requires ||= {}
    Squirrell.requires[klass] = []
    Squirrell.permits ||= {}
    Squirrell.permits[klass] = []

    klass.extend ClassMethods
    klass.include InstanceMethods
  end
end


text:
simple
======

Yet another CSS framework


text:
=head1 CONTACT

  Please email comments or questions to the public Ensembl
  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.

  Questions may also be sent to the Ensembl help desk at
  <helpdesk.org>.

=cut

# Import COSMIC data into an Ensembl variation schema database

use strict;
use warnings;

use Getopt::Long;

use Bio::EnsEMBL::Registry;
use Bio::EnsEMBL::Variation::DBSQL::DBAdaptor;
use Bio::EnsEMBL::Utils::Sequence qw(reverse_comp);
use Bio::EnsEMBL::Variation::Utils::Sequence qw(SO_variation_class);

my $USE_DB = 1;
my $ADD_SETS = 1;
my $VERBOSE = 1;

my $import_file;
my $registry_file;
my $version;
my $help;

GetOptions(
    "import|i=s"    => \$import_file,
    "registry|r=s"  => \$registry_file,
    "verbose|v"     => \$VERBOSE,
    "version=s"     => \$version,
    "test|t"        => \$USE_DB,
    "help|h"        => \$help,
);

unless (defined($registry_file) && defined($import_file) && defined($version)) {
    print "Must supply an import file, a registry file and a version ...\n" unless $help;
    $help = 1;
}
if ($import_file =~ /\.gz$/) {
  print "Please unzip the input file before running the script!\n";
  exit(0);
}
if ($help) {
    print "Usage: $0 --import <import_file> --registry <reg_file> --version <cosmic_version>\n";
    exit(0);
}

my $registry = 'Bio::EnsEMBL::Registry';

$registry->load_all($registry_file);

my $sa = $registry->get_adaptor(
    'human', 'core', 'slice'
);

my $dbh = $registry->get_adaptor(
    'human', 'variation', 'variation'
)->dbc->db_handle;

open my $INPUT, "<$import_file" or die "Can't open '$import_file'";

my $set_version_sth = $dbh->prepare(qq{UPDATE source SET version = ? WHERE source_id = ?});

# check to see if we already have the COSMIC source
my $src_sth = $dbh->prepare(qq{ SELECT source_id FROM source WHERE name LIKE "COSMIC%" });
$src_sth->execute;

my ($source_id) = $src_sth->fetchrow_array;

if ($source_id) {
    print "Found existing source_id: $source_id\n";
    $set_version_sth->execute($version,$source_id);
}
else {
    # if not, add it
    my $sth = $dbh->prepare(qq{
        INSERT INTO source (name, description, url, somatic_status, version)
        VALUES (
            'COSMIC',
            'Somatic mutations found in human cancers from the COSMIC project',
            'http://cancer.sanger.ac.uk/cancergenome/projects/cosmic/',
            'somatic',
            $version
        );
    });

    $sth->execute;

    $source_id = $dbh->last_insert_id(undef, undef, undef, undef);

    print "New source_id: $source_id\n";
}

# set up the various queries and inserts we'll need

my %failed_desc_list = ( 1 => 'Variation has no associated sequence',
                         2 => 'Mapped position is not compatible with reported alleles'
                       );

my $vf_table = 'variation_feature';
my $cosmic_phe_prefix = 'COSMIC:tumour_site:';

# Variations
my $find_existing_var_sth = $dbh->prepare(qq{
    SELECT variation_id FROM variation WHERE name = ?
});

# Variation set COSMIC
my $get_cosmic_set_id_sth = $dbh->prepare(qq{
    SELECT variation_set_id FROM variation_set WHERE name = "COSMIC phenotype variants"
});

$get_cosmic_set_id_sth->execute;

my ($cosmic_set_id) = $get_cosmic_set_id_sth->fetchrow_array;

die "Didn't find COSMIC set id?" unless defined $cosmic_set_id;

# Variation set phenotypes
my $get_phenotype_set_id_sth = $dbh->prepare(qq{
    SELECT variation_set_id FROM variation_set WHERE name like '%phenotype-associated variants%'
});
$get_phenotype_set_id_sth->execute;

my ($phenotype_set_id) = $get_phenotype_set_id_sth->fetchrow_array;

die "Didn't find COSMIC variation set id?" unless defined $phenotype_set_id;

my $add_var_sth = $dbh->prepare(qq{
    INSERT INTO variation (source_id, name, flipped, class_attrib_id, somatic) VALUES (?,?,?,?,1)
});

my $add_var_set_sth = $dbh->prepare(qq{
    INSERT INTO variation_set_variation (variation_id, variation_set_id) VALUES (?,?)
});

my $add_failed_var_sth = $dbh->prepare(qq{
    INSERT INTO failed_variation (variation_id, failed_description_id) VALUES (?,?)
});

my $add_vf_sth = $dbh->prepare(qq{
    INSERT INTO $vf_table (variation_id, seq_region_id, seq_region_start,
        seq_region_end, seq_region_strand, variation_name, allele_string, map_weight,
        source_id, class_attrib_id, somatic)
    VALUES (?,?,?,?,?,?,?,?,?,?,1)
});

my $select_populations_sth = $dbh->prepare(qq{
    SELECT population_id, name FROM population WHERE name like "COSMIC%"
});

my $add_population_sth = $dbh->prepare(qq{
    INSERT INTO population (name, size, description)
    VALUES (?,?,?)
});

my $add_allele_with_code_sth = $dbh->prepare(qq{
    INSERT INTO allele (variation_id, population_id, allele_code_id, frequency)
    VALUES (?,?,?,?)
});

my $select_phenotypes_sth = $dbh->prepare(qq{
    SELECT phenotype_id, description FROM phenotype WHERE description LIKE "$cosmic_phe_prefix%"
});

my $add_phenotype_sth = $dbh->prepare(qq{
    INSERT INTO phenotype (description) VALUE (?)
});

my $add_phe_feature_sth = $dbh->prepare(qq{
    INSERT INTO phenotype_feature (phenotype_id, source_id, type, object_id, seq_region_id,
        seq_region_start, seq_region_end, seq_region_strand)
    VALUES (?,?,'Variation',?,?,?,?,?)
});

my $add_phe_feature_attrib_sth = $dbh->prepare(qq{
    INSERT INTO phenotype_feature_attrib (phenotype_feature_id, attrib_type_id, value)
    SELECT ?, attrib_type_id, ? FROM attrib_type WHERE code=?
});

# allele code id
my $select_allele_codes_sth = $dbh->prepare(qq{
    SELECT allele_code_id, allele FROM allele_code WHERE allele IN ('A','T','G','C','-');
});

my $get_allele_code_sth = $dbh->prepare(qq{
    SELECT allele_code_id
    FROM allele_code
    WHERE allele=?
});
my $count_like_allele_code_sth = $dbh->prepare(qq{
    SELECT count(allele_code_id)
    FROM allele_code
    WHERE allele like ?
});
my $insert_allele_code_sth = $dbh->prepare(qq{
    INSERT INTO allele_code (allele) VALUES (?)
});

# get the failed description ID we will use

my $get_failed_desc_sth = $dbh->prepare(qq{
    SELECT failed_description_id
    FROM   failed_description
    WHERE  description = ?
});

my $get_class_attrib_ids_sth = $dbh->prepare(qq{
    SELECT a.value, a.attrib_id
    FROM   attrib a, attrib_type at
    WHERE  a.attrib_type_id = at.attrib_type_id
    AND    at.code = 'SO_term'
});

my $patched_version = 0;

my %class_attrib_ids;
my %cosmic_genes_list;
my %cosmic_populations_list;
my %cosmic_phenotypes_list;
my %allele_codes_list;

#### Pre load some of the data ####
# Variant classes list
$get_class_attrib_ids_sth->execute;
while (my ($value, $attrib_id) = $get_class_attrib_ids_sth->fetchrow_array) {
  $class_attrib_ids{$value} = $attrib_id;
}

# Existing COSMIC populations (empty if you used the "remove_cosmic.pl" script before running this script)
$select_populations_sth->execute;
while (my ($p_id, $p_name) = $select_populations_sth->fetchrow_array) {
  $cosmic_populations_list{$p_name} = $p_id;
}

# Existing COSMIC phenotypes
$select_phenotypes_sth->execute;
while (my ($phe_id, $phe_name) = $select_phenotypes_sth->fetchrow_array) {
  $cosmic_phenotypes_list{$phe_name} = $phe_id;
}

# Allele code IDs (A,T,G,C,')
$select_allele_codes_sth->execute;
while (my ($ac_id, $ac_name) = $select_allele_codes_sth->fetchrow_array) {
  $allele_codes_list{$ac_name} = $ac_id;
}

# loop over the input file

MAIN_LOOP : while(<$INPUT>) {

    next unless /COSM/;

    my $line = $_;

    my (
        $cosmic_version,
        $cosmic_id,
        $cosmic_gene,
        $accession,
        $class,
        $cds,
        $aa,
        $chr,
        $start,
        $stop,
        $mut_nt,
        $mut_aa,
        $is_snp,
        $tumour_site,
        $mutated_samples,
        $total_samples,
        $freq
    ) = split /,/, $_;

    next unless $cosmic_id =~ /COSM\d+/;

    while (!defined($freq)) {
      my $new_line = <$INPUT>;
      chomp $line;
      $line = "$line$new_line";

      (
        $cosmic_version,
        $cosmic_id,
        $cosmic_gene,
        $accession,
        $class,
        $cds,
        $aa,
        $chr,
        $start,
        $stop,
        $mut_nt,
        $mut_aa,
        $is_snp,
        $tumour_site,
        $mutated_samples,
        $total_samples,
        $freq
      ) = split /,/, $line;
    }

    unless ($patched_version) {

        my ($curr_version) = $cosmic_version =~ /COSMIC v(\d+)/;

        die "No version information in file" unless $curr_version;

        $set_version_sth->execute($curr_version, $source_id);

        print "Set COSMIC version to $curr_version\n";

        $patched_version = 1;
    }

    my %cosmic_attrib = ('associated_gene' => $cosmic_gene);

    print "$cosmic_id:";

    if ($chr == 23) {
        $chr = 'X';
    }
    elsif ($chr == 24) {
        $chr = 'Y';
    }

    # check if we should swap the start & end

    if ($start > $stop + 1) {
        ($start, $stop) = ($stop, $start);
        print "Swapped start & end incorrect coords: start: $start stop: $stop\n";
    }

#    if ($class =~ /insertion/i && $mut_nt =~ /(^-)|^\s*$/ && $cds !~ /dup/i && $cds !~ /del/) {
#        if ($stop == $start+1) {
#            ($start, $stop) = ($stop, $start);
#            print "Swapped start & end for insertion: start: $start stop: $stop\n";
#        }
#        else {
#            print "Wierd start stop for insertion?\n";
#        }
#    }

    my $fail_variation = 0;

    my $dont_rev_comp = 0;

    if ($mut_nt =~ /^\s+$/) {
        #print "$cosmic_id: $cds $class\n";
        $mut_nt = '';

        if ($cds =~ /del([A-Z]+)/) {
            $mut_nt = "$1>-";
        }
        elsif ($cds =~ /del([0-9]+)/) {
            $mut_nt = "($1 BP DELETION)>-";
            $dont_rev_comp = 1;
        }
        elsif ($cds =~ /del?/) {
            $mut_nt = "DELETION>-";
            $dont_rev_comp = 1;
        }
        elsif ($cds =~ /ins([A-Z]+)/) {
            $mut_nt = "->$1";
        }
        elsif ($cds =~ /ins([0-9]+)/) {
            $mut_nt = "->($1 BP INSERTION)";
            $dont_rev_comp = 1;
        }
        elsif ($cds =~ /ins?/) {
            $mut_nt = "->INSERTION";
            $dont_rev_comp = 1;
        }
        elsif ($cds =~ /([A-Z]+)>([A-Z]+)/) {
            $mut_nt = "$1>$2";
        }
        elsif ($cds =~ />([A-Z]+)/) {
            $mut_nt = "->$1";
        }
        else {
            $fail_variation = 1;
            print "buggy: failing variation\n";
        }
    }

    $mut_nt = uc($mut_nt);

    # cosmic doesn't prefix insertions with a '-', so add one if necessary

    $mut_nt = '-'.$mut_nt if $mut_nt =~ /^>/;

    if ($mut_nt =~ /^-/) {
        if ($stop == $start+1) {
            ($start, $stop) = ($stop, $start);
            print "Swapped start & end for insertion: start: $start stop: $stop\n";
        }
        else {
            if ($start == $stop) {
                $start++;
                print "Insertion start == stop, patched to: start: $start stop: $stop\n";
            }
            else {
                $fail_variation = 2;
                print "Wierd start stop for insertion?\n";
            }
        }
    }

    if ($mut_nt =~ /([A-Z]+)>-$/) {
        my $seq = $1;
        my $seq_len = length($seq);
        if (($seq_len) > 1 && ($stop == $start)) {
            $stop = $start + $seq_len - 1;
            print "Patched stop coordinate for deletion\n";
        }
    }

    my $slice = $sa->fetch_by_region('chromosome', $chr, $start, $stop);

    if ($slice) {

        # try to find a matching ensembl gene

        my $ens_gene;

        my @genes = @{ $slice->get_all_Genes };

        my $check_strand = 0;

        my $strand;

        GENE : for my $gene (@genes) {

            # Use existing gene found
            if ($cosmic_genes_list{$cosmic_gene}{$accession}) {
              if ($cosmic_genes_list{$cosmic_gene}{$accession} eq $gene) {
                $ens_gene = $gene;
                last;
              }
            }

            if ($gene->external_name eq $cosmic_gene) {
                $ens_gene = $gene;
                last;
            }
            else {
                # try synonyms of this gene
                for my $db_entry (@{ $gene->get_all_DBEntries } ) {
                    for my $syn (@{ $db_entry->get_all_synonyms }) {
                        if ($syn eq $cosmic_gene) {
                            $ens_gene = $gene;
                            last GENE;
                        }
                    }
                }
            }

            if ($gene->display_xref && $gene->display_xref->display_id eq $cosmic_gene) {
                $ens_gene = $gene;
                last GENE;
            }

            if ($accession =~ /ENST/) {
                for my $tran (@{ $gene->get_all_Transcripts }) {
                    if ($tran->stable_id eq $accession) {
                        $ens_gene = $gene;
                        last GENE;
                    }
                }

                # Extract the gene name (e.g. CDKN2A_ENST00000361570 => extracts CDKN2A)
                my @g_names = split('_',$cosmic_gene);
                if (scalar @g_names > 1 and $g_names[1] =~ /ENST/) {
                    if ($gene->external_name eq $g_names[0]) {
                        $ens_gene = $gene;
                        last GENE;
                    }
                    else {
                        # try synonyms of this gene
                        for my $db_entry (@{ $gene->get_all_DBEntries } ) {
                            for my $syn (@{ $db_entry->get_all_synonyms }) {
                                if ($syn eq $g_names[0]) {
                                    $ens_gene = $gene;
                                    last GENE;
                                }
                            }
                        }
                    }
                }
            }

            if ($gene->description && $gene->description =~ /$cosmic_gene/) {
                $ens_gene = $gene;
                last GENE;
            }

        }

        if (!$ens_gene && @genes == 1) {
            $ens_gene = $genes[0];
            print "Guess gene is ".$ens_gene->external_name."\n";
            $check_strand = 1;
        }

        if ($ens_gene) {
            $strand = $ens_gene->strand;
            $cosmic_genes_list{$cosmic_gene}{$accession} = $ens_gene if (!$cosmic_genes_list{$cosmic_gene}{$accession});
        }
        else {
            my $num = @genes;

            my $strands_match = 0;

            my $poss_strand;

            if ($num > 0) {
                $strands_match = 1;
                $poss_strand = $genes[0]->strand;
                for my $gene (@genes) {
                    if ($poss_strand != $gene->strand) {
                        $strands_match = 0;
                        $poss_strand = undef;
                        last;
                    }
                }
            }

            $strand = $poss_strand;

            print "Can't find a matching gene for $cosmic_gene or $accession ";
            print "($num genes lie here - strands match: $strands_match)\n";

            $check_strand = 1;
        }

        my $ens_ref = $slice->seq || '-';

        my $ens_ref_comp = $ens_ref;

        reverse_comp(\$ens_ref_comp);

        my ($cs_ref_nt, $cs_mut_nt) = split />/, $mut_nt;
        my ($cs_ref_aa, $cs_mut_aa) = split />/, $mut_aa;

        if ($check_strand && $fail_variation != 1) {
            if ($cs_ref_nt eq $ens_ref) {

                if (defined $strand && $strand == 1) {
                    print "Guessed strand 1 looks OK\n";
                }
                else {
                    print "cosmic reference matches ensembl reference, using 1\n";
                    $strand = 1;
                }
            }
            elsif ($cs_ref_nt eq $ens_ref_comp) {
                if (defined $strand && $strand == -1) {
                    print "Guessed strand -1 looks OK\n";
                }
                else {
                    print "cosmic reference matches reverse complemented ensembl reference, using -1\n";
                    $strand = -1;
                }
            }

            unless (defined $strand) {
                print "Reference bases mismatch and no evidence for any strand - leaving\n";
                next;
            }
        }

        unless (defined $strand) {
          print "Reference bases mismatch and no evidence for any strand - leaving\n";
          next;
        }

        # these two variables are used when adding this feature to the DB because we
        # add everything as if it were on the forward strand, regardless of the cosmic
        # strand

        my $flipped = 0;
        my $var_strand = $strand;

        my $forward_strand_ref_allele = $cs_ref_nt;
        my $forward_strand_mut_allele = $cs_mut_nt;

        my $mismatching_reference;

        unless ($fail_variation == 1) {
            if ($cs_ref_nt ne $ens_ref) {
              if ($cs_ref_nt =~ /^[^ATGC]$/ && $class =~ /^Substitution/) {
                if ($cds =~ /c\.\d+(\w)>\w$/) {
                  $cs_ref_nt = uc($1) if ($1 !~ /$cs_ref_nt/i);
                }
              } elsif ($cs_ref_nt =~ /^\d+$/ && $class =~ /^Deletion/) {
                 $cs_ref_nt = $ens_ref;
              }
            }

            my $flag_update_allele = 0;

            # Reverse complement if alleles match the reverse strand sequence
            if ($strand == 1) {
              if ($cs_ref_nt ne $ens_ref) {
                unless ($dont_rev_comp) {
                  reverse_comp(\$cs_ref_nt);
                  reverse_comp(\$cs_mut_nt);
                }
                if ($cs_ref_nt ne $ens_ref) {
                  $mismatching_reference = "cosmic: $cs_ref_nt vs. ensembl: $ens_ref";
                }
                else {
                  $flipped = 1;
                  $flag_update_allele = 1;
                }
              }
            }
            # Reverse complement and change strand if alleles match the reverse strand sequence
            else {
              if ($cs_ref_nt eq $ens_ref_comp) {
                unless ($dont_rev_comp) {
                  reverse_comp(\$cs_ref_nt);
                  reverse_comp(\$cs_mut_nt);
                  $flipped = 1;
                  $flag_update_allele = 1;
                  $var_strand = 1;
                }
              } elsif ($cs_ref_nt eq $ens_ref) {
                $var_strand = 1;
              }  else {
                $mismatching_reference = "cosmic: $cs_ref_nt vs. ensembl: $ens_ref";
              }
            }

            if ($flag_update_allele == 1 && !$mismatching_reference) {
              $forward_strand_ref_allele = $cs_ref_nt;
              $forward_strand_mut_allele = $cs_mut_nt;
            }
        }

        if ($mismatching_reference) {
            my $ens_gene_id = ($ens_gene) ? $ens_gene->stable_id : 'Ensembl gene not found';
            print "Reference bases don't match for $cosmic_gene ($ens_gene_id): $mismatching_reference\n";

#            print "Other variations here:\n";
#
#            my $vfs = $slice->get_all_VariationFeatures;
#
#            for my $vf (@$vfs) {
#                print $vf->allele_string, "\n";
#            }
#
#            next;
        }

        my $allele_string = ($fail_variation == 1) ? '' : "$forward_strand_ref_allele/$forward_strand_mut_allele";

        my $class_id = $class_attrib_ids{
            SO_variation_class($allele_string, defined $mismatching_reference ? 0 : 1)
        };

        die "No class attrib id for allele string: $allele_string" unless defined $class_id;

        # handle large deletions, insertions and indels
        if (defined($forward_strand_ref_allele)) {
          if (length($forward_strand_ref_allele) > 50 || ($stop-$start+1) > 50) {
            $allele_string = ($forward_strand_mut_allele eq '-') ? "LARGE_DELETION" : "LARGE_INDEL";
          }
        }
        if (defined($forward_strand_mut_allele)) {
          if (length($forward_strand_mut_allele) > 50 || ($stop-$start+1) > 50) {
            $allele_string = ($forward_strand_ref_allele eq '-') ? "LARGE_INSERTION" : "LARGE_INDEL";
          }
        }

        unless ($USE_DB) {
            print " all OK\n";
            next;
        }

        # all OK so far so let's (try to) add stuff to the database

        my $seq_region_id = $sa->get_seq_region_id($slice);

        # first check to see if we already have this variation

        $find_existing_var_sth->execute($cosmic_id);

        my ($variation_id) = $find_existing_var_sth->fetchrow_array;

        if (!$variation_id) {

            # it's new, so add the main variation object,

            $add_var_sth->execute($source_id, $cosmic_id, $flipped, $class_id);

            $variation_id = $dbh->last_insert_id(undef, undef, undef, undef);

            if ($fail_variation) {
                my $failed_description_id = get_failed_description_id($fail_variation);
                $add_failed_var_sth->execute($variation_id, $failed_description_id);
                print "Failed variation\n";
                next MAIN_LOOP if ($fail_variation == 1);
            }

            if ($ADD_SETS) {
                $add_var_set_sth->execute($variation_id, $cosmic_set_id);
            }

            # the variation feature object.

            $add_vf_sth->execute(
                $variation_id,
                $seq_region_id,
                $start,
                $stop,
                $var_strand,
                $cosmic_id,
                $allele_string,
                1,
                $source_id,
                $class_id,
            );
        }

        # add sample and allele information

        # first check if there is an existing population

        my $population_id;

        my $sample_name = "COSMIC:gene:$cosmic_gene:tumour_site:$tumour_site";

        if ($cosmic_populations_list{$sample_name}) {
            $population_id = $cosmic_populations_list{$sample_name};
        }
        else {
            # there is not, so add it

            $add_population_sth->execute(
                $sample_name,
                $total_samples,
                "$total_samples $tumour_site tumours examined through the $cosmic_gene gene"
            );

            $population_id = $dbh->last_insert_id(undef, undef, undef, undef);
            $cosmic_populations_list{$sample_name} = $population_id;
        }

        my $mut_freq = $mutated_samples / $total_samples;

        # add the mutant allele
        my $mut_allele_code_id = get_allele_code($forward_strand_mut_allele);
        $add_allele_with_code_sth->execute(
            $variation_id,
            $population_id,
            $mut_allele_code_id,
            $mut_freq,
        );

        # and the reference allele
        my $ref_allele_code_id = get_allele_code($forward_strand_ref_allele);
        $add_allele_with_code_sth->execute(
            $variation_id,
            $population_id,
            $ref_allele_code_id,
            (1 - $mut_freq)
        );

        # try to find an existing phenotype, or create a new phenotype entry

        my $phenotype_id;

        my $phenotype_name = "$cosmic_phe_prefix$tumour_site";

        if ($cosmic_phenotypes_list{$phenotype_name}) {
            $phenotype_id = $cosmic_phenotypes_list{$phenotype_name};
        }
        else {
            $add_phenotype_sth->execute($phenotype_name);
            $phenotype_id = $dbh->last_insert_id(undef, undef, undef, undef);
            $cosmic_phenotypes_list{$phenotype_name} = $phenotype_id;
        }

        # add variation annotation (phenotype_feature)

        $add_phe_feature_sth->execute(
          $phenotype_id,
          $source_id,
          $cosmic_id,
          $seq_region_id,
          $start,
          $stop,
          1
        );
        my $pf_id = $dbh->last_insert_id(undef, undef, undef, undef);

        # add phenotype feature attributes
        foreach my $attrib (keys(%cosmic_attrib)) {
          $add_phe_feature_attrib_sth->execute($pf_id,$cosmic_attrib{$attrib},$attrib);
        }
        print " added to DB\n";
    }
    else {
        print "Failed to get slice for chr $chr $start - $stop\n";
        next;
    }
}

sub get_failed_description_id {
  my $failed_id = shift;
  my $description = $failed_desc_list{$failed_id};

  $get_failed_desc_sth->execute($description);
  my ($failed_description_id) = $get_failed_desc_sth->fetchrow_array;

  return $failed_description_id;
}

sub get_allele_code {
    my $allele = shift;

    my $allele_code_id;

    # Check if an entry exists in the allele_code hash
    if ($allele_codes_list{$allele}) { # A,T,G,C,-
      $allele_code_id = $allele_codes_list{$allele};
    }
    # Check if an entry exists in the allele_code table
    else {
      $get_allele_code_sth->execute($allele);
      ($allele_code_id) = $get_allele_code_sth->fetchrow_array;
    }

    # Check with large allele, because of issue with the allele index
    # (limited to unique 1000 first bases)
    if (!defined($allele_code_id) && length($allele) >= 1000) {
      my $indexed_string = substr($allele,0,1000).'%';
      $count_like_allele_code_sth->execute($indexed_string);
      my ($count_allele) = $count_like_allele_code_sth->fetchrow_array;
      if ($count_allele > 0) {
        $allele = '(LARGE ALLELE)';
        $get_allele_code_sth->execute($allele);
        ($allele_code_id) = $get_allele_code_sth->fetchrow_array;
      }
    }

    # Insert a new allele in the allele_code table
    if (!defined($allele_code_id)) {
      $insert_allele_code_sth->execute($allele);
      $allele_code_id = $dbh->last_insert_id(undef, undef, undef, undef);
    }

    return $allele_code_id;
}


text:
typedef NS_ENUM(NSUInteger, ParseMode)
{
    ParseModeStandard,
    ParseModeTileset,
    ParseModeTile,
    ParseModeTileProperties,
    ParseModeLayer,
    ParseModeData,
    ParseModeObjectGroup,
    ParseModeObject,
    ParseModeObjectProperties
};

@interface SKATMXParser ()<NSXMLParserDelegate>

@property (strong, nonatomic) NSMutableDictionary *mapDictionary;
@property (strong, nonatomic) NSMutableDictionary *currentTileset;
@property (strong, nonatomic) NSMutableDictionary *currentProperties;
@property (strong, nonatomic) NSMutableDictionary *currentLayer;
@property (strong, nonatomic) NSMutableDictionary *currentCollectionProperties;

@property (strong, nonatomic) NSDictionary *currentDataAttributes;

@property (strong, nonatomic) NSString *currentTileID;

@property (nonatomic) ParseMode parseMode;

@end

@implementation SKATMXParser

#pragma mark - Init
- (instancetype)init
{
    if(!(self = [super init]))
        return nil;

    _parseMode = ParseModeStandard;

    _mapDictionary = [[NSMutableDictionary alloc] init];
    _mapDictionary[kTilesets] = [[NSMutableArray alloc] init];
    _mapDictionary[kLayers] = [[NSMutableArray alloc] init];
    return self;
}

#pragma mark - Public Getter
- (NSDictionary *)dictionaryWithData:(NSData *)data
{
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
    parser.delegate = self;
    parser.shouldResolveExternalEntities = NO;

    if([parser parse])
    {
        return [NSDictionary dictionaryWithDictionary:self.mapDictionary];
    }

    NSLog(@"error: invalid TMX");

    return nil;
}

#pragma mark - Map Dictionary Modifications
- (void)addCurrentTileset
{
    if(self.currentTileset)
    {
        [self.mapDictionary[kTilesets] addObject:self.currentTileset];
    }
}

- (void)addCurrentTileProperties
{
    if(self.currentProperties && self.currentTileset)
    {
        self.currentTileset[kTileProperties] = self.currentProperties;
    }
}

- (void)addCurrentLayer
{
    if(self.currentLayer)
    {
        [self.mapDictionary[kLayers] addObject:self.currentLayer];
    }
}

#pragma mark - Data Tag Parsing
- (void)parseData:(NSString *)dataString
{
    dataString =
        [dataString stringByTrimmingCharactersInSet:
                        [NSCharacterSet whitespaceAndNewlineCharacterSet]];

    if(self.currentDataAttributes &&
        [self.currentDataAttributes[kEncoding] isEqualToString:kBase64] &&
        [self.currentDataAttributes[kCompression] isEqualToString:kZlib])
    {
        NSData *data =
            [[NSData alloc] initWithBase64EncodedString:dataString
                                                options:0];
        data = [LFCGzipUtility ungzipData:data];

        NSInteger mapWidth = [self.mapDictionary[kWidth] integerValue];
        NSInteger mapHeight = [self.mapDictionary[kHeight] integerValue];

        // Verify data is the correct length
        if(data.length == mapWidth * mapHeight * 4)
        {
            uint8_t *bytes = (uint8_t *)[data bytes];
            NSInteger tileIndex = 0;
            NSMutableArray *tileIDArray = [[NSMutableArray alloc] init];

            for(NSInteger y = 0; y < mapHeight; y++)
            {
                for(NSInteger x = 0; x < mapWidth; x++)
                {
                    NSInteger globalTileID = bytes[tileIndex] | (bytes[tileIndex + 1] << 8) | (bytes[tileIndex + 2] << 16) | (bytes[tileIndex + 3] << 24);
                    [tileIDArray addObject:@(globalTileID)];
                    tileIndex += 4;
                }
            }

            self.currentLayer[kData] = [NSArray arrayWithArray:tileIDArray];
        }
    }
}

#pragma mark - NSXMLParserDelegate
- (void)parser:(NSXMLParser *)parser
    didStartElement:(NSString *)elementName
       namespaceURI:(NSString *)namespaceURI
      qualifiedName:(NSString *)qName
         attributes:(NSDictionary *)attributeDict
{
    if([elementName isEqualToString:kMap])
    {
        [self.mapDictionary addEntriesFromDictionary:attributeDict];
        [self.mapDictionary cleanseMap];
    }

    if([elementName isEqualToString:kTileset])
    {
        self.parseMode = ParseModeTileset;
        self.currentTileset =
            [NSMutableDictionary dictionaryWithDictionary:attributeDict];
        self.currentCollectionProperties = [[NSMutableDictionary alloc]init];
        [self.currentTileset cleanseTileset];
    }
    else if([elementName isEqualToString:kImage])
    {
        if(self.parseMode == ParseModeTileset)
        {
            self.currentTileset[kImage] = attributeDict[kSource];
            self.currentTileset[kImageWidth] = attributeDict[kWidth];
            self.currentTileset[kImageHeight] = attributeDict[kHeight];
        }
        else if (self.currentTileID)
        {
            self.currentCollectionProperties[self.currentTileID] = attributeDict;
            self.currentTileset[kTiles] = self.currentCollectionProperties;
            self.currentTileID = nil;
        }
    }
    else if([elementName isEqualToString:kTile])
    {
        self.parseMode = ParseModeTile;
        self.currentTileID = attributeDict[kId];
    }
    else if([elementName isEqualToString:kProperties])
    {

        if(self.parseMode == ParseModeTile)
        {
            self.parseMode = ParseModeTileProperties;

            if(!self.currentProperties)
            {
                self.currentProperties = [[NSMutableDictionary alloc] init];
            }
        }
        else if(self.parseMode == ParseModeObject)
        {
            self.parseMode = ParseModeObjectProperties;

            if(!self.currentProperties)
            {
                self.currentProperties = [[NSMutableDictionary alloc] init];
            }
        }
    }
    else if([elementName isEqualToString:kProperty])
    {
        if(self.parseMode == ParseModeTileProperties)
        {
            self.currentProperties[self.currentTileID] =
                @{ attributeDict[kName] : attributeDict[kValue] };
        }
        else if(self.parseMode == ParseModeObjectProperties)
        {
            self.currentProperties[attributeDict[kName]] = attributeDict[kValue];
        }
    }
    else if([elementName isEqualToString:kLayer])
    {
        if(self.parseMode == ParseModeStandard)
        {
            self.parseMode = ParseModeLayer;
            self.currentLayer =
                [NSMutableDictionary dictionaryWithDictionary:attributeDict];
            [self.currentLayer cleanseLayer];
        }
    }
    else if([elementName isEqualToString:kData])
    {
        if(self.parseMode == ParseModeLayer)
        {
            self.parseMode = ParseModeData;
            self.currentDataAttributes = attributeDict;
        }
    }
    else if([elementName isEqualToString:kObjectGroup])
    {
        if(self.parseMode == ParseModeStandard)
        {
            self.parseMode = ParseModeObjectGroup;

            NSMutableDictionary *objectGroupDict =
                [NSMutableDictionary dictionaryWithDictionary:attributeDict];
            [objectGroupDict cleanseObjectGroup];

            self.currentLayer = objectGroupDict;
        }
    }
    else if([elementName isEqualToString:kObject])
    {
        if(self.parseMode == ParseModeObjectGroup)
        {
            self.parseMode = ParseModeObject;

            if(!self.currentLayer[kObjects])
            {
                self.currentLayer[kObjects] = [[NSMutableArray alloc] init];
            }

            NSMutableDictionary *objectDict =
                [NSMutableDictionary dictionaryWithDictionary:attributeDict];
            [objectDict cleanseObject];

            [self.currentLayer[kObjects] addObject:objectDict];
        }
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if(self.parseMode == ParseModeData)
    {
        [self parseData:string];
    }
}

- (void)parser:(NSXMLParser *)parser
 didEndElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qName
{
    if([elementName isEqualToString:kTileset])
    {
        [self addCurrentTileProperties];
        [self addCurrentTileset];
        self.currentTileset = nil;
        self.currentProperties = nil;
        self.parseMode = ParseModeStandard;
    }
    else if([elementName isEqualToString:kTile])
    {
        self.parseMode = ParseModeTileset;
        self.currentTileID = nil;
    }
    else if([elementName isEqualToString:kProperties])
    {
        if(self.parseMode == ParseModeTileProperties)
        {
            self.parseMode = ParseModeTile;
        }
        else if(self.parseMode == ParseModeObjectProperties)
        {
            self.parseMode = ParseModeObject;

            if(self.currentProperties)
            {
                [self.currentLayer[kObjects] lastObject][kProperties] = self.currentProperties;
                self.currentProperties = nil;
            }
        }
    }
    else if([elementName isEqualToString:kObject])
    {
        self.parseMode = ParseModeObjectGroup;
    }
    else if([elementName isEqualToString:kLayer] ||
            [elementName isEqualToString:kObjectGroup])
    {
        [self addCurrentLayer];
        self.currentLayer = nil;
        self.parseMode = ParseModeStandard;
    }
    else if([elementName isEqualToString:kData])
    {
        self.parseMode = ParseModeLayer;
        self.currentDataAttributes = nil;
    }
}

@end