public boolean isProcessing() {
        return this.isWorking;
    }

package tsuteto.tofu.tileentity;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.*;
import tsuteto.tofu.api.TfMaterialRegistry;
import tsuteto.tofu.api.recipe.TfReformerRecipe;
import tsuteto.tofu.api.recipe.TfReformerRecipeRegistry;
import tsuteto.tofu.api.tileentity.ITfConsumer;
import tsuteto.tofu.api.tileentity.TileEntityTfMachineSidedInventoryBase;
import tsuteto.tofu.block.BlockTfReformer;
import tsuteto.tofu.init.TcFluids;
import tsuteto.tofu.recipe.Ingredient;

public class TileEntityTfReformer extends TileEntityTfMachineSidedInventoryBase implements IFluidHandler, ITfConsumer {

    public enum Model {

        simple(0, 2, new int[0]), mix(1, 5, new int[] { SLOT_INGREDIENT_ITEM1, SLOT_INGREDIENT_ITEM2, SLOT_INGREDIENT_ITEM3 });

        public final int id;

        public final int stackSize;

        public final int[] ingredientSlots;

        Model(int id, int stackSize, int[] ingredientSlots) {
            this.id = id;
            this.stackSize = stackSize;
            this.ingredientSlots = ingredientSlots;
        }
    }

    public static final int SLOT_INPUT_ITEM = 0;

    public static final int SLOT_OUTPUT_ITEM = 1;

    public static final int SLOT_INGREDIENT_ITEM1 = 2;

    public static final int SLOT_INGREDIENT_ITEM2 = 3;

    public static final int SLOT_INGREDIENT_ITEM3 = 4;

    public static final double TF_CAPACITY = 20;

    public static final double COST_TF_PER_TICK = 1;

    private static final int[] slotsTop = new int[] { 0 };

    private static final int[] slotsSides1 = new int[] { 0, 1 };

    private static final int[] slotsSides2 = new int[] { 1, 2, 3, 4 };

    private static final int[] slotsBottom = new int[] { 1 };

    public Model model;

    public double tfCapacity = TF_CAPACITY;

    public double tfAmount = 0;

    public TfReformerRecipe currentRecipe;

    public double tfOutput = 0;

    public double wholeTfOutput = 0;

    public int externalProcessTime = 0;

    public boolean isExternalProcessed = false;

    public FluidTank fluidTank = new FluidTank(0);

    private double tfConsumed = 0.0D;

    private TfReformerRecipe lastRecipe = null;

    private boolean shouldUpdateRecipe = false;

    public boolean isWorking;

    private boolean prevWorking;

    public TileEntityTfReformer() {
        this.model = Model.simple;
        this.fluidTank.setFluid(new FluidStack(TcFluids.SOYMILK, 0));
        this.fluidTank.setCapacity(TfMaterialRegistry.calcFluidAmountFrom(this.tfCapacity, TcFluids.SOYMILK));
    }

    @Override
    protected String getInventoryNameTranslate() {
        return "container.tofucraft.TfReformer." + model.name();
    }

    public static Model getModelById(int id) {
        for (Model model : Model.values()) {
            if (model.id == id)
                return model;
        }
        return null;
    }

    @Override
    public void onTileEntityCreated(World world, int x, int y, int z, EntityLivingBase entityCreatedBy, ItemStack itemstack) {
        this.model = TileEntityTfReformer.getModelById(itemstack.getItemDamage());
        this.itemStacks = new ItemStack[model.stackSize];
    }

    /**
     * Reads a tile entity from NBT.
     */
    @Override
    public void readFromNBT(NBTTagCompound nbtTagCompound) {
        int rev = nbtTagCompound.getByte("Rev");
        if (rev == 1) {
            this.model = Model.simple;
            this.itemStacks = new ItemStack[model.stackSize];
            this.tfOutput = nbtTagCompound.getShort("ProcO");
            this.tfAmount = nbtTagCompound.getFloat("TfAmount");
        } else {
            this.model = getModelById(nbtTagCompound.getByte("Model"));
            if (this.model == null)
                this.invalidate();
            this.itemStacks = new ItemStack[model.stackSize];
            this.tfOutput = nbtTagCompound.getDouble("ProcO");
            this.tfAmount = nbtTagCompound.getDouble("TfAmount");
        }
        super.readFromNBT(nbtTagCompound);
        this.fluidTank.setCapacity(TfMaterialRegistry.calcFluidAmountFrom(this.tfCapacity, TcFluids.SOYMILK));
        this.updateFluidTank();
        this.updateCurrentRecipe();
    }

    /**
     * Writes a tile entity to NBT.
     */
    @Override
    public void writeToNBT(NBTTagCompound nbtTagCompound) {
        super.writeToNBT(nbtTagCompound);
        nbtTagCompound.setByte("Model", (byte) this.model.id);
        nbtTagCompound.setDouble("ProcO", this.tfOutput);
        nbtTagCompound.setDouble("TfAmount", this.tfAmount);
    }

    @Override
    protected int getNBTRevision() {
        return 2;
    }

    @SideOnly(Side.CLIENT)
    public double getProgressScaledOutput() {
        if (wholeTfOutput > 0) {
            return this.tfOutput / this.wholeTfOutput;
        } else {
            return 0;
        }
    }

    /**
     * Returns true if the machine is currently processing
     */

    @Override
    public void updateEntity() {
        boolean isInventoryChanged = false;
        this.isWorking = false;
        if (!this.worldObj.isRemote) {
            tfConsumed = 0;
            if (shouldUpdateRecipe) {
                this.updateCurrentRecipe();
                shouldUpdateRecipe = false;
            }
            if (this.tfOutput == 0 && this.canProcessOutput()) {
                this.updateFluidTank();
            }
            if (this.wholeTfOutput > 0 && this.canProcessOutput()) {
                // Processing
                this.tfConsumed = Math.min(this.tfAmount, COST_TF_PER_TICK);
                this.tfOutput += tfConsumed;
                this.tfAmount -= tfConsumed;
                this.isWorking = true;
                if (this.tfOutput >= wholeTfOutput) {
                    // Finish
                    this.tfOutput = 0;
                    this.onOutputCompleted();
                    isInventoryChanged = true;
                }
            } else if (this.lastRecipe != this.currentRecipe) {
                // Stop processing
                this.tfOutput = 0;
                this.wholeTfOutput = 0;
            }
            if (this.isExternalProcessed) {
                this.externalProcessTime = 20;
                this.isExternalProcessed = false;
            } else if (this.externalProcessTime > 0) {
                --this.externalProcessTime;
            }
            if (this.isWorking != this.prevWorking) {
                isInventoryChanged = true;
                BlockTfReformer.updateMachineState(this.isProcessing(), this.worldObj, this.xCoord, this.yCoord, this.zCoord);
            }
        }
        if (isInventoryChanged) {
            this.markDirty();
        }
        this.lastRecipe = this.currentRecipe;
        this.prevWorking = this.isWorking;
    }

    /**
     * Checks if the machine accepts the item to output soymilk
     */
    private boolean canProcessOutput() {
        if (this.itemStacks[SLOT_INPUT_ITEM] == null)
            return false;
        if (this.tfAmount <= 0)
            return false;
        if (this.currentRecipe == null)
            return false;
        Ingredient containerItem = this.currentRecipe.containerItem;
        if (!containerItem.matches(this.itemStacks[SLOT_INPUT_ITEM]))
            return false;
        ItemStack var1 = this.currentRecipe.result;
        // Check if the filled item can be stacked to the output slot
        if (this.itemStacks[SLOT_OUTPUT_ITEM] == null)
            return true;
        if (!this.itemStacks[SLOT_OUTPUT_ITEM].isItemEqual(var1))
            return false;
        // Check if the stack will overflow
        int result = itemStacks[SLOT_OUTPUT_ITEM].stackSize + var1.stackSize;
        return result <= getInventoryStackLimit() && result <= var1.getMaxStackSize();
    }

    /**
     * When the output process completed. Take one from the output container stack and fill soymilk converted from TF
     */
    public void onOutputCompleted() {
        ItemStack var1 = this.currentRecipe.result;
        if (this.itemStacks[SLOT_OUTPUT_ITEM] == null) {
            this.itemStacks[SLOT_OUTPUT_ITEM] = var1.copy();
        } else if (this.itemStacks[SLOT_OUTPUT_ITEM].isItemEqual(var1)) {
            itemStacks[SLOT_OUTPUT_ITEM].stackSize += var1.stackSize;
        }
        if (--this.itemStacks[SLOT_INPUT_ITEM].stackSize == 0) {
            this.itemStacks[SLOT_INPUT_ITEM] = null;
        }
        // Ingredient slots
        for (int id : model.ingredientSlots) {
            ItemStack input = this.itemStacks[id];
            if (input != null) {
                if (!this.currentRecipe.isCatalystItem(input)) {
                    ItemStack container = input.getItem().getContainerItem(input);
                    if (container != null) {
                        this.itemStacks[id] = container;
                    } else {
                        if (--this.itemStacks[id].stackSize == 0) {
                            this.itemStacks[id] = null;
                        }
                    }
                }
            }
        }
    }

    /**
     * Updates the fluid tank to synchronize with the tf amount of the machine
     */
    private void updateFluidTank() {
        if (fluidTank.getFluid() == null) {
            this.fluidTank.setFluid(new FluidStack(TcFluids.SOYMILK, 0));
        }
        this.fluidTank.getFluid().amount = TfMaterialRegistry.calcFluidAmountFrom(this.tfAmount, TcFluids.SOYMILK);
    }

    public void updateCurrentRecipe() {
        TfReformerRecipe recipe = null;
        if (model == Model.mix) {
            recipe = TfReformerRecipeRegistry.getRecipe(this.itemStacks[SLOT_INPUT_ITEM], new ItemStack[] { this.itemStacks[SLOT_INGREDIENT_ITEM1], this.itemStacks[SLOT_INGREDIENT_ITEM2], this.itemStacks[SLOT_INGREDIENT_ITEM3] });
        } else if (model == Model.simple) {
            recipe = TfReformerRecipeRegistry.getRecipe(this.itemStacks[SLOT_INPUT_ITEM], new ItemStack[0]);
        }
        if (recipe != null) {
            this.wholeTfOutput = recipe.tfAmountNeeded;
        }
        this.currentRecipe = recipe;
    }

    @Override
    public void markDirty() {
        super.markDirty();
        this.shouldUpdateRecipe = true;
    }

    /**
     * Fill a container item by Forge fluid system (IFluidHandler)
     * Applicable to some industrial mods
     */
    @Override
    public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
        return 0;
    }

    /**
     * Drain soymilk from the machine by Forge fluid system (IFluidHandler)
     * Applicable to industrial mods or some
     */
    @Override
    public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
        this.updateFluidTank();
        if ((resource == null) || (!resource.isFluidEqual(fluidTank.getFluid()))) {
            return null;
        }
        if (!canDrain(from, resource.getFluid()))
            return null;
        FluidStack fluid = fluidTank.drain(resource.amount, doDrain);
        if (fluid != null && doDrain && fluid.amount > 0) {
            this.tfAmount -= TfMaterialRegistry.calcTfAmountFrom(fluid);
            this.updateFluidTank();
            this.isExternalProcessed = true;
        }
        return fluid;
    }

    /**
     * Drain soymilk from the machine by Forge fluid system (IFluidHandler) for pipes
     * Applicable to industrial mods or some
     */
    @Override
    public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
        this.updateFluidTank();
        FluidStack fluid = fluidTank.drain(maxDrain, doDrain);
        if (fluid != null && doDrain && fluid.amount > 0) {
            this.tfAmount -= TfMaterialRegistry.calcTfAmountFrom(fluid);
            this.updateFluidTank();
            this.isExternalProcessed = true;
        }
        return fluid;
    }

    @Override
    public boolean canFill(ForgeDirection from, Fluid fluid) {
        // This machine cannot be filled
        return false;
    }

    @Override
    public boolean canDrain(ForgeDirection from, Fluid fluid) {
        if (this.tfAmount <= 0)
            return false;
        return fluidTank.getFluid().getFluid().getID() == fluid.getID();
    }

    @Override
    public FluidTankInfo[] getTankInfo(ForgeDirection from) {
        this.updateFluidTank();
        return new FluidTankInfo[] { this.fluidTank.getInfo() };
    }

    @Override
    public double getCurrentTfConsumed() {
        return tfConsumed;
    }

    @Override
    public void chargeTf(double amount) {
        this.tfAmount += amount;
    }

    @Override
    public double getMaxTfCapacity() {
        return Math.min(tfCapacity - this.tfAmount, 5);
    }

    @Override
    public int[] getAccessibleSlotsFromSide(int var1) {
        return var1 == 0 ? slotsBottom : (var1 == 1 ? slotsTop : model == Model.simple ? slotsSides1 : slotsSides2);
    }

    @Override
    public boolean isItemValidForSlot(int par1, ItemStack par2ItemStack) {
        return par1 != 1;
    }

    public boolean canExtractItem(int slot, ItemStack item, int side) {
        return slot == 1;
    }
}


package com.hartwig.hmftools.statcalcs.css;

import static java.lang.Math.max;
import static java.lang.Math.round;
import static com.hartwig.hmftools.common.stats.CosineSimilarity.calcCosineSim;
import static com.hartwig.hmftools.common.sigs.NoiseCalcs.calcPoissonRangeGivenProb;
import static com.hartwig.hmftools.common.utils.MatrixUtils.loadMatrixDataFile;
import static com.hartwig.hmftools.common.utils.VectorUtils.copyVector;
import static com.hartwig.hmftools.common.utils.VectorUtils.sumVector;
import static com.hartwig.hmftools.common.utils.FileWriterUtils.closeBufferedWriter;
import static com.hartwig.hmftools.common.utils.FileWriterUtils.createBufferedWriter;
import static com.hartwig.hmftools.common.utils.FileWriterUtils.createFieldsIndexMap;
import static com.hartwig.hmftools.common.utils.FileWriterUtils.parseOutputDir;
import static com.hartwig.hmftools.statcalcs.common.StatsCommon.LOG_DEBUG;
import static com.hartwig.hmftools.statcalcs.common.StatsCommon.OUTPUT_FILE_ID;
import static com.hartwig.hmftools.statcalcs.common.StatsCommon.STAT_LOGGER;
import static com.hartwig.hmftools.statcalcs.common.StatsCommon.formOutputFilename;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hartwig.hmftools.common.utils.Matrix;
import com.hartwig.hmftools.statcalcs.common.StatsCommon;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
import org.jetbrains.annotations.NotNull;

public class CosineSimAnalyser {

    // config
    private final String mOutputDir;

    private final String mOutputId;

    private final Matrix mSampleCounts;

    private final List<String> mSampleIds;

    private final Map<String, String> mSampleCancerTypes;

    private final Map<String, Integer> mSampleCountsIndex;

    private final double mCssThreshold;

    private final boolean mUseElevated;

    private final Map<Integer, Integer> mRangeMap;

    private final Matrix mReferenceSampleCounts;

    private final List<String> mRefNames;

    private BufferedWriter mWriter;

    private static final String CSS_THRESHOLD = "css_threshold";

    private static final String USE_ELEVATED = "use_elevated";

    private static final String SAMPLE_COUNTS_FILE = "sample_counts_file";

    private static final String REF_COUNTS_FILE = "ref_counts_file";

    private static final String SAMPLE_REF_FILE = "sample_ref_file";

    private static final int MIN_ELEVATED_BUCKETS = 10;

    private static final double ELEVATED_BUCKET_PROBABILITY = 0.1;

    private static final double DEFAULT_CSS_THRESHOLD = 0.8;

    public CosineSimAnalyser(final CommandLine cmd) {
        mOutputDir = parseOutputDir(cmd);
        mOutputId = cmd.getOptionValue(OUTPUT_FILE_ID);
        mSampleCountsIndex = Maps.newHashMap();
        mCssThreshold = cmd.hasOption(CSS_THRESHOLD) ? Double.parseDouble(cmd.getOptionValue(CSS_THRESHOLD)) : DEFAULT_CSS_THRESHOLD;
        mUseElevated = cmd.hasOption(USE_ELEVATED);
        mRangeMap = Maps.newHashMap();
        mSampleCounts = loadMatrixDataFile(cmd.getOptionValue(SAMPLE_COUNTS_FILE), mSampleCountsIndex, null);
        mSampleCounts.cacheTranspose();
        mSampleCancerTypes = Maps.newHashMap();
        mSampleIds = Lists.newArrayList();
        if (cmd.hasOption(SAMPLE_REF_FILE)) {
            loadSampleRefDataFile(cmd.getOptionValue(SAMPLE_REF_FILE));
        } else {
            mSampleIds.addAll(mSampleCountsIndex.keySet());
        }
        mRefNames = Lists.newArrayList();
        if (cmd.hasOption(REF_COUNTS_FILE)) {
            STAT_LOGGER.info("loading reference data from file({})", cmd.getOptionValue(REF_COUNTS_FILE));
            mReferenceSampleCounts = loadMatrixDataFile(cmd.getOptionValue(REF_COUNTS_FILE), mRefNames);
            mReferenceSampleCounts.cacheTranspose();
        } else {
            mReferenceSampleCounts = null;
        }
        mWriter = null;
    }

    private void loadSampleRefDataFile(final String filename) {
        try {
            final List<String> fileData = Files.readAllLines(new File(filename).toPath());
            final String header = fileData.get(0);
            fileData.remove(0);
            final Map<String, Integer> fieldsIndexMap = createFieldsIndexMap(header, ",");
            for (final String line : fileData) {
                final String[] items = line.split(",", -1);
                final String sampleId = items[fieldsIndexMap.get("SampleId")];
                final String cancerType = items[fieldsIndexMap.get("CancerType")];
                mSampleIds.add(sampleId);
                mSampleCancerTypes.put(sampleId, cancerType);
            }
            STAT_LOGGER.info("loaded {} samples from file({})", filename);
        } catch (IOException e) {
            STAT_LOGGER.error("failed to read sample data file({}): {}", filename, e.toString());
        }
    }

    public void run() {
        if (mReferenceSampleCounts != null && mReferenceSampleCounts.Rows != mSampleCounts.Rows) {
            STAT_LOGGER.error("sampleCounts buckets({}) refCounts buckets({}) mismatch", mReferenceSampleCounts.Rows, mSampleCounts.Rows);
            return;
        }
        STAT_LOGGER.info("running CSS comparison for {} samples", mSampleIds.size());
        for (int i = 0; i < mSampleIds.size(); ++i) {
            final String sampleId = mSampleIds.get(i);
            if (mSampleCountsIndex.get(sampleId) == null)
                continue;
            final double[] sampleCounts = mSampleCounts.getCol(mSampleCountsIndex.get(sampleId));
            if (mReferenceSampleCounts == null) {
                for (int j = i + 1; j < mSampleIds.size(); ++j) {
                    final String sampleId2 = mSampleIds.get(j);
                    final double[] sampleCounts2 = mSampleCounts.getCol(mSampleCountsIndex.get(sampleId2));
                    double css = mUseElevated ? calcElevatedCountsCss(sampleCounts, sampleCounts2) : calcCosineSim(sampleCounts, sampleCounts2);
                    if (css >= mCssThreshold) {
                        writeCssResults(sampleId, sampleId2, css);
                    }
                }
            } else {
                double sampleTotal = sumVector(sampleCounts);
                final String sampleCancerType = mSampleCancerTypes.get(sampleId);
                for (int j = 0; j < mRefNames.size(); ++j) {
                    final String refName = mRefNames.get(j);
                    final double[] refCounts = mReferenceSampleCounts.getCol(j);
                    double css;
                    if (sampleCancerType != null && refName.equals(sampleCancerType)) {
                        double[] adjustedRefCounts = new double[refCounts.length];
                        copyVector(refCounts, adjustedRefCounts);
                        for (int b = 0; b < refCounts.length; ++b) {
                            adjustedRefCounts[b] = max(adjustedRefCounts[b] - (sampleCounts[b]), 0);
                        }
                        css = calcCosineSim(sampleCounts, adjustedRefCounts);
                    } else {
                        css = calcCosineSim(sampleCounts, refCounts);
                    }
                    if (css >= mCssThreshold) {
                        writeCssResults(sampleId, refName, css);
                    }
                }
            }
            if (i > 0 && (i % 100) == 0) {
                STAT_LOGGER.info("processed {} samples", i);
            }
        }
        STAT_LOGGER.info("CSS comparison complete");
        closeBufferedWriter(mWriter);
    }

    private double calcElevatedCountsCss(final double[] sampleCounts1, final double[] sampleCounts2) {
        double[] elevCounts1 = extractElevatedCounts(sampleCounts1);
        double[] elevCounts2 = extractElevatedCounts(sampleCounts2);
        int elevatedBuckets

        for (int b = 0; b < sampleCounts1.length; ++b) {
            if (elevCounts1[b] > 0 || elevCounts2[b] > 0) {
                elevCounts1[b] = sampleCounts1[b];
                elevCounts2[b] = sampleCounts2[b];
                ++elevatedBuckets;
            }
        }
        if (elevatedBuckets < MIN_ELEVATED_BUCKETS)
            return 0;
        return calcCosineSim(elevCounts1, elevCounts2);
    }

    private double[] extractElevatedCounts(final double[] counts) {
        double total = sumVector(counts);
        int bucketCount = counts.length;
        int expectedValue = (int) round(total / bucketCount);
        Integer maxPermittedValue = mRangeMap.get(expectedValue);
        if (maxPermittedValue == null) {
            int permittedRange = calcPoissonRangeGivenProb(expectedValue, ELEVATED_BUCKET_PROBABILITY, 0, false);
            maxPermittedValue = expectedValue + permittedRange;
            mRangeMap.put(expectedValue, maxPermittedValue);
        }
        double[] elevatedCounts = new double[bucketCount];
        for (int b = 0; b < bucketCount; ++b) {
            if (counts[b] > maxPermittedValue)
                elevatedCounts[b] = counts[b];
        }
        return elevatedCounts;
    }

    private void writeCssResults(final String sampleId1, final String sampleId2, double css) {
        try {
            if (mWriter == null) {
                mWriter = createBufferedWriter(formOutputFilename(mOutputDir, mOutputId, "sig_css"), false);
                if (mRefNames.isEmpty())
                    mWriter.write("SampleId1,SampleId2,CSS");
                else
                    mWriter.write("SampleId,RefName,CSS");
                mWriter.newLine();
            }
            mWriter.write(String.format("%s,%s,%.6f", sampleId1, sampleId2, css));
            mWriter.newLine();
        } catch (IOException e) {
            STAT_LOGGER.error("failed to write CSS results: {}", e.toString());
        }
    }

    public static void main(@NotNull final String[] args) throws ParseException {
        Options options = new Options();
        StatsCommon.addCmdLineArgs(options);
        options.addOption(CSS_THRESHOLD, true, "Optional - min CSS to log (default = 0.8)");
        options.addOption(USE_ELEVATED, false, "Optional - only include elevated counts in comparison");
        options.addOption(REF_COUNTS_FILE, true, "Optional - min CSS to log (default = 0.8)");
        options.addOption(SAMPLE_REF_FILE, true, "Optional - sample to ref-type mapping file");
        final CommandLineParser parser = new DefaultParser();
        final CommandLine cmd = parser.parse(options, args);
        if (cmd.hasOption(LOG_DEBUG))
            Configurator.setRootLevel(Level.DEBUG);
        CosineSimAnalyser cosineSims = new CosineSimAnalyser(cmd);
        cosineSims.run();
    }
}


for (int b = 0; b < bucketCount; ++b) {
            if (counts[b] > maxPermittedValue)
                elevatedCounts[b] = counts[b];
        }

package com.hartwig.hmftools.statcalcs.css;

import static java.lang.Math.max;
import static java.lang.Math.round;
import static com.hartwig.hmftools.common.stats.CosineSimilarity.calcCosineSim;
import static com.hartwig.hmftools.common.sigs.NoiseCalcs.calcPoissonRangeGivenProb;
import static com.hartwig.hmftools.common.utils.MatrixUtils.loadMatrixDataFile;
import static com.hartwig.hmftools.common.utils.VectorUtils.copyVector;
import static com.hartwig.hmftools.common.utils.VectorUtils.sumVector;
import static com.hartwig.hmftools.common.utils.FileWriterUtils.closeBufferedWriter;
import static com.hartwig.hmftools.common.utils.FileWriterUtils.createBufferedWriter;
import static com.hartwig.hmftools.common.utils.FileWriterUtils.createFieldsIndexMap;
import static com.hartwig.hmftools.common.utils.FileWriterUtils.parseOutputDir;
import static com.hartwig.hmftools.statcalcs.common.StatsCommon.LOG_DEBUG;
import static com.hartwig.hmftools.statcalcs.common.StatsCommon.OUTPUT_FILE_ID;
import static com.hartwig.hmftools.statcalcs.common.StatsCommon.STAT_LOGGER;
import static com.hartwig.hmftools.statcalcs.common.StatsCommon.formOutputFilename;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hartwig.hmftools.common.utils.Matrix;
import com.hartwig.hmftools.statcalcs.common.StatsCommon;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
import org.jetbrains.annotations.NotNull;

public class CosineSimAnalyser {

    // config
    private final String mOutputDir;

    private final String mOutputId;

    private final Matrix mSampleCounts;

    private final List<String> mSampleIds;

    private final Map<String, String> mSampleCancerTypes;

    private final Map<String, Integer> mSampleCountsIndex;

    private final double mCssThreshold;

    private final boolean mUseElevated;

    private final Map<Integer, Integer> mRangeMap;

    private final Matrix mReferenceSampleCounts;

    private final List<String> mRefNames;

    private BufferedWriter mWriter;

    private static final String CSS_THRESHOLD = "css_threshold";

    private static final String USE_ELEVATED = "use_elevated";

    private static final String SAMPLE_COUNTS_FILE = "sample_counts_file";

    private static final String REF_COUNTS_FILE = "ref_counts_file";

    private static final String SAMPLE_REF_FILE = "sample_ref_file";

    private static final int MIN_ELEVATED_BUCKETS = 10;

    private static final double ELEVATED_BUCKET_PROBABILITY = 0.1;

    private static final double DEFAULT_CSS_THRESHOLD = 0.8;

    public CosineSimAnalyser(final CommandLine cmd) {
        mOutputDir = parseOutputDir(cmd);
        mOutputId = cmd.getOptionValue(OUTPUT_FILE_ID);
        mSampleCountsIndex = Maps.newHashMap();
        mCssThreshold = cmd.hasOption(CSS_THRESHOLD) ? Double.parseDouble(cmd.getOptionValue(CSS_THRESHOLD)) : DEFAULT_CSS_THRESHOLD;
        mUseElevated = cmd.hasOption(USE_ELEVATED);
        mRangeMap = Maps.newHashMap();
        mSampleCounts = loadMatrixDataFile(cmd.getOptionValue(SAMPLE_COUNTS_FILE), mSampleCountsIndex, null);
        mSampleCounts.cacheTranspose();
        mSampleCancerTypes = Maps.newHashMap();
        mSampleIds = Lists.newArrayList();
        if (cmd.hasOption(SAMPLE_REF_FILE)) {
            loadSampleRefDataFile(cmd.getOptionValue(SAMPLE_REF_FILE));
        } else {
            mSampleIds.addAll(mSampleCountsIndex.keySet());
        }
        mRefNames = Lists.newArrayList();
        if (cmd.hasOption(REF_COUNTS_FILE)) {
            STAT_LOGGER.info("loading reference data from file({})", cmd.getOptionValue(REF_COUNTS_FILE));
            mReferenceSampleCounts = loadMatrixDataFile(cmd.getOptionValue(REF_COUNTS_FILE), mRefNames);
            mReferenceSampleCounts.cacheTranspose();
        } else {
            mReferenceSampleCounts = null;
        }
        mWriter = null;
    }

    private void loadSampleRefDataFile(final String filename) {
        try {
            final List<String> fileData = Files.readAllLines(new File(filename).toPath());
            final String header = fileData.get(0);
            fileData.remove(0);
            final Map<String, Integer> fieldsIndexMap = createFieldsIndexMap(header, ",");
            for (final String line : fileData) {
                final String[] items = line.split(",", -1);
                final String sampleId = items[fieldsIndexMap.get("SampleId")];
                final String cancerType = items[fieldsIndexMap.get("CancerType")];
                mSampleIds.add(sampleId);
                mSampleCancerTypes.put(sampleId, cancerType);
            }
            STAT_LOGGER.info("loaded {} samples from file({})", filename);
        } catch (IOException e) {
            STAT_LOGGER.error("failed to read sample data file({}): {}", filename, e.toString());
        }
    }

    public void run() {
        if (mReferenceSampleCounts != null && mReferenceSampleCounts.Rows != mSampleCounts.Rows) {
            STAT_LOGGER.error("sampleCounts buckets({}) refCounts buckets({}) mismatch", mReferenceSampleCounts.Rows, mSampleCounts.Rows);
            return;
        }
        STAT_LOGGER.info("running CSS comparison for {} samples", mSampleIds.size());
        for (int i = 0; i < mSampleIds.size(); ++i) {
            final String sampleId = mSampleIds.get(i);
            if (mSampleCountsIndex.get(sampleId) == null)
                continue;
            final double[] sampleCounts = mSampleCounts.getCol(mSampleCountsIndex.get(sampleId));
            if (mReferenceSampleCounts == null) {
                for (int j = i + 1; j < mSampleIds.size(); ++j) {
                    final String sampleId2 = mSampleIds.get(j);
                    final double[] sampleCounts2 = mSampleCounts.getCol(mSampleCountsIndex.get(sampleId2));
                    double css = mUseElevated ? calcElevatedCountsCss(sampleCounts, sampleCounts2) : calcCosineSim(sampleCounts, sampleCounts2);
                    if (css >= mCssThreshold) {
                        writeCssResults(sampleId, sampleId2, css);
                    }
                }
            } else {
                double sampleTotal = sumVector(sampleCounts);
                final String sampleCancerType = mSampleCancerTypes.get(sampleId);
                for (int j = 0; j < mRefNames.size(); ++j) {
                    final String refName = mRefNames.get(j);
                    final double[] refCounts = mReferenceSampleCounts.getCol(j);
                    double css;
                    if (sampleCancerType != null && refName.equals(sampleCancerType)) {
                        double[] adjustedRefCounts = new double[refCounts.length];
                        copyVector(refCounts, adjustedRefCounts);
                        for (int b = 0; b < refCounts.length; ++b) {
                            adjustedRefCounts[b] = max(adjustedRefCounts[b] - (sampleCounts[b]), 0);
                        }
                        css = calcCosineSim(sampleCounts, adjustedRefCounts);
                    } else {
                        css = calcCosineSim(sampleCounts, refCounts);
                    }
                    if (css >= mCssThreshold) {
                        writeCssResults(sampleId, refName, css);
                    }
                }
            }
            if (i > 0 && (i % 100) == 0) {
                STAT_LOGGER.info("processed {} samples", i);
            }
        }
        STAT_LOGGER.info("CSS comparison complete");
        closeBufferedWriter(mWriter);
    }

    private double calcElevatedCountsCss(final double[] sampleCounts1, final double[] sampleCounts2) {
        double[] elevCounts1 = extractElevatedCounts(sampleCounts1);
        double[] elevCounts2 = extractElevatedCounts(sampleCounts2);
        int elevatedBuckets = 0;
        for (int b = 0; b < sampleCounts1.length; ++b) {
            if (elevCounts1[b] > 0 || elevCounts2[b] > 0) {
                elevCounts1[b] = sampleCounts1[b];
                elevCounts2[b] = sampleCounts2[b];
                ++elevatedBuckets;
            }
        }
        if (elevatedBuckets < MIN_ELEVATED_BUCKETS)
            return 0;
        return calcCosineSim(elevCounts1, elevCounts2);
    }

    private double[] extractElevatedCounts(final double[] counts) {
        double total = sumVector(counts);
        int bucketCount = counts.length;
        int expectedValue = (int) round(total / bucketCount);
        Integer maxPermittedValue = mRangeMap.get(expectedValue);
        if (maxPermittedValue == null) {
            int permittedRange = calcPoissonRangeGivenProb(expectedValue, ELEVATED_BUCKET_PROBABILITY, 0, false);
            maxPermittedValue = expectedValue + permittedRange;
            mRangeMap.put(expectedValue, maxPermittedValue);
        }
        double[] elevatedCounts = new double[bucketCount];

        return elevatedCounts;
    }

    private void writeCssResults(final String sampleId1, final String sampleId2, double css) {
        try {
            if (mWriter == null) {
                mWriter = createBufferedWriter(formOutputFilename(mOutputDir, mOutputId, "sig_css"), false);
                if (mRefNames.isEmpty())
                    mWriter.write("SampleId1,SampleId2,CSS");
                else
                    mWriter.write("SampleId,RefName,CSS");
                mWriter.newLine();
            }
            mWriter.write(String.format("%s,%s,%.6f", sampleId1, sampleId2, css));
            mWriter.newLine();
        } catch (IOException e) {
            STAT_LOGGER.error("failed to write CSS results: {}", e.toString());
        }
    }

    public static void main(@NotNull final String[] args) throws ParseException {
        Options options = new Options();
        StatsCommon.addCmdLineArgs(options);
        options.addOption(CSS_THRESHOLD, true, "Optional - min CSS to log (default = 0.8)");
        options.addOption(USE_ELEVATED, false, "Optional - only include elevated counts in comparison");
        options.addOption(REF_COUNTS_FILE, true, "Optional - min CSS to log (default = 0.8)");
        options.addOption(SAMPLE_REF_FILE, true, "Optional - sample to ref-type mapping file");
        final CommandLineParser parser = new DefaultParser();
        final CommandLine cmd = parser.parse(options, args);
        if (cmd.hasOption(LOG_DEBUG))
            Configurator.setRootLevel(Level.DEBUG);
        CosineSimAnalyser cosineSims = new CosineSimAnalyser(cmd);
        cosineSims.run();
    }
}


package com.intuit.fuzzymatcher.domain;

/**
 * This holds the result of matching 2 Documents, Elements or Tokens.
 * This also holds the reference of the Match object, used to aggregate score with the ScoringFunction.
 */
public class Score {

    private double result;

    private Match match;

    public Score(double result, Match match) {
        this.result = result;
        this.match = match;
    }

    public double getResult()

    public Match getMatch() {
        return match;
    }

    @Override
    public String toString() {
        return "Score{" + "result=" + result + ", match=" + match + '}';
    }
}


t=" + result + ", match=" + match + '}';

package com.intuit.fuzzymatcher.domain;

/**
 * This holds the result of matching 2 Documents, Elements or Tokens.
 * This also holds the reference of the Match object, used to aggregate score with the ScoringFunction.
 */
public class Score {

    private double result;

    private Match match;

    public Score(double result, Match match) {
        this.result = result;
        this.match = match;
    }

    public double getResult() {
        return result;
    }

    public Match getMatch() {
        return match;
    }

    @Override
    public String toString() {
        return "Score{" + "resul


{
        System.out.println("kiwi jumps");
    }

package tute8.flyer;

/**
 * @author Chuang Wang
 * @institution University of Melbourne
 */
public class Kiwi extends Bird {

    public void jump()


package org.timepedia.exporter.rebind;

import com.google.gwt.core.ext.typeinfo.JField;
import org.timepedia.exporter.client.Export;

public class JExportableField {

    private JExportableClassType enclosingExportType;

    private JField field;

    private String exportName;

    public JExportableField(JExportableClassType enclosingExportType, JField field) {
        this.enclosingExportType = enclosingExportType;
        this.field = field;
        Export ann = field.getAnnotation(Export.class);
        if (ann != null && ann.value().length() > 0) {
            exportName = ann.value();
        } else {
            exportName = field.getName();
        }
    }

    public String getJSExportName()

    public String getJSQualifiedExportName() {
        return enclosingExportType.getJSQualifiedExportName() + "." + getJSExportName();
    }

    public String getJSNIReference() {
        return field.getEnclosingType().getQualifiedSourceName() + "::" + field.getName();
    }
}


package org.springframework.cloud.aws.jdbc.retry;

import org.springframework.cloud.aws.core.support.documentation.RuntimeUse;

/**
 * Enumeration that holds all possible Amazon RDS database instance states. Used by client
 * code to check if the database is available at all, and to verify if a retry is useful.
 *
 * @author Agim Emruli
 * @since 1.0
 */
public enum InstanceStatus {

    /**
     * Database state that is available during creation of the database. This is typically
     * the case if the database is started at the same time like the application is
     * bootstrapped. In this case a retry will succeed.
     */
    @RuntimeUse
    CREATING(true, false),
    /**
     * Database state that defines that the database is available. The database can be
     * used at all, also a retry for a temporary problem (like a dead-lock) is likely to
     * succeed if called twice.
     */
    @RuntimeUse
    AVAILABLE(true, true),
    /**
     * Database state which defines that the database instance is rebooting. This can
     * happen during a user initiated reboot. A second attempt is likely to succeed
     * especially in the combination with a replicated Multi A/Z instance.
     */
    @RuntimeUse
    REBOOTING(true, false),
    /**
     * Database state which defines that the database instance is modifying. The database
     * is still available and usable, but a modification is in progress. This can be the
     * case if an read-replica instance is added to the database itself.
     */
    @RuntimeUse
    MODIFYING(true, true),
    /**
     * Database state which defines that the database is deleting. Thus it is assumed that
     * is is deleted.
     */
    @RuntimeUse
    DELETING(false, false),
    /**
     * Unknown status, which assumes the database is not available and not retryable.
     */
    @RuntimeUse
    UNKNOWN(false, false);

    /**
     * boolean flag indicating if a second attempt to execute the operation will succeed.
     */
    private final boolean retryable;

    /**
     * boolean flag indicating if the database is available from the management.
     * perspective of Amazon RDS
     */
    private final boolean available;

    InstanceStatus(boolean retryable, boolean available) {
        this.retryable = retryable;
        this.available = available;
    }

    static InstanceStatus fromDatabaseStatus(String databaseStatus) {
        for (InstanceStatus instanceStatus : values()) {
            if (instanceStatus.name().equalsIgnoreCase(databaseStatus)) {
                return instanceStatus;
            }
        }
        return UNKNOWN;
    }

    /**
     * Operation that returns true if a second call will likely succeed. This
     * is typically the case if the database is down for temporary reasons like a reboot
     * after a configuration change, or a multi a/z failover until the DNS record is
     * updated. Clients should wait some time (e.g. up until 3 minutes) before retrying
     * their last database operation.
     * @return true if the operation is retryable, false
     * otherwise
     */
    public boolean isRetryable()

/**
     * Operation that returns true if the database is available from the
     * Amazon RDS perspective. That does not necessarily mean that there is a connection
     * possible to that database itself. Due to wrong/missing rule in the security
     * credentials it might be possible that a database is available but not connectible
     * through the JDBC protocol.
     * @return true if the database is available, false
     * otherwise
     */
    public boolean isAvailable() {
        return this.available;
    }
}


public boolean isRetryable() {
        return this.retryable;
    }

package org.springframework.cloud.aws.jdbc.retry;

import org.springframework.cloud.aws.core.support.documentation.RuntimeUse;

/**
 * Enumeration that holds all possible Amazon RDS database instance states. Used by client
 * code to check if the database is available at all, and to verify if a retry is useful.
 *
 * @author Agim Emruli
 * @since 1.0
 */
public enum InstanceStatus {

    /**
     * Database state that is available during creation of the database. This is typically
     * the case if the database is started at the same time like the application is
     * bootstrapped. In this case a retry will succeed.
     */
    @RuntimeUse
    CREATING(true, false),
    /**
     * Database state that defines that the database is available. The database can be
     * used at all, also a retry for a temporary problem (like a dead-lock) is likely to
     * succeed if called twice.
     */
    @RuntimeUse
    AVAILABLE(true, true),
    /**
     * Database state which defines that the database instance is rebooting. This can
     * happen during a user initiated reboot. A second attempt is likely to succeed
     * especially in the combination with a replicated Multi A/Z instance.
     */
    @RuntimeUse
    REBOOTING(true, false),
    /**
     * Database state which defines that the database instance is modifying. The database
     * is still available and usable, but a modification is in progress. This can be the
     * case if an read-replica instance is added to the database itself.
     */
    @RuntimeUse
    MODIFYING(true, true),
    /**
     * Database state which defines that the database is deleting. Thus it is assumed that
     * is is deleted.
     */
    @RuntimeUse
    DELETING(false, false),
    /**
     * Unknown status, which assumes the database is not available and not retryable.
     */
    @RuntimeUse
    UNKNOWN(false, false);

    /**
     * boolean flag indicating if a second attempt to execute the operation will succeed.
     */
    private final boolean retryable;

    /**
     * boolean flag indicating if the database is available from the management.
     * perspective of Amazon RDS
     */
    private final boolean available;

    InstanceStatus(boolean retryable, boolean available) {
        this.retryable = retryable;
        this.available = available;
    }

    static InstanceStatus fromDatabaseStatus(String databaseStatus) {
        for (InstanceStatus instanceStatus : values()) {
            if (instanceStatus.name().equalsIgnoreCase(databaseStatus)) {
                return instanceStatus;
            }
        }
        return UNKNOWN;
    }

    /**
     * Operation that returns true if a second call will likely succeed. This
     * is typically the case if the database is down for temporary reasons like a reboot
     * after a configuration change, or a multi a/z failover until the DNS record is
     * updated. Clients should wait some time (e.g. up until 3 minutes) before retrying
     * their last database operation.
     * @return true if the operation is retryable, false
     * otherwise
     */


{
        return Type.getType(int.class);
    }

package com.alibaba.bytekit.asm.binding;

import com.alibaba.deps.org.objectweb.asm.Type;
import com.alibaba.deps.org.objectweb.asm.tree.AbstractInsnNode;
import com.alibaba.deps.org.objectweb.asm.tree.InsnList;
import com.alibaba.deps.org.objectweb.asm.tree.LineNumberNode;
import com.alibaba.bytekit.asm.location.Location;
import com.alibaba.bytekit.utils.AsmOpUtils;

/**
 * @author hengyunabc
 */
public class LineBinding extends Binding {

    private boolean exact;

    public LineBinding(boolean exact) {
        this.exact = exact;
    }

    @Override
    public void pushOntoStack(InsnList instructions, BindingContext bindingContext) {
        Location location = bindingContext.getLocation();
        AbstractInsnNode insnNode = location.getInsnNode();
        int line = -1;
        if (exact) {
            if (insnNode instanceof LineNumberNode) {
                line = ((LineNumberNode) insnNode).line;
            } else {
                throw new IllegalArgumentException("LineBinding location is not LineNumberNode, insnNode: " + insnNode);
            }
        } else {
            if (location.isWhenComplete() == false) {
                while (insnNode != null) {
                    if (insnNode instanceof LineNumberNode) {
                        line = ((LineNumberNode) insnNode).line;
                        break;
                    }
                    insnNode = insnNode.getPrevious();
                }
            } else {
                while (insnNode != null) {
                    if (insnNode instanceof LineNumberNode) {
                        line = ((LineNumberNode) insnNode).line;
                        break;
                    }
                    insnNode = insnNode.getNext();
                }
            }
        }
        AsmOpUtils.push(instructions, line);
    }

    @Override
    public Type getType(BindingContext bindingContext)


while (insnNode != null) {
                    if (insnNode instanceof LineNumberNode) {
                        line = ((LineNumberNode) insnNode).line;
                        break;
                    }
                    insnNode = insnNode.getNext();
                }

package com.alibaba.bytekit.asm.binding;

import com.alibaba.deps.org.objectweb.asm.Type;
import com.alibaba.deps.org.objectweb.asm.tree.AbstractInsnNode;
import com.alibaba.deps.org.objectweb.asm.tree.InsnList;
import com.alibaba.deps.org.objectweb.asm.tree.LineNumberNode;
import com.alibaba.bytekit.asm.location.Location;
import com.alibaba.bytekit.utils.AsmOpUtils;

/**
 * @author hengyunabc
 */
public class LineBinding extends Binding {

    private boolean exact;

    public LineBinding(boolean exact) {
        this.exact = exact;
    }

    @Override
    public void pushOntoStack(InsnList instructions, BindingContext bindingContext) {
        Location location = bindingContext.getLocation();
        AbstractInsnNode insnNode = location.getInsnNode();
        int line = -1;
        if (exact) {
            if (insnNode instanceof LineNumberNode) {
                line = ((LineNumberNode) insnNode).line;
            } else {
                throw new IllegalArgumentException("LineBinding location is not LineNumberNode, insnNode: " + insnNode);
            }
        } else {
            if (location.isWhenComplete() == false) {
                while (insnNode != null) {
                    if (insnNode instanceof LineNumberNode) {
                        line = ((LineNumberNode) insnNode).line;
                        break;
                    }
                    insnNode = insnNode.getPrevious();
                }
            } else {

            }
        }
        AsmOpUtils.push(instructions, line);
    }

    @Override
    public Type getType(BindingContext bindingContext) {
        return Type.getType(int.class);
    }
}


package org.bouncycastle.crypto.tls;

import java.io.IOException;
import java.io.OutputStream;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.encodings.PKCS1Encoding;
import org.bouncycastle.crypto.engines.RSABlindedEngine;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.util.Arrays;

public class TlsRSAUtils {

    public static byte[] generateEncryptedPreMasterSecret(TlsContext tlsContext, RSAKeyParameters rSAKeyParameters, OutputStream outputStream) throws IOException {
        byte[] bArr = new byte[48];
        tlsContext.getSecureRandom().nextBytes(bArr);
        TlsUtils.writeVersion(tlsContext.getClientVersion(), bArr, 0);
        PKCS1Encoding pKCS1Encoding = new PKCS1Encoding(new RSABlindedEngine());
        pKCS1Encoding.init(true, new ParametersWithRandom(rSAKeyParameters, tlsContext.getSecureRandom()));
        try {
            byte[] processBlock = pKCS1Encoding.processBlock(bArr, 0, bArr.length);
            if (TlsUtils.isSSL(tlsContext)) {
                outputStream.write(processBlock);
            } else {
                TlsUtils.writeOpaque16(processBlock, outputStream);
            }
            return bArr;
        } catch (InvalidCipherTextException e) {
            throw new TlsFatalAlert(80, e);
        }
    }

    public static byte[] safeDecryptPreMasterSecret(TlsContext tlsContext, RSAKeyParameters rSAKeyParameters, byte[] bArr) {
        ProtocolVersion clientVersion = tlsContext.getClientVersion();
        byte[] bArr2 = new byte[48];
        tlsContext.getSecureRandom().nextBytes(bArr2);
        byte[] clone = Arrays.clone(bArr2);
        try {
            PKCS1Encoding pKCS1Encoding = new PKCS1Encoding(new RSABlindedEngine(), bArr2);
            pKCS1Encoding.init(false, new ParametersWithRandom(rSAKeyParameters, tlsContext.getSecureRandom()));
            clone = pKCS1Encoding.processBlock(bArr, 0, bArr.length);
        } catch (Exception e) {
        }
        byte majorVersion = (clientVersion.getMajorVersion() ^ (clone[0] & 255)) | (clientVersion.getMinorVersion() ^ (clone[1] & 255));
        byte b = majorVersion | (majorVersion >> 1);
        byte b2 = b | (b >> 2);
        int i = ~(((b2 | (b2 >> 4)) & 1) - 1);


try {
            byte[] processBlock = pKCS1Encoding.processBlock(bArr, 0, bArr.length);
            if (TlsUtils.isSSL(tlsContext)) {
                outputStream.write(processBlock);
            } else {
                TlsUtils.writeOpaque16(processBlock, outputStream);
            }
            return bArr;
        } catch (InvalidCipherTextException e) {
            throw new TlsFatalAlert(80, e);
        }

package org.bouncycastle.crypto.tls;

import java.io.IOException;
import java.io.OutputStream;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.encodings.PKCS1Encoding;
import org.bouncycastle.crypto.engines.RSABlindedEngine;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.util.Arrays;

public class TlsRSAUtils {

    public static byte[] generateEncryptedPreMasterSecret(TlsContext tlsContext, RSAKeyParameters rSAKeyParameters, OutputStream outputStream) throws IOException {
        byte[] bArr = new byte[48];
        tlsContext.getSecureRandom().nextBytes(bArr);
        TlsUtils.writeVersion(tlsContext.getClientVersion(), bArr, 0);
        PKCS1Encoding pKCS1Encoding = new PKCS1Encoding(new RSABlindedEngine());
        pKCS1Encoding.init(true, new ParametersWithRandom(rSAKeyParameters, tlsContext.getSecureRandom()));

    }

    public static byte[] safeDecryptPreMasterSecret(TlsContext tlsContext, RSAKeyParameters rSAKeyParameters, byte[] bArr) {
        ProtocolVersion clientVersion = tlsContext.getClientVersion();
        byte[] bArr2 = new byte[48];
        tlsContext.getSecureRandom().nextBytes(bArr2);
        byte[] clone = Arrays.clone(bArr2);
        try {
            PKCS1Encoding pKCS1Encoding = new PKCS1Encoding(new RSABlindedEngine(), bArr2);
            pKCS1Encoding.init(false, new ParametersWithRandom(rSAKeyParameters, tlsContext.getSecureRandom()));
            clone = pKCS1Encoding.processBlock(bArr, 0, bArr.length);
        } catch (Exception e) {
        }
        byte majorVersion = (clientVersion.getMajorVersion() ^ (clone[0] & 255)) | (clientVersion.getMinorVersion() ^ (clone[1] & 255));
        byte b = majorVersion | (majorVersion >> 1);
        byte b2 = b | (b >> 2);
        int i = ~(((b2 | (b2 >> 4)) & 1) - 1);
        for (int i2 = 0; i2 < 48; i2++) {
            clone[i2] = (byte) ((clone[i2] & (~i)) | (bArr2[i2] & i));
        }
        return clone;
    }
}


{
        if (!"1".equals(req.getParameter("appinfo")) || !AppInfo.getBoolean("sumk.appinfo.monitor", false)) {
            return;
        }
        StringBuilder sb = new StringBuilder();
        new TreeMap<>(AppInfo.subMap("")).forEach((k, v) -> {
            sb.append(k).append(" = ").append(v.replace(LN, Const.CONFIG_NEW_LINE)).append(LN);
        });
        writer.append(sb.toString());
        writer.append(TYPE_SPLIT);
    }

package org.yx.http.server;

import static org.yx.conf.Const.LN;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ThreadPoolExecutor;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.yx.annotation.Bean;
import org.yx.annotation.http.SumkServlet;
import org.yx.common.Monitors;
import org.yx.common.action.ActionStatis;
import org.yx.common.action.StatisItem;
import org.yx.common.sumk.UnsafeStringWriter;
import org.yx.conf.AppInfo;
import org.yx.conf.Const;
import org.yx.http.kit.InnerHttpUtil;
import org.yx.http.user.UserSession;
import org.yx.http.user.WebSessions;
import org.yx.main.SumkThreadPool;
import org.yx.util.StringUtil;

@Bean
@SumkServlet(path = { "/_sumk_monitor/*" }, loadOnStartup = -1, appKey = "sumkMonitor")
public class SumkMonitor extends AbstractCommonHttpServlet {

    private static final long serialVersionUID = 2364534491L;

    private static final String TYPE_SPLIT = "\n\n\n";

    @Override
    protected void handle(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (!InnerHttpUtil.preServerHandle(req, resp, "sumk.http.monitor")) {
            return;
        }
        UnsafeStringWriter writer = new UnsafeStringWriter(512);
        this.outputServerInfo(req, writer);
        this.outputStatis(req, writer);
        this.visitInfo(req, writer);
        this.outputSystem(req, writer);
        this.outputJvmInfo(req, writer);
        this.outputGcInfo(req, writer);
        this.outputAllTrack(req, writer);
        this.outputThreadPool(req, writer);
        this.outputLogLevels(req, writer);
        this.outputLocalSessions(req, writer);
        this.outputAppInfo(req, writer);
        this.outputDataSource(req, writer);
        this.outputSumkDate(req, writer);
        this.outputRpcDatas(req, writer);
        writer.flush();
        String ret = writer.toString();
        resp.getOutputStream().write(ret.getBytes(StandardCharsets.UTF_8));
    }

    private String localSessions() {
        UserSession userSession = WebSessions.userSession();
        if (userSession == null) {
            return "";
        }
        return new StringBuilder("##localSessions:").append("  ").append(userSession.localCacheSize()).toString();
    }

    private void outputLocalSessions(HttpServletRequest req, Writer writer) throws IOException {
        if (!"1".equals(req.getParameter("localSessions"))) {
            return;
        }
        writer.append(localSessions());
        writer.append(TYPE_SPLIT);
    }

    private void outputServerInfo(HttpServletRequest req, Writer writer) throws IOException {
        if (!"1".equals(req.getParameter("server"))) {
            return;
        }
        writer.append(Monitors.serverInfo());
        writer.append(TYPE_SPLIT);
    }

    private void outputStatis(HttpServletRequest req, Writer writer) throws IOException {
        if (!"1".equals(req.getParameter("statis"))) {
            return;
        }
        ActionStatis actStatic = InnerHttpUtil.getActionStatis();
        boolean needReset = "1".equals(req.getParameter("statis.reset")) && AppInfo.getBoolean("sumk.http.statis.reset.allow", true);
        Map<String, StatisItem> map = needReset ? actStatic.getAndReset() : actStatic.getAll();
        List<StatisItem> values = new ArrayList<>(map.values());
        values.sort((a, b) -> Long.compare(b.getSuccessTime(), a.getSuccessTime()));
        long totalSuccessCount = 0;
        long totalSuccessTime = 0;
        long totalFailCount = 0;
        long totalFailTime = 0;
        boolean onlyfailed = "1".equals(req.getParameter("statis.onlyfailed"));
        StringBuilder sb = new StringBuilder("##").append(StatisItem.header()).append(LN);
        for (StatisItem v : values) {
            if (onlyfailed && v.getFailedCount() == 0) {
                continue;
            }
            sb.append(v.toSimpleString()).append(LN);
            totalSuccessCount += v.getSuccessCount();
            totalSuccessTime += v.getSuccessTime();
            totalFailCount += v.getFailedCount();
            totalFailTime += v.getFailedTime();
        }
        long c = totalSuccessCount;
        long t = totalSuccessTime;
        double avg = c == 0 ? 0 : t * 1d / c;
        String total = String.join("   ", "**TOTAL**", String.valueOf(c), String.valueOf(t), String.valueOf(Math.round(avg)), String.valueOf(totalFailCount), String.valueOf(totalFailTime));
        sb.append(total).append(LN);
        writer.append(sb.toString());
        writer.append(TYPE_SPLIT);
    }

    private void outputSystem(HttpServletRequest req, Writer writer) throws IOException {
        if (!"1".equals(req.getParameter("system"))) {
            return;
        }
        writer.append(Monitors.systemInfo());
        writer.append(TYPE_SPLIT);
    }

    private void outputJvmInfo(HttpServletRequest req, Writer writer) throws IOException {
        if (!"1".equals(req.getParameter("jvm"))) {
            return;
        }
        writer.append(Monitors.jvmInfo());
        writer.append(TYPE_SPLIT);
    }

    private void outputAllTrack(HttpServletRequest req, Writer writer) throws IOException {
        if (!"1".equals(req.getParameter("stack"))) {
            return;
        }
        writer.append(Monitors.allTrack());
        writer.append(TYPE_SPLIT);
    }

    private void outputThreadPool(HttpServletRequest req, Writer writer) throws IOException {
        if (!"1".equals(req.getParameter("threadpool"))) {
            return;
        }
        writer.append(Monitors.threadPoolInfo((ThreadPoolExecutor) SumkThreadPool.executor()));
        writer.append(TYPE_SPLIT);
    }

    private void outputLogLevels(HttpServletRequest req, Writer writer) throws IOException {
        if (!"1".equals(req.getParameter("logLevel"))) {
            return;
        }
        writer.append(Monitors.logLevels());
        writer.append(TYPE_SPLIT);
    }

    private void outputAppInfo(HttpServletRequest req, Writer writer) throws IOException

    private void visitInfo(HttpServletRequest req, Writer writer) throws IOException {
        if (!"1".equals(req.getParameter("db.cache"))) {
            return;
        }
        writer.append(Monitors.dbVisitInfo());
        writer.append(TYPE_SPLIT);
    }

    private void outputDataSource(HttpServletRequest req, Writer writer) throws IOException {
        String ds = req.getParameter("datasource");
        if (StringUtil.isEmpty(ds)) {
            return;
        }
        writer.append(Monitors.dataSourceStatus(ds));
        writer.append(TYPE_SPLIT);
    }

    private void outputSumkDate(HttpServletRequest req, UnsafeStringWriter writer) {
        if (!"1".equals(req.getParameter("sumkdate"))) {
            return;
        }
        writer.append(Monitors.sumkDateCacheChangeCount());
        writer.append(TYPE_SPLIT);
    }

    private void outputGcInfo(HttpServletRequest req, UnsafeStringWriter writer) {
        if (!"1".equals(req.getParameter("gc"))) {
            return;
        }
        writer.append(Monitors.gcInfo());
        writer.append(TYPE_SPLIT);
    }

    private void outputRpcDatas(HttpServletRequest req, Writer writer) throws IOException {
        if (!"1".equals(req.getParameter("rpcData"))) {
            return;
        }
        writer.append(Monitors.rpcDatas());
        writer.append(TYPE_SPLIT);
    }
}


package org.aisen.android.ui.fragment;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.aisen.android.R;
import org.aisen.android.common.utils.Logger;
import org.aisen.android.common.utils.ViewUtils;
import org.aisen.android.component.bitmaploader.BitmapLoader;
import org.aisen.android.component.bitmaploader.core.BitmapOwner;
import org.aisen.android.network.biz.ABizLogic.CacheMode;
import org.aisen.android.network.biz.IResult;
import org.aisen.android.network.task.ITaskManager;
import org.aisen.android.network.task.TaskException;
import org.aisen.android.network.task.TaskManager;
import org.aisen.android.network.task.WorkTask;
import org.aisen.android.support.inject.InjectUtility;
import org.aisen.android.support.inject.ViewInject;
import org.aisen.android.ui.activity.basic.BaseActivity;
import java.text.SimpleDateFormat;

/**
 * 基于ABaseFragment，维护与Activity之间的生命周期绑定，管理WorkTask线程，支持四种个基本视图之间的自动切换

 *
 * 1、处理缓存数据过期后，自动刷新页面

 * 2、处理页面离开设定时间后，自动刷新页面

 */
public abstract class ABaseFragment extends Fragment implements ITaskManager, BitmapOwner {

    static final String TAG = "AFragment-Base";

    public enum ABaseTaskState {

        none,
        prepare,
        falid,
        success,
        finished,
        canceled
    }

    // 管理线程
    private TaskManager taskManager;

    // 根视图
    ViewGroup rootView;

    @ViewInject(idStr = "layoutLoading")
    View // 加载中视图
    loadingLayout;

    @ViewInject(idStr = "layoutLoadFailed")
    View // 加载失败视图
    loadFailureLayout;

    @ViewInject(idStr = "layoutContent")
    View // 内容视图
    contentLayout;

    @ViewInject(idStr = "layoutEmpty")
    View // 空视图
    emptyLayout;

    // 标志是否ContentView是否为空
    private boolean contentEmpty = true;

    // 最后一次非缓存数据获取时间
    protected long lastResultGetTime = 0;

    private boolean destory = false;

    // UI线程的Handler
    Handler mHandler = new Handler(Looper.getMainLooper()) {
    };

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (activity instanceof BaseActivity)
            ((BaseActivity) activity).addFragment(toString(), this);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        taskManager = new TaskManager();
        if (savedInstanceState != null)
            taskManager.restore(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (inflateContentView() > 0) {
            ViewGroup contentView = (ViewGroup) inflater.inflate(inflateContentView(), null);
            contentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            setupContentView(inflater, contentView, savedInstanceState);
            return getContentView();
        }
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    /**
     * 根据ContentView初始化视图
     *
     * @param inflater
     * @param contentView
     * @param savedInstanceState
     */
    protected void setupContentView(LayoutInflater inflater, ViewGroup contentView, Bundle savedInstanceState) {
        setContentView(contentView);
        _layoutInit(inflater, savedInstanceState);
        layoutInit(inflater, savedInstanceState);
    }

    public void setContentView(ViewGroup view) {
        this.rootView = view;
    }

    public ViewGroup getContentView() {
        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (savedInstanceState == null)
            requestData();
    }

    /**
     * Action的home被点击了
     *
     * @return
     */
    public boolean onHomeClick() {
        return onBackClick();
    }

    public boolean onBackClick() {
        return false;
    }

    public void requestData() {
    }

    /**
     * 延迟时间刷新
     *
     * @param delay
     */
    public void requestDataDelay(long delay) {
        Runnable requestDelayRunnable = new Runnable() {

            @Override
            public void run() {
                Logger.d(TAG, "延迟刷新，开始刷新, " + toString());
                requestData();
            }
        };
        runUIRunnable(requestDelayRunnable, delay);
    }

    public void requestDataOutofdate() {
        requestData();
    }

    /**
     * A*Fragment重写这个方法
     *
     * @param inflater
     * @param savedInstanceSate
     */
    void _layoutInit(LayoutInflater inflater, Bundle savedInstanceSate) {
        InjectUtility.initInjectedView(getActivity(), this, getContentView());
        if (emptyLayout != null) {
            View reloadView = emptyLayout.findViewById(R.id.layoutReload);
            if (reloadView != null)
                setViewOnClick(reloadView);
        }
        if (loadFailureLayout != null) {
            View reloadView = loadFailureLayout.findViewById(R.id.layoutReload);
            if (reloadView != null)
                setViewOnClick(reloadView);
        }
        setViewVisiable(loadingLayout, View.GONE);
        setViewVisiable(loadFailureLayout, View.GONE);
        setViewVisiable(emptyLayout, View.GONE);
        if (isContentEmpty()) {
            // 如果视图为空，就开始加载数据
            if (savedInstanceSate != null) {
                requestData();
            } else {
                setViewVisiable(emptyLayout, View.VISIBLE);
                setViewVisiable(contentLayout, View.GONE);
            }
        } else {
            setViewVisiable(contentLayout, View.VISIBLE);
        }
    }

    public View findViewById(int viewId) {
        if (getContentView() == null)
            return null;
        return getContentView().findViewById(viewId);
    }

    public void setContentEmpty(boolean empty) {
        this.contentEmpty = empty;
    }

    public boolean isContentEmpty() {
        return contentEmpty;
    }

    /**
     * 视图点击回调，子类重写
     *
     * @param view
     */
    public void onViewClicked(View view) {
        if (view.getId() == R.id.layoutReload)
            requestData();
        else if (view.getId() == R.id.layoutRefresh)
            requestData();
    }

    protected void setViewVisiable(View v, int visibility) {
        if (v != null && v.getVisibility() != visibility)
            v.setVisibility(visibility);
    }

    /**
     * 根据{@link ABaseTask} 的加载状态，刷新视图
     *
     * @param state
     *
     * @param exception
     */
    protected void onTaskStateChanged(ABaseTaskState state, TaskException exception) {
        // 开始Task
        if (state == ABaseTaskState.prepare) {
            if (isContentEmpty()) {
                setViewVisiable(loadingLayout, View.VISIBLE);
                setViewVisiable(contentLayout, View.GONE);
            } else {
                setViewVisiable(loadingLayout, View.GONE);
                setViewVisiable(contentLayout, View.VISIBLE);
            }
            setViewVisiable(emptyLayout, View.GONE);
            if (isContentEmpty() && loadingLayout == null) {
                setViewVisiable(contentLayout, View.VISIBLE);
            }
            setViewVisiable(loadFailureLayout, View.GONE);
        } else // Task成功
        if (state == ABaseTaskState.success) {
            setViewVisiable(loadingLayout, View.GONE);
            if (isContentEmpty()) {
                setViewVisiable(emptyLayout, View.VISIBLE);
                setViewVisiable(contentLayout, View.GONE);
            } else {
                setViewVisiable(contentLayout, View.VISIBLE);
                setViewVisiable(emptyLayout, View.GONE);
            }
        } else // 取消Task
        if (state == ABaseTaskState.canceled) {
            if (isContentEmpty()) {
                setViewVisiable(loadingLayout, View.GONE);
                setViewVisiable(emptyLayout, View.VISIBLE);
            }
        } else // Task失败
        if (state == ABaseTaskState.falid) {
            if (isContentEmpty()) {
                if (loadFailureLayout != null) {
                    setViewVisiable(loadFailureLayout, View.VISIBLE);
                    if (exception != null) {
                        TextView txtLoadFailed = (TextView) loadFailureLayout.findViewById(R.id.txtLoadFailed);
                        if (txtLoadFailed != null)
                            txtLoadFailed.setText(exception.getMessage());
                    }
                    setViewVisiable(emptyLayout, View.GONE);
                } else {
                    setViewVisiable(emptyLayout, View.VISIBLE);
                }
                setViewVisiable(loadingLayout, View.GONE);
            }
        } else // Task结束
        if (state == ABaseTaskState.finished) {
        }
    }

    public void showMessage(CharSequence msg) {
        if (!TextUtils.isEmpty(msg) && getActivity() != null)
            ViewUtils.showMessage(getActivity(), msg.toString());
    }

    public void showMessage(int msgId) {
        if (getActivity() != null)
            showMessage(getString(msgId));
    }

    /**
     * Fragment主要的刷新任务线程，定义任务加载流程，耦合Fragment各个状态下的视图刷新方法
     *
     * @param <Params>
     * @param <Progress>
     * @param <Result>
     */
    protected abstract class ABaseTask<Params, Progress, Result> extends WorkTask<Params, Progress, Result> {

        public ABaseTask(String taskId) {
            super(taskId, ABaseFragment.this);
        }

        @Override
        protected void onPrepare() {
            super.onPrepare();
            onTaskStateChanged(ABaseTaskState.prepare, null);
        }

        @Override
        protected void onSuccess(Result result) {
            super.onSuccess(result);
            // 默认加载数据成功，且ContentView有数据展示
            ABaseFragment.this.setContentEmpty(resultIsEmpty(result));
            onTaskStateChanged(ABaseTaskState.success, null);
            if (Logger.DEBUG)
                Logger.d(TAG, "Result获取时间：%s", new SimpleDateFormat("HH:mm:ss").format(lastResultGetTime));
            if (result instanceof IResult) {
                IResult iResult = (IResult) result;
                // 数据是缓存数据
                if (iResult.fromCache()) {
                    // 缓存过期刷新数据
                    if (iResult.outofdate()) {
                        runUIRunnable(new Runnable() {

                            @Override
                            public void run() {
                                Logger.d(TAG, "数据过期，开始刷新, " + toString());
                                requestDataOutofdate();
                            }
                        }, configRequestDelay());
                    }
                } else {
                    lastResultGetTime = System.currentTimeMillis();
                }
            } else {
                lastResultGetTime = System.currentTimeMillis();
            }
        }

        @Override
        protected void onFailure(TaskException exception) {
            super.onFailure(exception);
            onTaskStateChanged(ABaseTaskState.falid, exception);
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
            onTaskStateChanged(ABaseTaskState.canceled, null);
        }

        @Override
        protected void onFinished() {
            super.onFinished();
            onTaskStateChanged(ABaseTaskState.finished, null);
        }

        /**
         * 返回数据是否空
         *
         * @param result
         * @return
         */
        protected boolean resultIsEmpty(Result result) {
            return result == null ? true : false;
        }
    }

    @Override
    public void onDestroy() {
        destory = true;
        try {
            // 4.1.1必报错，不知道为什么
            super.onDestroy();
        } catch (Exception e) {
            Logger.printExc(getClass(), e);
        }
        removeAllTask(true);
        if (BitmapLoader.getInstance() != null)
            BitmapLoader.getInstance().cancelPotentialTask(this);
    }

    public boolean isDestory() {
        return destory;
    }

    public boolean isActivityRunning() {
        return getActivity() != null;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        if (getActivity() != null && getActivity() instanceof BaseActivity)
            ((BaseActivity) getActivity()).removeFragment(this.toString());
    }

    @Override
    final public void addTask(@SuppressWarnings("rawtypes") WorkTask task) {
        taskManager.addTask(task);
    }

    @Override
    final public void removeTask(String taskId, boolean cancelIfRunning) {
        taskManager.removeTask(taskId, cancelIfRunning);
    }

    @Override
    final public void removeAllTask(boolean cancelIfRunning) {
        taskManager.removeAllTask(cancelIfRunning);
    }

    @Override
    final public int getTaskCount(String taskId) {
        return taskManager.getTaskCount(taskId);
    }

    /**
     * 初步定义，当Task执行BizLogic方法时，第一次创建时拉取缓存，其他都只拉取网络
     *
     * @param task
     * @return
     */
    final protected CacheMode getTaskCacheMode(WorkTask task) {
        if (task == null || !TextUtils.isEmpty(task.getTaskId()))
            return getTaskCount(task.getTaskId()) == 1 ? CacheMode.auto : CacheMode.disable;
        return CacheMode.disable;
    }

    @Override
    public void clearTaskCount(String taskId) {
        taskManager.clearTaskCount(taskId);
    }

    protected void setViewOnClick(View v) {
        if (v == null)
            return;
        v.setOnClickListener(innerOnClickListener);
    }

    View.OnClickListener innerOnClickListener = new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            onViewClicked(v);
        }
    };

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (taskManager != null)
            taskManager.save(outState);
    }

    protected ITaskManager getTaskManager() {
        return taskManager;
    }

    public void runUIRunnable(Runnable runnable) {
        runUIRunnable(runnable, 0);
    }

    public void runUIRunnable(Runnable runnable, long delay) {
        if (delay > 0) {
            mHandler.removeCallbacks(runnable);
            mHandler.postDelayed(runnable, delay);
        } else {
            mHandler.post(runnable);
        }
    }

    /**
     * 子类重写这个方法，初始化视图
     *
     * @param inflater
     * @param savedInstanceSate
     */
    protected void layoutInit(LayoutInflater inflater, Bundle savedInstanceSate) {
    }

    @Override
    public boolean canDisplay() {
        return true;
    }

    /**
     * 指定Fragment的LayoutID
     *
     * @return
     */
    abstract public int inflateContentView();

    /**
     * 指定Activity的ContentViewID
     *
     * @return
     */
    public int inflateActivityContentView() {
        return -1;
    }

    /**
     * 设置Activity的Theme
     *
     * @return
     */
    public int setActivityTheme() {
        return -1;
    }

    public int configRequestDelay()

    public View getLoadingLayout() {
        return loadingLayout;
    }

    public View getLoadFailureLayout() {
        return loadFailureLayout;
    }

    public View getContentLayout() {
        return contentLayout;
    }

    public View getEmptyLayout() {
        return emptyLayout;
    }
}


public boolean onHomeClick() {
        return onBackClick();
    }

package org.aisen.android.ui.fragment;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.aisen.android.R;
import org.aisen.android.common.utils.Logger;
import org.aisen.android.common.utils.ViewUtils;
import org.aisen.android.component.bitmaploader.BitmapLoader;
import org.aisen.android.component.bitmaploader.core.BitmapOwner;
import org.aisen.android.network.biz.ABizLogic.CacheMode;
import org.aisen.android.network.biz.IResult;
import org.aisen.android.network.task.ITaskManager;
import org.aisen.android.network.task.TaskException;
import org.aisen.android.network.task.TaskManager;
import org.aisen.android.network.task.WorkTask;
import org.aisen.android.support.inject.InjectUtility;
import org.aisen.android.support.inject.ViewInject;
import org.aisen.android.ui.activity.basic.BaseActivity;
import java.text.SimpleDateFormat;

/**
 * 基于ABaseFragment，维护与Activity之间的生命周期绑定，管理WorkTask线程，支持四种个基本视图之间的自动切换

 *
 * 1、处理缓存数据过期后，自动刷新页面

 * 2、处理页面离开设定时间后，自动刷新页面

 */
public abstract class ABaseFragment extends Fragment implements ITaskManager, BitmapOwner {

    static final String TAG = "AFragment-Base";

    public enum ABaseTaskState {

        none,
        prepare,
        falid,
        success,
        finished,
        canceled
    }

    // 管理线程
    private TaskManager taskManager;

    // 根视图
    ViewGroup rootView;

    @ViewInject(idStr = "layoutLoading")
    View // 加载中视图
    loadingLayout;

    @ViewInject(idStr = "layoutLoadFailed")
    View // 加载失败视图
    loadFailureLayout;

    @ViewInject(idStr = "layoutContent")
    View // 内容视图
    contentLayout;

    @ViewInject(idStr = "layoutEmpty")
    View // 空视图
    emptyLayout;

    // 标志是否ContentView是否为空
    private boolean contentEmpty = true;

    // 最后一次非缓存数据获取时间
    protected long lastResultGetTime = 0;

    private boolean destory = false;

    // UI线程的Handler
    Handler mHandler = new Handler(Looper.getMainLooper()) {
    };

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (activity instanceof BaseActivity)
            ((BaseActivity) activity).addFragment(toString(), this);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        taskManager = new TaskManager();
        if (savedInstanceState != null)
            taskManager.restore(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (inflateContentView() > 0) {
            ViewGroup contentView = (ViewGroup) inflater.inflate(inflateContentView(), null);
            contentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            setupContentView(inflater, contentView, savedInstanceState);
            return getContentView();
        }
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    /**
     * 根据ContentView初始化视图
     *
     * @param inflater
     * @param contentView
     * @param savedInstanceState
     */
    protected void setupContentView(LayoutInflater inflater, ViewGroup contentView, Bundle savedInstanceState) {
        setContentView(contentView);
        _layoutInit(inflater, savedInstanceState);
        layoutInit(inflater, savedInstanceState);
    }

    public void setContentView(ViewGroup view) {
        this.rootView = view;
    }

    public ViewGroup getContentView() {
        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (savedInstanceState == null)
            requestData();
    }

    /**
     * Action的home被点击了
     *
     * @return
     */

    public boolean onBackClick() {
        return false;
    }

    public void requestData() {
    }

    /**
     * 延迟时间刷新
     *
     * @param delay
     */
    public void requestDataDelay(long delay) {
        Runnable requestDelayRunnable = new Runnable() {

            @Override
            public void run() {
                Logger.d(TAG, "延迟刷新，开始刷新, " + toString());
                requestData();
            }
        };
        runUIRunnable(requestDelayRunnable, delay);
    }

    public void requestDataOutofdate() {
        requestData();
    }

    /**
     * A*Fragment重写这个方法
     *
     * @param inflater
     * @param savedInstanceSate
     */
    void _layoutInit(LayoutInflater inflater, Bundle savedInstanceSate) {
        InjectUtility.initInjectedView(getActivity(), this, getContentView());
        if (emptyLayout != null) {
            View reloadView = emptyLayout.findViewById(R.id.layoutReload);
            if (reloadView != null)
                setViewOnClick(reloadView);
        }
        if (loadFailureLayout != null) {
            View reloadView = loadFailureLayout.findViewById(R.id.layoutReload);
            if (reloadView != null)
                setViewOnClick(reloadView);
        }
        setViewVisiable(loadingLayout, View.GONE);
        setViewVisiable(loadFailureLayout, View.GONE);
        setViewVisiable(emptyLayout, View.GONE);
        if (isContentEmpty()) {
            // 如果视图为空，就开始加载数据
            if (savedInstanceSate != null) {
                requestData();
            } else {
                setViewVisiable(emptyLayout, View.VISIBLE);
                setViewVisiable(contentLayout, View.GONE);
            }
        } else {
            setViewVisiable(contentLayout, View.VISIBLE);
        }
    }

    public View findViewById(int viewId) {
        if (getContentView() == null)
            return null;
        return getContentView().findViewById(viewId);
    }

    public void setContentEmpty(boolean empty) {
        this.contentEmpty = empty;
    }

    public boolean isContentEmpty() {
        return contentEmpty;
    }

    /**
     * 视图点击回调，子类重写
     *
     * @param view
     */
    public void onViewClicked(View view) {
        if (view.getId() == R.id.layoutReload)
            requestData();
        else if (view.getId() == R.id.layoutRefresh)
            requestData();
    }

    protected void setViewVisiable(View v, int visibility) {
        if (v != null && v.getVisibility() != visibility)
            v.setVisibility(visibility);
    }

    /**
     * 根据{@link ABaseTask} 的加载状态，刷新视图
     *
     * @param state
     *
     * @param exception
     */
    protected void onTaskStateChanged(ABaseTaskState state, TaskException exception) {
        // 开始Task
        if (state == ABaseTaskState.prepare) {
            if (isContentEmpty()) {
                setViewVisiable(loadingLayout, View.VISIBLE);
                setViewVisiable(contentLayout, View.GONE);
            } else {
                setViewVisiable(loadingLayout, View.GONE);
                setViewVisiable(contentLayout, View.VISIBLE);
            }
            setViewVisiable(emptyLayout, View.GONE);
            if (isContentEmpty() && loadingLayout == null) {
                setViewVisiable(contentLayout, View.VISIBLE);
            }
            setViewVisiable(loadFailureLayout, View.GONE);
        } else // Task成功
        if (state == ABaseTaskState.success) {
            setViewVisiable(loadingLayout, View.GONE);
            if (isContentEmpty()) {
                setViewVisiable(emptyLayout, View.VISIBLE);
                setViewVisiable(contentLayout, View.GONE);
            } else {
                setViewVisiable(contentLayout, View.VISIBLE);
                setViewVisiable(emptyLayout, View.GONE);
            }
        } else // 取消Task
        if (state == ABaseTaskState.canceled) {
            if (isContentEmpty()) {
                setViewVisiable(loadingLayout, View.GONE);
                setViewVisiable(emptyLayout, View.VISIBLE);
            }
        } else // Task失败
        if (state == ABaseTaskState.falid) {
            if (isContentEmpty()) {
                if (loadFailureLayout != null) {
                    setViewVisiable(loadFailureLayout, View.VISIBLE);
                    if (exception != null) {
                        TextView txtLoadFailed = (TextView) loadFailureLayout.findViewById(R.id.txtLoadFailed);
                        if (txtLoadFailed != null)
                            txtLoadFailed.setText(exception.getMessage());
                    }
                    setViewVisiable(emptyLayout, View.GONE);
                } else {
                    setViewVisiable(emptyLayout, View.VISIBLE);
                }
                setViewVisiable(loadingLayout, View.GONE);
            }
        } else // Task结束
        if (state == ABaseTaskState.finished) {
        }
    }

    public void showMessage(CharSequence msg) {
        if (!TextUtils.isEmpty(msg) && getActivity() != null)
            ViewUtils.showMessage(getActivity(), msg.toString());
    }

    public void showMessage(int msgId) {
        if (getActivity() != null)
            showMessage(getString(msgId));
    }

    /**
     * Fragment主要的刷新任务线程，定义任务加载流程，耦合Fragment各个状态下的视图刷新方法
     *
     * @param <Params>
     * @param <Progress>
     * @param <Result>
     */
    protected abstract class ABaseTask<Params, Progress, Result> extends WorkTask<Params, Progress, Result> {

        public ABaseTask(String taskId) {
            super(taskId, ABaseFragment.this);
        }

        @Override
        protected void onPrepare() {
            super.onPrepare();
            onTaskStateChanged(ABaseTaskState.prepare, null);
        }

        @Override
        protected void onSuccess(Result result) {
            super.onSuccess(result);
            // 默认加载数据成功，且ContentView有数据展示
            ABaseFragment.this.setContentEmpty(resultIsEmpty(result));
            onTaskStateChanged(ABaseTaskState.success, null);
            if (Logger.DEBUG)
                Logger.d(TAG, "Result获取时间：%s", new SimpleDateFormat("HH:mm:ss").format(lastResultGetTime));
            if (result instanceof IResult) {
                IResult iResult = (IResult) result;
                // 数据是缓存数据
                if (iResult.fromCache()) {
                    // 缓存过期刷新数据
                    if (iResult.outofdate()) {
                        runUIRunnable(new Runnable() {

                            @Override
                            public void run() {
                                Logger.d(TAG, "数据过期，开始刷新, " + toString());
                                requestDataOutofdate();
                            }
                        }, configRequestDelay());
                    }
                } else {
                    lastResultGetTime = System.currentTimeMillis();
                }
            } else {
                lastResultGetTime = System.currentTimeMillis();
            }
        }

        @Override
        protected void onFailure(TaskException exception) {
            super.onFailure(exception);
            onTaskStateChanged(ABaseTaskState.falid, exception);
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
            onTaskStateChanged(ABaseTaskState.canceled, null);
        }

        @Override
        protected void onFinished() {
            super.onFinished();
            onTaskStateChanged(ABaseTaskState.finished, null);
        }

        /**
         * 返回数据是否空
         *
         * @param result
         * @return
         */
        protected boolean resultIsEmpty(Result result) {
            return result == null ? true : false;
        }
    }

    @Override
    public void onDestroy() {
        destory = true;
        try {
            // 4.1.1必报错，不知道为什么
            super.onDestroy();
        } catch (Exception e) {
            Logger.printExc(getClass(), e);
        }
        removeAllTask(true);
        if (BitmapLoader.getInstance() != null)
            BitmapLoader.getInstance().cancelPotentialTask(this);
    }

    public boolean isDestory() {
        return destory;
    }

    public boolean isActivityRunning() {
        return getActivity() != null;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        if (getActivity() != null && getActivity() instanceof BaseActivity)
            ((BaseActivity) getActivity()).removeFragment(this.toString());
    }

    @Override
    final public void addTask(@SuppressWarnings("rawtypes") WorkTask task) {
        taskManager.addTask(task);
    }

    @Override
    final public void removeTask(String taskId, boolean cancelIfRunning) {
        taskManager.removeTask(taskId, cancelIfRunning);
    }

    @Override
    final public void removeAllTask(boolean cancelIfRunning) {
        taskManager.removeAllTask(cancelIfRunning);
    }

    @Override
    final public int getTaskCount(String taskId) {
        return taskManager.getTaskCount(taskId);
    }

    /**
     * 初步定义，当Task执行BizLogic方法时，第一次创建时拉取缓存，其他都只拉取网络
     *
     * @param task
     * @return
     */
    final protected CacheMode getTaskCacheMode(WorkTask task) {
        if (task == null || !TextUtils.isEmpty(task.getTaskId()))
            return getTaskCount(task.getTaskId()) == 1 ? CacheMode.auto : CacheMode.disable;
        return CacheMode.disable;
    }

    @Override
    public void clearTaskCount(String taskId) {
        taskManager.clearTaskCount(taskId);
    }

    protected void setViewOnClick(View v) {
        if (v == null)
            return;
        v.setOnClickListener(innerOnClickListener);
    }

    View.OnClickListener innerOnClickListener = new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            onViewClicked(v);
        }
    };

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (taskManager != null)
            taskManager.save(outState);
    }

    protected ITaskManager getTaskManager() {
        return taskManager;
    }

    public void runUIRunnable(Runnable runnable) {
        runUIRunnable(runnable, 0);
    }

    public void runUIRunnable(Runnable runnable, long delay) {
        if (delay > 0) {
            mHandler.removeCallbacks(runnable);
            mHandler.postDelayed(runnable, delay);
        } else {
            mHandler.post(runnable);
        }
    }

    /**
     * 子类重写这个方法，初始化视图
     *
     * @param inflater
     * @param savedInstanceSate
     */
    protected void layoutInit(LayoutInflater inflater, Bundle savedInstanceSate) {
    }

    @Override
    public boolean canDisplay() {
        return true;
    }

    /**
     * 指定Fragment的LayoutID
     *
     * @return
     */
    abstract public int inflateContentView();

    /**
     * 指定Activity的ContentViewID
     *
     * @return
     */
    public int inflateActivityContentView() {
        return -1;
    }

    /**
     * 设置Activity的Theme
     *
     * @return
     */
    public int setActivityTheme() {
        return -1;
    }

    public int configRequestDelay() {
        return 500;
    }

    public View getLoadingLayout() {
        return loadingLayout;
    }

    public View getLoadFailureLayout() {
        return loadFailureLayout;
    }

    public View getContentLayout() {
        return contentLayout;
    }

    public View getEmptyLayout() {
        return emptyLayout;
    }
}