switch(thread.getName()) {
            case "learner":
                updateIndicatorText("Learning Complete");
                break;
        }

package com.gc.fakeimagedetection.ui.controllers;

import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXSnackbar;
import com.gc.fakeimagedetection.core.constants.ConstantObjects;
import com.gc.fakeimagedetection.core.errorlevelanalysis.FIDErrorLevelAnalysis;
import com.gc.fakeimagedetection.core.listener.ErrorLevelAnalysisListener;
import com.gc.fakeimagedetection.core.listener.NeuralnetProcessorListener;
import com.gc.fakeimagedetection.core.metadata.MetadataProcessor;
import com.gc.fakeimagedetection.core.processor.NeuralNetProcessor;
import com.gc.fakeimagedetection.core.trainer.SingleImageTrainer;
import com.gc.fakeimagedetection.core.listener.ThreadCompleteListener;
import com.gc.fakeimagedetection.ui.alert.Calert;
import ij.ImagePlus;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.ParallelTransition;
import javafx.animation.ScaleTransition;
import javafx.animation.Timeline;
import javafx.animation.TranslateTransition;
import javafx.application.Platform;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.control.ButtonType;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
import javax.imageio.ImageIO;

public class NeuralnetInterfaceController implements Initializable, ErrorLevelAnalysisListener, ThreadCompleteListener, NeuralnetProcessorListener {

    public static String imageLocation = "";

    public static String getImageLocation() {
        return imageLocation = LaunchScreeenController.processingFile.getAbsolutePath();
    }

    @FXML
    private StackPane rootPane;

    @FXML
    private ImageView backgroundImageView;

    @FXML
    private AnchorPane anchorPane;

    @FXML
    private Text description;

    @FXML
    private Text christopher;

    @FXML
    private JFXButton navigation_button;

    @FXML
    private ImageView homeIcon;

    NeuralnetInterfaceController thisObject = this;

    ScaleTransition bulgingTransition;

    FIDErrorLevelAnalysis elaAnalyzer;

    NeuralNetProcessor nprocessor;

    BufferedImage elaImage;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        startAnimation();
        getImageLocation();
        elaAnalyzer = new FIDErrorLevelAnalysis(imageLocation, 95, new Dimension(100, 100), this);
        elaAnalyzer.setName("elaAnalyzer");
        elaAnalyzer.start();
    }

    private void startAnimation() {
        navigation_button.setText("Applying ELA on Image");
        float animationExtension = 1.2f;
        bulgingTransition = new ScaleTransition(Duration.millis(2000), navigation_button);
        bulgingTransition.setToX(animationExtension);
        bulgingTransition.setToY(animationExtension);
        bulgingTransition.autoReverseProperty().setValue(true);
        bulgingTransition.setCycleCount(bulgingTransition.INDEFINITE);
        bulgingTransition.play();
    }

    @FXML
    private void loadAnimation(MouseEvent event) {
    }

    @FXML
    private void rollBack(MouseEvent event) {
        LaunchScreeenController.processingFile = null;
        MetadataProcessor.extracted_data = "";
        try {
            Stage stage = (Stage) rootPane.getScene().getWindow();
            Scene pane = new Scene(FXMLLoader.load(getClass().getResource("/resources/fxml/launch.fxml")));
            stage.setScene(pane);
        } catch (IOException ex) {
            Logger.getLogger(NeuralnetInterfaceController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    void updateIndicatorText(String message) {
        Platform.runLater(new Runnable() {

            @Override
            public void run() {
                navigation_button.setText(message);
            }
        });
    }

    void finalMoveOfIndicator() {
        Platform.runLater(new Runnable() {

            @Override
            public void run() {
                Timeline timeline = new Timeline();
                timeline.setCycleCount(1);
                KeyValue keyValueX = new KeyValue(navigation_button.prefWidthProperty(), 300);
                KeyFrame keyFrame = new KeyFrame(Duration.millis(2000), keyValueX);
                timeline.getKeyFrames().add(keyFrame);
                timeline.play();
                navigation_button.setStyle("-fx-background-radius: 0px;");
            }
        });
    }

    void loadResult(HashMap<String, Double> result) {
        System.out.println("Metadata Result: Fakeness = " + ConstantObjects.fakeness);
        if (ConstantObjects.fakeness < 0) {
            System.out.println("Invalid Result from metadata");
        }
        Platform.runLater(new Runnable() {

            final float NEURAL_NET_WEIGHT = 0.4f;

            final float METADATA_NET_WEIGHT = 1 - NEURAL_NET_WEIGHT;

            @Override
            public void run() {
                double real = result.get("real") * 100;
                double fake = result.get("faked") * 100;
                DecimalFormat df2 = new DecimalFormat(".#");
                if (ConstantObjects.shouldPropogateResult) {
                    real = (real * NEURAL_NET_WEIGHT) + (METADATA_NET_WEIGHT * ConstantObjects.realness * 100);
                    fake = (fake * NEURAL_NET_WEIGHT) + (METADATA_NET_WEIGHT * ConstantObjects.fakeness * 100);
                }
                if (real < 10 && fake < 10) {
                    String possibility;
                    if (real >= fake) {
                        possibility = "Possibly Real";
                    } else {
                        possibility = "Possibly Fake";
                    }
                    navigation_button.setStyle("-fx-background-color:#EF6C00");
                    navigation_button.setText("Cant Determine whether fake or not " + possibility);
                } else if (fake > real) {
                    navigation_button.setStyle("-fx-background-color:#f44336");
                    navigation_button.setText("FAKE IMAGE" + "\nConfidence :" + df2.format(fake) + "%");
                } else if (fake < real) {
                    navigation_button.setStyle("-fx-background-color:#4CAF50");
                    navigation_button.setText("REAL IMAGE" + "\nConfidence :" + df2.format(real) + "%");
                } else {
                    navigation_button.setStyle("-fx-background-color:#4CAF50");
                    navigation_button.setText("Process Failed. 50-50 Chance");
                }
                final JFXSnackbar snackbar = new JFXSnackbar(rootPane);
                snackbar.getStylesheets().add(getClass().getResource("/resources/stylesheets/main.css").toExternalForm());
                EventHandler handler = new EventHandler() {

                    @Override
                    public void handle(Event event) {
                        snackbar.unregisterSnackbarContainer(rootPane);
                        Alert alert = new Alert(AlertType.CONFIRMATION);
                        alert.setTitle("Confirmation Dialog");
                        alert.setContentText("Is this image Fake or Real ?");
                        ButtonType fakeButton = new ButtonType("Fake");
                        ButtonType realButton = new ButtonType("Real");
                        ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
                        alert.getButtonTypes().setAll(fakeButton, realButton, buttonTypeCancel);
                        Optional<ButtonType> result = alert.showAndWait();
                        if (result.get() == fakeButton) {
                            navigation_button.setText("Learning...");
                            SingleImageTrainer learner = new SingleImageTrainer(NeuralNetProcessor.nnet, elaImage, false);
                            learner.addListener(thisObject);
                            learner.setName("learner");
                            learner.start();
                        } else if (result.get() == realButton) {
                            navigation_button.setText("Learning...");
                            SingleImageTrainer learner = new SingleImageTrainer(NeuralNetProcessor.nnet, elaImage, true);
                            learner.addListener(thisObject);
                            learner.setName("learner");
                            learner.start();
                        } else {
                        }
                    }
                };
                snackbar.show("Isn't That Right ? Help Me Grow", "Okay", 10000, handler);
                addELAListener();
            }

            private void addELAListener() {
                navigation_button.setOnAction((e) -> {
                });
                navigation_button.setOnMousePressed(new EventHandler<MouseEvent>() {

                    @Override
                    public void handle(MouseEvent event) {
                        if (event.getButton() == MouseButton.PRIMARY) {
                            new ImagePlus("Error Level Analysis", elaImage).show();
                        } else if (event.getButton() == MouseButton.SECONDARY) {
                            try {
                                new ImagePlus("Original Image", ImageIO.read(LaunchScreeenController.processingFile)).show();
                            } catch (IOException ex) {
                                Logger.getLogger(NeuralnetInterfaceController.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                });
            }
        });
    }

    private void removeBannersandDescs() {
        TranslateTransition tChristopher = new TranslateTransition(Duration.millis(1000), christopher);
        TranslateTransition tDescription = new TranslateTransition(Duration.millis(1000), description);
        tChristopher.setToY(-500);
        tDescription.setToY(-500);
        ParallelTransition pt = new ParallelTransition(tChristopher, tDescription);
        pt.play();
    }

    @Override
    public void notifyOfThreadComplete(Thread thread) {

    }

    @Override
    public void elaCompleted(BufferedImage image) {
        updateIndicatorText("Serializing Image");
        elaImage = image;
        updateIndicatorText("Connecting to Neural Network");
        nprocessor = new NeuralNetProcessor(elaImage);
        nprocessor.setName("nprocessor");
        nprocessor.addListener(this);
        nprocessor.setListener(this);
        nprocessor.start();
        removeBannersandDescs();
    }

    @Override
    public void neuralnetProcessCompleted(HashMap<String, Double> result) {
        if (result == null) {
            Platform.runLater(new Runnable() {

                @Override
                public void run() {
                    Calert.showAlert("Forced Rollback", "Image Detection Failed:\nCorrupted File", AlertType.ERROR);
                    rollBack(null);
                    return;
                }
            });
        }
        bulgingTransition.stop();
        updateIndicatorText("Done");
        System.out.println("Neural net result:-\n" + result);
        loadResult(result);
    }
}


switch(item.getItemId()) {
            case android.R.id.home:
                AppUtils.navigateUp(this);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }

/*
 * All Rights Reserved.
 */
package me.zhanghai.android.materialratingbar.sample;

import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.MenuItem;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;

public class AboutActivity extends AppCompatActivity {

    @BindView(R.id.version)
    TextView mVersionText;

    @BindView(R.id.github)
    TextView mGithubText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.about_activity);
        ButterKnife.bind(this);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        String version = getString(R.string.about_version_format, BuildConfig.VERSION_NAME);
        mVersionText.setText(version);
        mGithubText.setMovementMethod(LinkMovementMethod.getInstance());
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {


switch(reason) {
            case NONE:
            case NATIVES:
                return null;
            default:
                break;
        }

/**
 *  This file is part of FreeCol.
 */
package net.sf.freecol.server.ai.mission;

import java.util.Comparator;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.stream.XMLStreamException;
import net.sf.freecol.common.io.FreeColXMLReader;
import net.sf.freecol.common.io.FreeColXMLWriter;
import net.sf.freecol.common.model.Colony;
import net.sf.freecol.common.model.Constants;
import net.sf.freecol.common.model.Location;
import net.sf.freecol.common.model.PathNode;
import net.sf.freecol.common.model.Player;
import net.sf.freecol.common.model.Tile;
import net.sf.freecol.common.model.Unit;
import net.sf.freecol.common.model.pathfinding.CostDecider;
import net.sf.freecol.common.model.pathfinding.CostDeciders;
import net.sf.freecol.common.model.pathfinding.GoalDecider;
import net.sf.freecol.common.model.pathfinding.GoalDeciders;
import static net.sf.freecol.common.util.CollectionUtils.*;
import net.sf.freecol.common.util.LogBuilder;
import static net.sf.freecol.common.util.RandomUtils.*;
import net.sf.freecol.server.ai.AIColony;
import net.sf.freecol.server.ai.AIMain;
import net.sf.freecol.server.ai.AIMessage;
import net.sf.freecol.server.ai.AIUnit;
import net.sf.freecol.server.ai.EuropeanAIPlayer;

/**
 * Mission for building a {@code Colony}.
 *
 * @see net.sf.freecol.common.model.Colony Colony
 */
public final class BuildColonyMission extends Mission {

    private static final Logger logger = Logger.getLogger(BuildColonyMission.class.getName());

    public static final String TAG = "buildColonyMission";

    private static final String tag = "AI colony builder";

    /**
     * The target of this mission.  It can either be a Tile where a
     * Colony should be built, or an existing connected Colony owned
     * by this player to go to before retargeting.
     */
    private Location target;

    /**
     * The value of a target {@code Tile}.
     */
    private int colonyValue;

    /**
     * Creates a mission for the given {@code AIUnit}.
     *
     * @param aiMain The main AI-object.
     * @param aiUnit The {@code AIUnit} this mission is created for.
     * @param target The target {@code Location} for this mission.
     */
    public BuildColonyMission(AIMain aiMain, AIUnit aiUnit, Location target) {
        super(aiMain, aiUnit);
        setTarget(target);
    }

    /**
     * Creates a new {@code BuildColonyMission} from a reader.
     *
     * @param aiMain The main AI-object.
     * @param aiUnit The {@code AIUnit} this mission is created for.
     * @param xr The input stream containing the XML.
     * @throws XMLStreamException if a problem was encountered during parsing.
     * @see net.sf.freecol.server.ai.AIObject#readFromXML
     */
    public BuildColonyMission(AIMain aiMain, AIUnit aiUnit, FreeColXMLReader xr) throws XMLStreamException {
        super(aiMain, aiUnit);
        readFromXML(xr);
    }

    /**
     * Get the colony value for a tile.
     *
     * @param tile The {@code Tile} to test.
     * @return The colony value for this player.
     */
    private int getColonyValue(Tile tile) {
        final Player owner = getAIUnit().getUnit().getOwner();
        return owner.getColonyValue(tile);
    }

    /**
     * Extract a valid target for this mission from a path.
     *
     * @param aiUnit A {@code AIUnit} to perform the mission.
     * @param path A {@code PathNode} to extract a target from,
     *     (uses the unit location if null).
     * @return A target for this mission, or null if none found.
     */
    public static Location extractTarget(AIUnit aiUnit, PathNode path) {
        if (path == null)
            return null;
        final Location loc = path.getLastNode().getLocation();
        Tile tile = loc.getTile();
        Colony colony = loc.getColony();
        return (invalidMissionReason(aiUnit, tile) == null) ? tile : (invalidMissionReason(aiUnit, colony) == null) ? colony : null;
    }

    /**
     * Gets the value of a path to a colony building site.
     *
     * @param aiUnit The {@code AIUnit} to build the colony.
     * @param path The {@code PathNode} to check.
     * @return A score for the target.
     */
    public static float scorePath(AIUnit aiUnit, PathNode path) {
        Location loc;
        if (path == null || !((loc = extractTarget(aiUnit, path)) instanceof Tile))
            return Integer.MIN_VALUE;
        final Tile tile = (Tile) loc;
        final Player player = aiUnit.getUnit().getOwner();
        float turns = path.getTotalTurns() + 1.0f;
        return player.getColonyValue(tile) / turns;
    }

    /**
     * Gets a {@code GoalDecider} for finding the best colony
     * {@code Tile}, optionally falling back to the nearest colony.
     *
     * @param aiUnit The {@code AIUnit} that is searching.
     * @param deferOK Enable colony fallback.
     * @return A suitable {@code GoalDecider}.
     */
    private static GoalDecider getGoalDecider(final AIUnit aiUnit, boolean deferOK) {
        GoalDecider gd = new GoalDecider() {

            private PathNode bestPath = null;

            private float bestValue = 0f;

            @Override
            public PathNode getGoal() {
                return bestPath;
            }

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

            @Override
            public boolean check(Unit u, PathNode path) {
                Location loc = extractTarget(aiUnit, path);
                if (loc instanceof Tile) {
                    float value = scorePath(aiUnit, path);
                    if (bestValue < value) {
                        bestValue = value;
                        bestPath = path;
                        return true;
                    }
                }
                return false;
            }
        };
        return (deferOK) ? GoalDeciders.getComposedGoalDecider(false, gd, GoalDeciders.getOurClosestSettlementGoalDecider()) : gd;
    }

    /**
     * Finds a site for a new colony.  Favour closer sites.
     *
     * @param aiUnit The {@code AIUnit} to execute this mission.
     * @param range An upper bound on the number of moves.
     * @param deferOK Enables deferring to a fallback colony.
     * @return A path to the new target, or null if none found.
     */
    private static PathNode findTargetPath(AIUnit aiUnit, int range, boolean deferOK) {
        if (invalidAIUnitReason(aiUnit) != null)
            return null;
        final Unit unit = aiUnit.getUnit();
        final Location start = unit.getPathStartLocation();
        final Unit carrier = unit.getCarrier();
        final GoalDecider gd = getGoalDecider(aiUnit, deferOK);
        final CostDecider standardCd = CostDeciders.avoidSettlementsAndBlockingUnits();
        // Try for something sensible nearby.
        return unit.search(start, gd, standardCd, range, carrier);
    }

    /**
     * Finds a site for a new colony or a backup colony to go to.
     *
     * @param aiUnit The {@code AIUnit} to find a colony site with.
     * @param range An upper bound on the number of moves.
     * @param deferOK Enables deferring to a fallback colony.
     * @return A new target for this mission.
     */
    public static Location findMissionTarget(AIUnit aiUnit, int range, boolean deferOK) {
        PathNode path = findTargetPath(aiUnit, range, deferOK);
        return (path != null) ? extractTarget(aiUnit, path) : Location.upLoc(findCircleTarget(aiUnit, getGoalDecider(aiUnit, deferOK), range * 3, deferOK));
    }

    /**
     * Why would this mission be invalid with the given unit?
     *
     * @param aiUnit The {@code AIUnit} to test.
     * @return A reason why the mission would be invalid with the unit,
     *     or null if none found.
     */
    private static String invalidUnitReason(AIUnit aiUnit) {
        String reason = invalidAIUnitReason(aiUnit);
        return (reason != null) ? reason : (!aiUnit.getUnit().getOwner().canBuildColonies()) ? "player-not-a-colony-founder" : (!aiUnit.getUnit().getType().canBuildColony()) ? "unit-not-a-colony-founder" : null;
    }

    /**
     * Why is this mission invalid with a given colony target?
     *
     * @param aiUnit The {@code AIUnit} to check.
     * @param colony The potential target {@code Colony}.
     * @return A reason for mission invalidity, or null if none found.
     */
    private static String invalidColonyReason(AIUnit aiUnit, Colony colony) {
        return invalidTargetReason(colony, aiUnit.getUnit().getOwner());
    }

    /**
     * Why is this mission invalid with a given tile target?
     *
     * @param aiUnit The {@code AIUnit} to check.
     * @param tile The potential target {@code Tile}.
     * @return A reason for mission invalidity, or null if none found.
     */
    private static String invalidTileReason(AIUnit aiUnit, Tile tile) {
        Player owner = aiUnit.getUnit().getOwner();
        Player.NoClaimReason reason = owner.canClaimToFoundSettlementReason(tile);

        return "target-" + reason;
    }

    /**
     * Why would this mission be invalid with the given AI unit?
     *
     * @param aiUnit The {@code AIUnit} to check.
     * @return A reason for mission invalidity, or null if none found.
     */
    public static String invalidMissionReason(AIUnit aiUnit) {
        return invalidUnitReason(aiUnit);
    }

    /**
     * Why would this mission be invalid with the given AI unit and location?
     *
     * @param aiUnit The {@code AIUnit} to check.
     * @param loc The {@code Location} to check.
     * @return A reason for invalidity, or null if none found.
     */
    public static String invalidMissionReason(AIUnit aiUnit, Location loc) {
        String reason = invalidMissionReason(aiUnit);
        return (reason != null) ? reason : (loc instanceof Colony) ? invalidColonyReason(aiUnit, (Colony) loc) : (loc instanceof Tile) ? invalidTileReason(aiUnit, (Tile) loc) : Mission.TARGETINVALID;
    }

    // Implement Mission
    // Inherit dispose, getTransportDestination, isOneTime
    @Override
    public int getBaseTransportPriority() {
        return NORMAL_TRANSPORT_PRIORITY + 10;
    }

    @Override
    public Location getTarget() {
        return target;
    }

    @Override
    public void setTarget(Location target) {
        if (target == null || target instanceof Colony || target instanceof Tile) {
            this.target = target;
            this.colonyValue = (target instanceof Tile) ? getColonyValue((Tile) target) : -1;
        }
    }

    @Override
    public Location findTarget() {
        return findMissionTarget(getAIUnit(), 5, true);
    }

    @Override
    public String invalidReason() {
        return invalidMissionReason(getAIUnit(), target);
    }

    @Override
    public Mission doMission(LogBuilder lb) {
        lb.add(tag);
        final AIMain aiMain = getAIMain();
        final AIUnit aiUnit = getAIUnit();
        final Unit unit = getUnit();
        final Player player = unit.getOwner();
        final EuropeanAIPlayer euaip = getEuropeanAIPlayer();
        boolean retarget = false;
        String reason = invalidReason();
        if (isTargetReason(reason)) {
            // Allow target invalidation by another builder succeeding, and
            // continue on to the target as an intermediate colony.
            Colony c;
            if (target instanceof Tile && (c = target.getColony()) != null && player.owns(c)) {
                // Favour improving colony center.
                Mission m = euaip.getPioneeringMission(aiUnit, c.getTile());
                if (m != null)
                    return lbDrop(lb, ", improving with ", m);
                // Just go to the colony.
                setTarget(c);
                return lbRetarget(lb);
            }
        } else if (reason != null) {
            return lbFail(lb, false, reason);
        } else {
            // Target valid, but has it devalued?
            if (target instanceof Tile) {
                int newValue = getColonyValue((Tile) target);
                if (newValue < colonyValue) {
                    reason = "target tile " + target.toShortString() + " value " + colonyValue + " -> " + newValue;
                    retarget = true;
                }
            }
        }
        if (retarget)
            return retargetMission(reason, lb);
        for (; ; ) {
            // Go there.
            Unit.MoveType mt = travelToTarget(getTarget(), CostDeciders.avoidSettlementsAndBlockingUnits(), lb);
            switch(mt) {
                case // Arrived
                MOVE:
                    break;
                case MOVE_HIGH_SEAS:
                case MOVE_NO_MOVES:
                case MOVE_ILLEGAL:
                    return lbWait(lb);
                case MOVE_NO_REPAIR:
                    return lbFail(lb, false, AIUNITDIED);
                case MOVE_NO_ACCESS_EMBARK:
                case MOVE_NO_TILE:
                    return this;
                default:
                    return lbMove(lb, mt);
            }
            lbAt(lb);
            if (getTarget() instanceof Colony) {
                // If arrived at the target colony it is time to retarget
                // another building site, unless the existing one is small
                // or nothing is found.
                Colony colony = (Colony) getTarget();
                // Improve colony center?
                Mission m = euaip.getPioneeringMission(aiUnit, colony.getTile());
                if (m != null)
                    return lbDrop(lb, ", improving with ", m);
                // Colony too small?
                if (colony.getUnitCount() <= 1) {
                    setTarget(colony);
                    return lbDrop(lb, ", join small colony");
                }
                // Find a real tile target?
                Location newTarget;
                if ((newTarget = findMissionTarget(aiUnit, 5, false)) != null) {
                    setTarget(newTarget);
                    return lbRetarget(lb);
                }
                // Go to the nearest smaller colony?
                final Predicate<Colony> smallPred = c -> c != colony && c.getUnitCount() < colony.getUnitCount();
                final Comparator<Colony> closeComp = cachingIntComparator(c -> unit.getTurnsToReach(c));
                Colony best = minimize(player.getColonies(), smallPred, closeComp);
                if (best != null) {
                    lb.add(", going to smaller ", best.getUnitCount(), "<", colony.getUnitCount(), " colony");
                    setTarget(best);
                    return lbRetarget(lb);
                }
                // Just join up then.
                return lbDrop(lb, ", joining");
            }
            if (!(getTarget() instanceof Tile)) {
                return lbFail(lb, false, "bogus target ", getTarget());
            }
            Tile tile = (Tile) getTarget();
            // Check that the unit has moves left, which are required
            if (unit.getMovesLeft() <= 0) {
                return lbWait(lb, ", waiting to build at ", tile);
            }
            if (tile.getOwner() == null) {
                // All is well
                ;
            } else if (player.owns(tile)) {
                // Already ours, clear users
                Colony colony = (Colony) tile.getOwningSettlement();
                if (colony != null) {
                    logger.warning("Building on colony tile: " + tile);
                    return lbFail(lb, false, "building on colony tile ", tile);
                }
            } else {
                // Not our tile, so claim it first.  Fail if someone
                // has claimed the tile and will not sell.  Otherwise
                // try to buy it or steal it.
                int price = player.getLandPrice(tile);
                boolean fail = price < 0;
                if (price > 0 && !player.checkGold(price)) {
                    if (randomInt(logger, "Land gold?", getAIRandom(), 4) == 0) {
                        lb.add(", ");
                        euaip.cheatGold(price, lb);
                        lb.add(" to buy ", tile);
                    }
                }
                if (price >= 0) {
                    fail = !AIMessage.askClaimLand(tile, aiUnit, ((price == 0) ? 0 : (player.checkGold(price)) ? price : Constants.STEAL_LAND)) || !player.owns(tile);
                }
                if (fail)
                    return retargetMission("tile-claim-at-" + tile, lb);
                lb.add(", claimed colony tile");
            }
            // Log the colony values so we can improve things
            if (logger.isLoggable(Level.FINE)) {
                LogBuilder l2 = new LogBuilder(64);
                l2.add(tag, " score-at-foundation ", tile, ":");
                for (Double d : player.getAllColonyValues(tile)) {
                    l2.add(" ", d);
                }
                l2.log(logger, Level.FINE);
            }
            // Clear to build the colony.
            if (AIMessage.askBuildColony(aiUnit, Player.ASSIGN_SETTLEMENT_NAME) && tile.getColony() != null) {
                Colony colony = tile.getColony();
                AIColony aiColony = aiMain.getAIColony(colony);
                aiColony.requestRearrange();
                Mission m = euaip.getWorkInsideColonyMission(aiUnit, aiColony);
                return lbDone(lb, m != null, colony);
            }
            return lbFail(lb, false, "build at ", tile);
        }
    }

    // Serialization
    private static final String TARGET_TAG = "target";

    @Override
    protected void writeAttributes(FreeColXMLWriter xw) throws XMLStreamException {
        super.writeAttributes(xw);
        if (target != null) {
            xw.writeAttribute(TARGET_TAG, target.getId());
            if (colonyValue > 0) {
                xw.writeAttribute(VALUE_TAG, colonyValue);
            }
        }
    }

    @Override
    protected void readAttributes(FreeColXMLReader xr) throws XMLStreamException {
        super.readAttributes(xr);
        target = xr.getLocationAttribute(getGame(), TARGET_TAG, false);
        colonyValue = xr.getAttribute(VALUE_TAG, -1);
    }

    @Override
    public String getXMLTagName() {
        return TAG;
    }
}


switch(tagType) {
            case TAG_COLOR_TRANSFORM:
                return getColorTransformDescription();
            case TAG_DCT_ENCODE_VERSION:
                return getDctEncodeVersionDescription();
            default:
                return super.getDescription(tagType);
        }

/*
 *
 *
 * More information about this project is available at:
 *
 *    http://example.com
 *    http://example.com
 */
package com.drew.metadata.adobe;

import com.drew.lang.annotations.Nullable;
import com.drew.metadata.TagDescriptor;
import static com.drew.metadata.adobe.AdobeJpegDirectory.*;

/**
 * Provides human-readable string versions of the tags stored in an AdobeJpegDirectory.
 */
@SuppressWarnings("WeakerAccess")
public class AdobeJpegDescriptor extends TagDescriptor<AdobeJpegDirectory> {

    public AdobeJpegDescriptor(AdobeJpegDirectory directory) {
        super(directory);
    }

    @Override
    public String getDescription(int tagType) {

    }

    @Nullable
    private String getDctEncodeVersionDescription() {
        Integer value = _directory.getInteger(TAG_DCT_ENCODE_VERSION);
        return value == null ? null : value == 0x64 ? "100" : Integer.toString(value);
    }

    @Nullable
    private String getColorTransformDescription() {
        return getIndexedDescription(TAG_COLOR_TRANSFORM, "Unknown (RGB or CMYK)", "YCbCr", "YCCK");
    }
}


switch(item.getItemId()) {
            case R.id.menu_source:
                // 调起浏览器更新app
                Intent intent = new Intent();
                intent.setAction("android.intent.action.VIEW");
                Uri url = Uri.parse("http://example.com");
                intent.setData(url);
                startActivity(intent);
                break;
        }

package com.rabtman.wsdemo;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ScrollingView;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.rabtman.wsmanager.WsManager;
import com.rabtman.wsmanager.listener.WsStatusListener;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import okio.ByteString;

public class MainActivity extends AppCompatActivity {

    private final static String TAG = "MainActivity";

    private WsManager wsManager;

    private TextView btn_send, btn_clear, tv_content;

    private Button btn_connect, btn_disconnect;

    private EditText edit_url, edit_content;

    private ScrollingView scrollingView;

    private WsStatusListener wsStatusListener = new WsStatusListener() {

        @Override
        public void onOpen(Response response) {
            Log.d(TAG, "WsManager-----onOpen");
            tv_content.append(Spanny.spanText("服务器连接成功\n\n", new ForegroundColorSpan(ContextCompat.getColor(getBaseContext(), R.color.colorPrimary))));
        }

        @Override
        public void onMessage(String text) {
            Log.d(TAG, "WsManager-----onMessage");
            tv_content.append(Spanny.spanText("服务器 " + DateUtils.formatDateTime(getBaseContext(), System.currentTimeMillis(), DateUtils.FORMAT_SHOW_TIME) + "\n", new ForegroundColorSpan(ContextCompat.getColor(getBaseContext(), R.color.colorPrimary))));
            tv_content.append(fromHtmlText(text) + "\n\n");
        }

        @Override
        public void onMessage(ByteString bytes) {
            Log.d(TAG, "WsManager-----onMessage");
        }

        @Override
        public void onReconnect() {
            Log.d(TAG, "WsManager-----onReconnect");
            tv_content.append(Spanny.spanText("服务器重连接中...\n", new ForegroundColorSpan(ContextCompat.getColor(getBaseContext(), android.R.color.holo_red_light))));
        }

        @Override
        public void onClosing(int code, String reason) {
            Log.d(TAG, "WsManager-----onClosing");
            tv_content.append(Spanny.spanText("服务器连接关闭中...\n", new ForegroundColorSpan(ContextCompat.getColor(getBaseContext(), android.R.color.holo_red_light))));
        }

        @Override
        public void onClosed(int code, String reason) {
            Log.d(TAG, "WsManager-----onClosed");
            tv_content.append(Spanny.spanText("服务器连接已关闭\n", new ForegroundColorSpan(ContextCompat.getColor(getBaseContext(), android.R.color.holo_red_light))));
        }

        @Override
        public void onFailure(Throwable t, Response response) {
            Log.d(TAG, "WsManager-----onFailure");
            tv_content.append(Spanny.spanText("服务器连接失败\n", new ForegroundColorSpan(ContextCompat.getColor(getBaseContext(), android.R.color.holo_red_light))));
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_send = (TextView) findViewById(R.id.btn_send);
        btn_clear = (TextView) findViewById(R.id.btn_clear);
        tv_content = (TextView) findViewById(R.id.tv_content);
        btn_connect = (Button) findViewById(R.id.btn_connect);
        btn_disconnect = (Button) findViewById(R.id.btn_disconnect);
        edit_url = (EditText) findViewById(R.id.edit_url);
        edit_content = (EditText) findViewById(R.id.edit_content);
        btn_connect.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                String url = edit_url.getText().toString();
                if (!TextUtils.isEmpty(url) && url.contains("ws")) {
                    if (wsManager != null) {
                        wsManager.stopConnect();
                        wsManager = null;
                    }
                    wsManager = new WsManager.Builder(getBaseContext()).client(new OkHttpClient().newBuilder().pingInterval(15, TimeUnit.SECONDS).retryOnConnectionFailure(true).build()).needReconnect(true).wsUrl(url).build();
                    wsManager.setWsStatusListener(wsStatusListener);
                    wsManager.startConnect();
                } else {
                    Toast.makeText(getBaseContext(), "请填写需要链接的地址", Toast.LENGTH_SHORT).show();
                }
            }
        });
        btn_disconnect.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (wsManager != null) {
                    wsManager.stopConnect();
                    wsManager = null;
                }
            }
        });
        btn_send.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                String content = edit_content.getText().toString();
                if (!TextUtils.isEmpty(content)) {
                    if (wsManager != null && wsManager.isWsConnected()) {
                        boolean isSend = wsManager.sendMessage(content);
                        if (isSend) {
                            tv_content.append(Spanny.spanText("我 " + DateUtils.formatDateTime(getBaseContext(), System.currentTimeMillis(), DateUtils.FORMAT_SHOW_TIME) + "\n", new ForegroundColorSpan(ContextCompat.getColor(getBaseContext(), android.R.color.holo_green_light))));
                            tv_content.append(content + "\n\n");
                        } else {
                            tv_content.append(Spanny.spanText("消息发送失败\n", new ForegroundColorSpan(ContextCompat.getColor(getBaseContext(), android.R.color.holo_red_light))));
                        }
                        showOrHideInputMethod();
                        edit_content.setText("");
                    } else {
                        Toast.makeText(getBaseContext(), "请先连接服务器", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Toast.makeText(getBaseContext(), "请填写需要发送的内容", Toast.LENGTH_SHORT).show();
                }
            }
        });
        btn_clear.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                tv_content.setText("");
            }
        });
    }

    @Override
    protected void onDestroy() {
        if (wsManager != null) {
            wsManager.stopConnect();
            wsManager = null;
        }
        super.onDestroy();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        return super.onOptionsItemSelected(item);
    }

    private Spanned fromHtmlText(String s) {
        Spanned result;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            result = Html.fromHtml(s, Html.FROM_HTML_MODE_LEGACY);
        } else {
            result = Html.fromHtml(s);
        }
        return result;
    }

    private void showOrHideInputMethod() {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
    }
}


switch(ce.getStatusCode()) {
                case 404:
                    // not found: _bulk_get not supported
                    return false;
                case 405:
                    // method not allowed: this endpoint exists, we called with the wrong method
                    return true;
                default:
                    // will re-throw with this as cause since we didn't understand the result
                    cause = ce;
            }

package com.cloudant.sync.internal.mazha;

import com.cloudant.http.Http;
import com.cloudant.http.HttpConnection;
import com.cloudant.http.HttpConnectionRequestInterceptor;
import com.cloudant.http.HttpConnectionResponseInterceptor;
import com.cloudant.http.internal.interceptors.SSLCustomizerInterceptor;
import com.cloudant.http.internal.interceptors.UserAgentInterceptor;
import com.cloudant.sync.internal.common.RetriableTask;
import com.cloudant.sync.internal.documentstore.DocumentRevsList;
import com.cloudant.sync.internal.documentstore.MultipartAttachmentWriter;
import com.cloudant.sync.internal.util.JSONUtils;
import com.cloudant.sync.internal.util.Misc;
import com.cloudant.sync.replication.PullFilter;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URI;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class CouchClient {

    public static final List<HttpConnectionRequestInterceptor> DEFAULT_REQUEST_INTERCEPTORS;

    // Set up the defaults
    static {
        HttpConnectionRequestInterceptor ua_interceptor = new UserAgentInterceptor(CouchClient.class.getClassLoader(), "META-INF/com.cloudant.sync.client.properties");
        HttpConnectionRequestInterceptor tlsInterceptor = checkAndGetTlsInterceptor();
        DEFAULT_REQUEST_INTERCEPTORS = (tlsInterceptor != null) ? Arrays.asList(ua_interceptor, tlsInterceptor) : Collections.singletonList(ua_interceptor);
    }

    private CouchURIHelper uriHelper;

    private List<HttpConnectionRequestInterceptor> requestInterceptors;

    private List<HttpConnectionResponseInterceptor> responseInterceptors;

    private final static Logger logger = Logger.getLogger(RetriableTask.class.getCanonicalName());

    public CouchClient(URI rootUri, List<HttpConnectionRequestInterceptor> requestInterceptors, List<HttpConnectionResponseInterceptor> responseInterceptors) {
        this.uriHelper = new CouchURIHelper(rootUri);
        this.requestInterceptors = new ArrayList<HttpConnectionRequestInterceptor>();
        this.responseInterceptors = new ArrayList<HttpConnectionResponseInterceptor>();
        this.requestInterceptors.addAll(DEFAULT_REQUEST_INTERCEPTORS);
        if (requestInterceptors != null) {
            this.requestInterceptors.addAll(requestInterceptors);
        }
        if (responseInterceptors != null) {
            this.responseInterceptors.addAll(responseInterceptors);
        }
    }

    private static SSLCustomizerInterceptor checkAndGetTlsInterceptor() {
        // Some assistance for TLSv1.2 support. Two things we check before we try to force TLSv1.2
        // so that we don't interfere with any other custom configuration that may have been
        // i) are we running on Android, and an old version of Android (api level < 20 does not
        // ii) does the default SSLContext have TLSv1.2 enabled or available
        if (Misc.isRunningOnAndroid()) {
            // This block catches all exceptions from TLSv1.2 checks, if we get exceptions we bail
            // with a RuntimeException
            try {
                // Get the API level reflectively so we don't need to import classes only available
                // in Android
                int androidApiLevel = Class.forName("android.os.Build$VERSION").getField("SDK_INT").getInt(null);
                // If we are on an old version of Android and TLSv1.2 has not been enabled already
                // on the default context then we add a special interceptor
                if (androidApiLevel < 20) {
                    // Check i has passed we are on an old version of Android
                    // Get the default SSLContext
                    SSLContext defSslCtx = SSLContext.getDefault();
                    if (!Arrays.asList(defSslCtx.getDefaultSSLParameters().getProtocols()).contains(TlsOnlySslSocketFactory.TLSv12) && Arrays.asList(defSslCtx.getSupportedSSLParameters().getProtocols()).contains(TlsOnlySslSocketFactory.TLSv12)) {
                        // Check ii has passed TLSv1.2 is not already enabled on the default context
                        // but is supported on the default context so we can use it
                        // In an ideal world we would also check the default SSLSocketFactory that
                        // is set on the HttpsUrlConnection to see if that has been customized from
                        // the default, but there isn't really a way to check this, equals is not
                        // overridden on the SSLSocketFactory and there is no route back to the
                        // SSLContext that generated the SSLSocketFactory.
                        SSLContext sc = SSLContext.getInstance(TlsOnlySslSocketFactory.TLSv12);
                        sc.init(null, null, null);
                        // We add this interceptor, but it could be overridden by a later user
                        // provided interceptor, so this shouldn't change anyone's existing
                        SSLSocketFactory s = sc.getSocketFactory();
                        return new SSLCustomizerInterceptor(new TlsOnlySslSocketFactory(s));
                    }
                }
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            } catch (KeyManagementException e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }

    private static final class TlsOnlySslSocketFactory extends SSLSocketFactory {

        private static final String TLSv12 = "TLSv1.2";

        private static final String[] TLSv12Only = new String[] { TLSv12 };

        private final SSLSocketFactory delegate;

        private TlsOnlySslSocketFactory(SSLSocketFactory delegate) {
            this.delegate = delegate;
        }

        @Override
        public String[] getDefaultCipherSuites() {
            return delegate.getDefaultCipherSuites();
        }

        @Override
        public String[] getSupportedCipherSuites() {
            return delegate.getSupportedCipherSuites();
        }

        @Override
        public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException {
            return tlsOnlySocket(delegate.createSocket(socket, s, i, b));
        }

        @Override
        public Socket createSocket(String s, int i) throws IOException {
            return tlsOnlySocket(delegate.createSocket(s, i));
        }

        @Override
        public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException {
            return tlsOnlySocket(delegate.createSocket(s, i, inetAddress, i1));
        }

        @Override
        public Socket createSocket(InetAddress inetAddress, int i) throws IOException {
            return tlsOnlySocket(delegate.createSocket(inetAddress, i));
        }

        @Override
        public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException {
            return tlsOnlySocket(delegate.createSocket(inetAddress, i, inetAddress1, i1));
        }

        private Socket tlsOnlySocket(Socket s) {
            if (s instanceof SSLSocket) {
                ((SSLSocket) s).setEnabledProtocols(TLSv12Only);
            }
            return s;
        }
    }

    public URI getRootUri() {
        return this.uriHelper.getRootUri();
    }

    // result of executing an HTTP call:
    // - stream non-null and exception null: the call was successful, result in stream
    // - stream null and exception non-null: the call was unsuccessful, details in exception
    // - fatal: set to true when exception non-null, indicates call should not be retried
    private static class ExecuteResult {

        private ExecuteResult(InputStream stream, InputStream errorStream, int responseCode, String responseMessage, Throwable cause) {
            boolean needsCouchException = false;
            switch(responseCode / 100) {
                case 1:
                case 2:
                    // 1xx and 2xx are OK
                    // we would not normally expect to see 1xx in a response
                    // explicitly set these to show we are OK
                    this.fatal = false;
                    this.exception = null;
                    this.stream = stream;
                    break;
                case 3:
                    // 3xx redirection
                    throw new CouchException("Unexpected redirection (3xx) code encountered", responseCode);
                case 4:
                    // 4xx errors normally mean we are not authenticated so we shouldn't retry
                    this.fatal = true;
                    if (responseCode == 404) {
                        this.exception = new NoResourceException(responseMessage, cause);
                    } else if (responseCode == 409) {
                        this.exception = new DocumentConflictException(responseMessage);
                    } else {
                        needsCouchException = true;
                    }
                    break;
                case 5:
                    // 5xx errors are transient server errors so we should retry
                    this.fatal = false;
                    needsCouchException = true;
                    break;
                default:
                    // couldn't get response code
                    // something bad happened but we should retry (timeouts, socket closed etc)
                    this.fatal = false;
                    needsCouchException = true;
            }
            if (needsCouchException) {
                try {
                    Map<String, String> json = JSONUtils.fromJson(new InputStreamReader(errorStream, Charset.forName("UTF-8")), Map.class);
                    CouchException ce = new CouchException(responseMessage, cause, responseCode);
                    ce.setError(json.get("error"));
                    ce.setReason(json.get("reason"));
                    this.exception = ce;
                } catch (Exception e) {
                    CouchException ce = new CouchException("Error deserializing server response", cause, responseCode);
                    this.exception = ce;
                }
            }
        }

        InputStream stream;

        CouchException exception;

        boolean fatal;
    }

    // - map 404 to NoResourceException
    // - if there's a couch error returned as json, un-marshall and throw
    // - anything else, just throw the IOException back, use the cause part of the exception?
    // it needs to catch eg FileNotFoundException and rethrow to emulate the previous exception
    // handling behaviour
    private ExecuteResult execute(HttpConnection connection) {
        // input stream - response from server on success
        InputStream inputStream = null;
        // error stream - response from server for a 500 etc
        InputStream errorStream = null;
        String responseMessage = null;
        int responseCode = -1;
        Throwable cause = null;
        // first try to execute our request and get the input stream with the server's response
        // we want to catch IOException because HttpUrlConnection throws these for non-success
        // responses (eg 404 throws a FileNotFoundException) but we need to map to our own
        // specific exceptions
        try {
            inputStream = connection.execute().responseAsInputStream();
        } catch (IOException ioe) {
            cause = ioe;
        }
        // response code and message will generally be present together or not all
        try {
            responseCode = connection.getConnection().getResponseCode();
            responseMessage = connection.getConnection().getResponseMessage();
        } catch (IOException ioe) {
            responseMessage = "Error retrieving server response message";
        }
        // error stream will be present or null if not applicable
        errorStream = connection.getConnection().getErrorStream();
        try {
            ExecuteResult executeResult = new ExecuteResult(inputStream, errorStream, responseCode, responseMessage, cause);
            return executeResult;
        } finally {
            // don't close inputStream as the callee still needs it
            IOUtils.closeQuietly(errorStream);
        }
    }

    // execute HTTP task with retries:
    // return an InputStream if successful or throw an exception
    private <T> T executeWithRetry(final Callable<ExecuteResult> task, InputStreamProcessor<T> processor) throws CouchException {
        int attempts = 10;
        CouchException lastException = null;
        while (attempts-- > 0) {
            ExecuteResult result = null;
            try {
                result = task.call();
                if (result.stream != null) {
                    // success - process the inputstream
                    try {
                        return processor.processStream(result.stream);
                    } catch (Exception e) {
                        // Error processing the input stream
                        if (attempts > 0) {
                            logger.log(Level.WARNING, "Received an exception during response " + "stream processing. A retry will be attempted.", e);
                        } else {
                            logger.log(Level.SEVERE, "Response stream processing failed, no " + "retries remaining.", e);
                            throw e;
                        }
                    } finally {
                        result.stream.close();
                    }
                }
            } catch (Exception e) {
                throw new CouchException("Unexpected exception", e, -1);
            }
            lastException = result.exception;
            if (result.fatal) {
                // fatal exception - don't attempt any more retries
                throw result.exception;
            }
        }
        throw lastException;
    }

    private <T> T executeToJsonObjectWithRetry(final HttpConnection connection, final TypeReference<T> type) throws CouchException {
        return executeWithRetry(connection, new TypeInputStreamProcessor<T>(type));
    }

    private <T> T executeToJsonObjectWithRetry(final HttpConnection connection, Class<T> c) throws CouchException {
        return executeToJsonObjectWithRetry(connection, new CouchClientTypeReference<T>(c));
    }

    private <T> T executeWithRetry(final HttpConnection connection, InputStreamProcessor<T> processor) throws CouchException {
        // all CouchClient requests want to receive application/json responses
        connection.requestProperties.put("Accept", "application/json");
        connection.responseInterceptors.addAll(responseInterceptors);
        connection.requestInterceptors.addAll(requestInterceptors);
        return this.executeWithRetry(new Callable<ExecuteResult>() {

            @Override
            public ExecuteResult call() throws Exception {
                return execute(connection);
            }
        }, processor);
    }

    public void createDb() {
        HttpConnection connection = Http.PUT(uriHelper.getRootUri(), "application/json");
        executeToJsonObjectWithRetry(connection, DBOperationResponse.class);
    }

    public void deleteDb() {
        HttpConnection connection = Http.DELETE(this.uriHelper.getRootUri());
        executeToJsonObjectWithRetry(connection, DBOperationResponse.class);
    }

    public CouchDbInfo getDbInfo() {
        HttpConnection connection = Http.GET(uriHelper.getRootUri());
        return executeToJsonObjectWithRetry(connection, CouchDbInfo.class);
    }

    private Map<String, Object> getDefaultChangeFeedOptions() {
        Map<String, Object> options = new HashMap<String, Object>();
        options.put("style", "all_docs");
        options.put("feed", "normal");
        return options;
    }

    private Map<String, Object> getParametrizedChangeFeedOptions(Object since, Integer limit) {
        Map<String, Object> options = getDefaultChangeFeedOptions();
        if (since != null) {
            options.put("since", since);
        }
        if (limit != null) {
            options.put("limit", limit);
        }
        // seq_interval: improve performance and reduce load on the remote database
        if (limit != null) {
            options.put("seq_interval", limit);
        } else {
            options.put("seq_interval", 1000);
        }
        return options;
    }

    public ChangesResult changes(Object since, Integer limit) {
        Map<String, Object> options = getParametrizedChangeFeedOptions(since, limit);
        return this.changesRequestWithGet(options);
    }

    public ChangesResult changes(PullFilter filter, Object since, Integer limit) {
        Map<String, Object> options = getParametrizedChangeFeedOptions(since, limit);
        if (filter != null) {
            String filterName = filter.getName();
            Map filterParameters = filter.getParameters();
            if (filterName != null) {
                options.put("filter", filterName);
                if (filterParameters != null) {
                    options.putAll(filterParameters);
                }
            }
        }
        return this.changesRequestWithGet(options);
    }

    public ChangesResult changes(String selector, Object since, Integer limit) {
        Misc.checkNotNullOrEmpty(selector, null);
        Map<String, Object> options = getParametrizedChangeFeedOptions(since, limit);
        options.put("filter", "_selector");
        return changesRequestWithPost(selector, options);
    }

    public ChangesResult changes(List<String> docIds, Object since, Integer limit) {
        Misc.checkState((docIds != null && !docIds.isEmpty()), null);
        Map<String, Object> options = getParametrizedChangeFeedOptions(since, limit);
        options.put("filter", "_doc_ids");
        Map<String, Object> docIdsMap = new HashMap<String, Object>();
        docIdsMap.put("doc_ids", docIds);
        String docsIdsDoc = JSONUtils.serializeAsString(docIdsMap);
        return changesRequestWithPost(docsIdsDoc, options);
    }

    private ChangesResult changesRequestWithGet(final Map<String, Object> options) {
        URI changesFeedUri = uriHelper.changesUri(options);
        HttpConnection connection = Http.GET(changesFeedUri);
        return executeToJsonObjectWithRetry(connection, ChangesResult.class);
    }

    private ChangesResult changesRequestWithPost(String body, final Map<String, Object> options) {
        URI changesFeedUri = uriHelper.changesUri(options);
        HttpConnection connection = Http.POST(changesFeedUri, "application/json");
        connection.setRequestBody(body);
        return executeToJsonObjectWithRetry(connection, ChangesResult.class);
    }

    // TODO does this still work the same way we expect it to?
    public boolean contains(String id) {
        Misc.checkNotNullOrEmpty(id, "id");
        try {
            getDocumentRev(id);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public Response create(Object document) {
        String json = JSONUtils.toJson(document);
        InputStream is = null;
        try {
            HttpConnection connection = Http.POST(this.uriHelper.getRootUri(), "application/json");
            connection.setRequestBody(json);
            Response res = executeToJsonObjectWithRetry(connection, Response.class);
            if (!res.getOk()) {
                throw new ServerException(res.toString());
            } else {
                return res;
            }
        } catch (CouchException e) {
            if (e.getStatusCode() == 409) {
                throw new DocumentConflictException(e.toString());
            } else {
                throw e;
            }
        }
    }

    public <T> T processAttachmentStream(String id, String rev, String attachmentName, final boolean acceptGzip, InputStreamProcessor<T> processor) {
        Misc.checkNotNullOrEmpty(id, "id");
        Misc.checkNotNullOrEmpty(rev, "rev");
        Map<String, Object> queries = new HashMap<String, Object>();
        queries.put("rev", rev);
        final URI doc = this.uriHelper.attachmentUri(id, queries, attachmentName);
        HttpConnection connection = Http.GET(doc);
        if (acceptGzip) {
            connection.requestProperties.put("Accept-Encoding", "gzip");
        }
        return executeWithRetry(connection, processor);
    }

    public void putAttachmentStream(String id, String rev, String attachmentName, String contentType, byte[] attachmentData) {
        Misc.checkNotNullOrEmpty(id, "id");
        Misc.checkNotNullOrEmpty(rev, "rev");
        Map<String, Object> queries = new HashMap<String, Object>();
        queries.put("rev", rev);
        URI doc = this.uriHelper.attachmentUri(id, queries, attachmentName);
        HttpConnection connection = Http.PUT(doc, contentType);
        connection.setRequestBody(attachmentData);
        // TODO check result?
        executeToJsonObjectWithRetry(connection, Response.class);
    }

    /**
     * Convenience method to get document with all the conflicts revisions. It does that by adding
     * "conflicts=true" option to the GET request. An example response JSON is the following:
     * {
     * "_id" : "c3fe5bfdee767fa3d51717bb8b51d55b",
     * "_rev" : "3-176c3c8b3f284d4fa6e8c075d58b7b86",
     * "hello" : "world",
     * "name" : "Tom",
     * "_conflicts" : [
     *   "2-d9789a01da0c41aeb3d86ff039f461f6",
     *   "2-65ddd7d56da84f25af544e84a3267ccf" ]
     * }
     */
    public Map<String, Object> getDocConflictRevs(String id) {
        Map<String, Object> options = new HashMap<String, Object>();
        options.put("conflicts", true);
        return this.getDocument(id, options, JSONUtils.STRING_MAP_TYPE_DEF);
    }

    /**
     * Convenience method to get document with revision history for a given list of open
     * revisions. It does that by
     * adding "open_revs=["rev1", "rev2"]" option to the GET request.
     *
     * It must return a list because that is how CouchDB return its results.
     */
    public List<OpenRevision> getDocWithOpenRevisions(String id, Collection<String> revisions, Collection<String> attsSince, boolean pullAttachmentsInline) {
        Misc.checkNotNullOrEmpty(id, "id");
        Misc.checkArgument(revisions.size() > 0, "Need at least one open revision");
        Map<String, Object> options = new HashMap<String, Object>();
        options.put("revs", true);
        // by adding latest we should never receive a "missing" response from the server. A descendant
        // of the revision requested will be returned even if it has been deleted.
        options.put("latest", true);
        // only pull attachments inline if we're configured to
        if (pullAttachmentsInline) {
            options.put("attachments", true);
            if (attsSince != null) {
                options.put("atts_since", JSONUtils.toJson(attsSince));
            }
        } else {
            options.put("attachments", false);
            options.put("att_encoding_info", true);
        }
        options.put("open_revs", JSONUtils.toJson(revisions));
        return this.getDocument(id, options, JSONUtils.OPEN_REVS_LIST_TYPE_DEF);
    }

    /**
     * <p>
     * Return an iterator representing the result of calling the _bulk_docs endpoint.
     * </p>
     * <p>
     * Each time the iterator is advanced, a DocumentRevsList is returned, which represents the
     * leaf nodes and their ancestries for a given document ID.
     * </p>
     *
     * @param request               A request for 1 or more (ID,rev) pairs.
     * @param pullAttachmentsInline If true, retrieve attachments as inline base64
     * @return An iterator representing the result of calling the _bulk_docs endpoint.
     */
    public Iterable<DocumentRevsList> bulkReadDocsWithOpenRevisions(List<BulkGetRequest> request, boolean pullAttachmentsInline) {
        Map<String, Object> options = new HashMap<String, Object>();
        options.put("revs", true);
        options.put("latest", true);
        if (pullAttachmentsInline) {
            options.put("attachments", true);
        } else {
            options.put("attachments", false);
            options.put("att_encoding_info", true);
        }
        URI bulkGet = this.uriHelper.documentUri("_bulk_get", options);
        HttpConnection connection = Http.POST(bulkGet, "application/json");
        Map<String, List<BulkGetRequest>> jsonRequest = new HashMap<String, List<BulkGetRequest>>();
        jsonRequest.put("docs", request);
        // build request
        connection.setRequestBody(JSONUtils.toJson(jsonRequest));
        // deserialise response
        BulkGetResponse response = executeToJsonObjectWithRetry(connection, BulkGetResponse.class);
        Map<String, ArrayList<DocumentRevs>> revsMap = new HashMap<String, ArrayList<DocumentRevs>>();
        // merge results back in, so there is one list of DocumentRevs per ID
        for (BulkGetResponse.Result result : response.results) {
            for (BulkGetResponse.Doc doc : result.docs) {
                if (doc.ok != null) {
                    String id = doc.ok.getId();
                    if (!revsMap.containsKey(id)) {
                        revsMap.put(id, new ArrayList<DocumentRevs>());
                    }
                    revsMap.get(id).add(doc.ok);
                }
            }
        }
        List<DocumentRevsList> allRevs = new ArrayList<DocumentRevsList>();
        // flatten out revsMap hash so that there is one entry in our return array for each ID
        for (ArrayList<DocumentRevs> value : revsMap.values()) {
            allRevs.add(new DocumentRevsList(value));
        }
        return allRevs;
    }

    public Map<String, Object> getDocument(String id) {
        return this.getDocument(id, new HashMap<String, Object>(), JSONUtils.STRING_MAP_TYPE_DEF);
    }

    public <T> T getDocument(String id, final Class<T> type) {
        return this.getDocument(id, new HashMap<String, Object>(), new CouchClientTypeReference<T>(type));
    }

    public <T> T getDocument(final String id, final Map<String, Object> options, final TypeReference<T> type) {
        Misc.checkNotNullOrEmpty(id, "id");
        Misc.checkNotNull(type, "Type");
        URI doc = uriHelper.documentUri(id, options);
        HttpConnection connection = Http.GET(doc);
        T returndoc = executeToJsonObjectWithRetry(connection, type);
        logger.fine("get returning " + returndoc);
        return returndoc;
    }

    public Map<String, Object> getDocument(String id, String rev) {
        return getDocument(id, rev, JSONUtils.STRING_MAP_TYPE_DEF);
    }

    public <T> T getDocument(String id, String rev, TypeReference<T> type) {
        Misc.checkNotNullOrEmpty(id, "id");
        Misc.checkNotNullOrEmpty(rev, "rev");
        Misc.checkNotNull(type, "Type");
        Map<String, Object> queries = new HashMap<String, Object>();
        queries.put("rev", rev);
        final URI doc = this.uriHelper.documentUri(id, queries);
        HttpConnection connection = Http.GET(doc);
        T returndoc = executeToJsonObjectWithRetry(connection, type);
        logger.fine("get returning " + returndoc);
        return returndoc;
    }

    public <T> T getDocument(String id, String rev, final Class<T> type) {
        return getDocument(id, rev, new CouchClientTypeReference<T>(type));
    }

    /**
     * Get document along with its revision history, and the result is converted to a
     * <code>DocumentRevs</code> object.
     *
     * @see <code>DocumentRevs</code>
     */
    public DocumentRevs getDocRevisions(String id, String rev) {
        return getDocRevisions(id, rev, new CouchClientTypeReference<DocumentRevs>(DocumentRevs.class));
    }

    public <T> T getDocRevisions(String id, String rev, TypeReference<T> type) {
        Misc.checkNotNullOrEmpty(id, "id");
        Misc.checkNotNull(rev, "Revision ID");
        Map<String, Object> queries = new HashMap<String, Object>();
        queries.put("revs", "true");
        queries.put("rev", rev);
        URI findRevs = this.uriHelper.documentUri(id, queries);
        HttpConnection connection = Http.GET(findRevs);
        return executeToJsonObjectWithRetry(connection, type);
    }

    // Document should be complete document include "_id" matches ID
    public Response update(String id, Object document) {
        Misc.checkNotNullOrEmpty(id, "id");
        Misc.checkNotNull(document, "Document");
        // Get the latest rev, will throw if doc doesn't exist
        getDocumentRev(id);
        return putUpdate(id, document);
    }

    public Response putUpdate(String id, Object document) {
        Misc.checkNotNullOrEmpty(id, "id");
        Misc.checkNotNull(document, "Document");
        URI doc = this.uriHelper.documentUri(id);
        String json = JSONUtils.toJson(document);
        HttpConnection connection = Http.PUT(doc, "application/json");
        connection.setRequestBody(json);
        Response r = executeToJsonObjectWithRetry(connection, Response.class);
        return r;
    }

    public String getDocumentRev(String id) {
        URI doc = this.uriHelper.documentUri(id);
        HttpConnection head = Http.HEAD(doc);
        executeWithRetry(head, new NoOpInputStreamProcessor());
        String rev = head.getConnection().getHeaderField("ETag");
        // Remove enclosing "" before returning
        return rev.substring(1, rev.length() - 1);
    }

    public Response delete(String id, String rev) {
        Misc.checkNotNullOrEmpty(id, "id");
        Misc.checkNotNullOrEmpty(rev, "rev");
        Map<String, Object> queries = new HashMap<String, Object>();
        queries.put("rev", rev);
        URI doc = this.uriHelper.documentUri(id, queries);
        HttpConnection connection = Http.DELETE(doc);
        return executeToJsonObjectWithRetry(connection, Response.class);
    }

    public List<Response> bulkCreateDocs(Object... objects) {
        return bulkCreateDocs(Arrays.asList(objects));
    }

    public List<Response> bulkCreateDocs(List<?> objects) {
        Misc.checkNotNull(objects, "Object list");
        String newEditsVal = "\"new_edits\": false, ";
        String payload = String.format("{%s%s%s}", newEditsVal, "\"docs\": ", JSONUtils.toJson(objects));
        return bulkCreateDocs(payload);
    }

    private List<Response> bulkCreateDocs(String payload) {
        URI uri = this.uriHelper.bulkDocsUri();
        HttpConnection connection = Http.POST(uri, "application/json");
        connection.setRequestBody(payload);
        return executeToJsonObjectWithRetry(connection, new CouchClientTypeReference<List<Response>>());
    }

    /**
     * Bulk insert a list of document that are serialized to JSON data already. For performance reasons,
     * the JSON doc is not validated.
     *
     * @param serializedDocs array of JSON documents
     * @return list of Response
     */
    public List<Response> bulkCreateSerializedDocs(String... serializedDocs) {
        return bulkCreateSerializedDocs(Arrays.asList(serializedDocs));
    }

    /**
     * Bulk insert a list of document that are serialized to JSON data already. For performance
     * reasons,
     * the JSON doc is not validated.
     *
     * @param serializedDocs list of JSON documents
     * @return list of Response
     */
    public List<Response> bulkCreateSerializedDocs(List<String> serializedDocs) {
        Misc.checkNotNull(serializedDocs, "Serialized doc list");
        String payload = generateBulkSerializedDocsPayload(serializedDocs);
        return bulkCreateDocs(payload);
    }

    private String generateBulkSerializedDocsPayload(List<String> serializedDocs) {
        String newEditsVal = "\"new_edits\": false, ";
        StringBuilder sb = new StringBuilder("[");
        for (String doc : serializedDocs) {
            if (sb.length() > 1) {
                sb.append(", ");
            }
            sb.append(doc);
        }
        sb.append("]");
        return String.format("{%s%s%s}", newEditsVal, "\"docs\": ", sb.toString());
    }

    /**
     * Returns the subset of given the documentId/revisions that are not stored in the database.
     *
     * The input revisions is a map, whose key is document ID, and value is a list of revisions.
     * An example input could be (in JSON format):
     *
     * { "03ee06461a12f3c288bb865b22000170":
     *     [
     *       "1-b2e54331db828310f3c772d6e042ac9c",
     *       "2-3a24009a9525bde9e4bfa8a99046b00d"
     *     ],
     *   "82e04f650661c9bdb88c57e044000a4b":
     *     [
     *       "3-bb39f8c740c6ffb8614c7031b46ac162"
     *     ]
     * }
     *
     * The output is in same format.
     *
     * If the ID has no missing revision, it should not appear in the Map's key set. If all IDs
     * do not have missing revisions, the returned Map should be empty map, but never null.
     *
     * @see
     * <a target="_blank" href="http://example.com">HttpPostRevsDiff
     * documentation</a>
     */
    public Map<String, MissingRevisions> revsDiff(Map<String, Set<String>> revisions) {
        Misc.checkNotNull(revisions, "Input revisions");
        URI uri = this.uriHelper.revsDiffUri();
        String payload = JSONUtils.toJson(revisions);
        HttpConnection connection = Http.POST(uri, "application/json");
        connection.setRequestBody(payload);
        return executeToJsonObjectWithRetry(connection, JSONUtils.STRING_MISSING_REVS_MAP_TYPE_DEF);
    }

    public Response putMultipart(final MultipartAttachmentWriter mpw) {
        Map<String, Object> options = new HashMap<String, Object>();
        options.put("new_edits", "false");
        URI uri = this.uriHelper.documentUri(mpw.getId(), options);
        String contentType = "multipart/related;boundary=" + mpw.getBoundary();
        HttpConnection connection = Http.PUT(uri, contentType);
        connection.setRequestBody(mpw.makeInputStreamGenerator(), mpw.getContentLength());
        return executeToJsonObjectWithRetry(connection, Response.class);
    }

    public boolean isBulkSupported() {
        URI bulkGet = this.uriHelper.documentUri("_bulk_get");
        HttpConnection get = Http.GET(bulkGet);
        Throwable cause = null;
        try {
            executeWithRetry(get, new NoOpInputStreamProcessor());
        } catch (CouchException ce) {

        }
        // if we got here, we either ran out of retries or couldn't figure out the response code
        // so all we can do is throw an exception
        throw new RuntimeException("Could not determine if the _bulk_get endpoint is supported", cause);
    }

    public static class MissingRevisions {

        public Set<String> possible_ancestors;

        public Set<String> missing;
    }

    public interface InputStreamProcessor<T> {

        T processStream(InputStream stream) throws Exception;
    }

    private static class CouchClientTypeReference<T> extends TypeReference<T> {

        private Class<T> type;

        CouchClientTypeReference() {
            this(null);
        }

        CouchClientTypeReference(Class<T> type) {
            this.type = type;
        }

        @Override
        public Type getType() {
            if (this.type == null) {
                return super.getType();
            } else {
                return this.type;
            }
        }
    }

    private static final class TypeInputStreamProcessor<T> implements InputStreamProcessor<T> {

        private final TypeReference<T> typeReference;

        TypeInputStreamProcessor(TypeReference<T> typeReference) {
            this.typeReference = typeReference;
        }

        @Override
        public T processStream(InputStream stream) {
            return JSONUtils.fromJson(new InputStreamReader(stream, Charset.forName("UTF-8")), typeReference);
        }
    }

    /**
     * For use with e.g. HEAD requests where there is no InputStream
     */
    public static final class NoOpInputStreamProcessor implements InputStreamProcessor<Void> {

        @Override
        public Void processStream(InputStream stream) {
            return null;
        }
    }
}


switch(action) {
            case AppStatus.ACTION_KICK_OUT:
                break;
            case AppStatus.ACTION_LOGOUT:
                break;
            case AppStatus.ACTION_RESTART_APP:
                protectApp();
                break;
            case AppStatus.ACTION_BACK_TO_HOME:
                break;
            default:
        }

package com.jeez.guanpj.jreadhub.module.main;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.text.TextUtils;
import android.view.MenuItem;
import com.jeez.guanpj.jreadhub.R;
import com.jeez.guanpj.jreadhub.app.AppStatus;
import com.jeez.guanpj.jreadhub.app.AppStatusTracker;
import com.jeez.guanpj.jreadhub.base.fragment.AbsBaseFragment;
import com.jeez.guanpj.jreadhub.bean.NewsBean;
import com.jeez.guanpj.jreadhub.event.OpenWebSiteEvent;
import com.jeez.guanpj.jreadhub.event.SetDrawerStatusEvent;
import com.jeez.guanpj.jreadhub.event.ToolbarNavigationClickEvent;
import com.jeez.guanpj.jreadhub.module.about.AboutFragment;
import com.jeez.guanpj.jreadhub.module.settting.SettingFragment;
import com.jeez.guanpj.jreadhub.module.splash.SplashActivity;
import com.jeez.guanpj.jreadhub.module.star.StarFragment;
import com.jeez.guanpj.jreadhub.module.web.WebViewFragment;
import com.jeez.guanpj.jreadhub.mvpframe.view.activity.AbsBaseMvpActivity;
import com.jeez.guanpj.jreadhub.util.Constants;
import com.jeez.guanpj.jreadhub.util.NavigationUtil;
import butterknife.BindView;
import butterknife.ButterKnife;
import me.yokeyword.fragmentation.ISupportFragment;
import me.yokeyword.fragmentation.SupportFragment;
import me.yokeyword.fragmentation.anim.FragmentAnimator;

public class MainActivity extends AbsBaseMvpActivity<MainPresenter> implements MainContract.View, NavigationView.OnNavigationItemSelectedListener {

    @BindView(R.id.dl_main)
    DrawerLayout mDrawerLayout;

    @BindView(R.id.nv_main)
    NavigationView mNavigationView;

    private long TOUCH_TIME = 0;

    public static void start(@NonNull Activity activity) {
        Intent intent = new Intent(activity, MainActivity.class);
        activity.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ButterKnife.bind(this);
    }

    @Override
    public int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    public void initView() {
        if (findFragment(MainFragment.class) == null) {
            loadRootFragment(R.id.fl_container, MainFragment.newInstance());
        }
        mNavigationView.setCheckedItem(R.id.nav_home);
    }

    @Override
    public void initDataAndEvent() {
        mNavigationView.setNavigationItemSelectedListener(this);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        int action = intent.getIntExtra(AppStatus.KEY_HOME_ACTION, AppStatus.ACTION_BACK_TO_HOME);

    }

    @Override
    protected void protectApp() {
        startActivity(new Intent(this, SplashActivity.class));
        finish();
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        mDrawerLayout.closeDrawer(GravityCompat.START);
        mDrawerLayout.postDelayed(() -> {
            switch(item.getItemId()) {
                case R.id.nav_home:
                    MainFragment mainFragment = findFragment(MainFragment.class);
                    start(mainFragment, SupportFragment.SINGLETASK);
                    break;
                case R.id.nav_star:
                    StarFragment starFragment = findFragment(StarFragment.class);
                    if (starFragment == null) {
                        startWithPopTo(StarFragment.newInstance(), MainFragment.class, false);
                    } else {
                        start(starFragment, SupportFragment.SINGLETASK);
                    }
                    break;
                case R.id.nav_setting:
                    findFragment(MainFragment.class).start(SettingFragment.newInstance());
                    break;
                case R.id.nav_about:
                    findFragment(MainFragment.class).start(AboutFragment.newInstance());
                    break;
                default:
                    break;
            }
        }, 300);
        return true;
    }

    @Override
    public void onBackPressedSupport() {
        if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
            mDrawerLayout.closeDrawer(GravityCompat.START);
        } else {
            ISupportFragment topFragment = getTopFragment();
            if (topFragment instanceof AbsBaseFragment) {
                mNavigationView.setCheckedItem(R.id.nav_home);
            }
            if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
                pop();
            } else {
                if (System.currentTimeMillis() - TOUCH_TIME < Constants.EXIT_WAIT_TIME) {
                    AppStatusTracker.getInstance().exitApp();
                } else {
                    TOUCH_TIME = System.currentTimeMillis();
                    showShortToast(R.string.exit_tips);
                }
            }
        }
    }

    @Override
    public void onToolbarNavigationClickEvent(ToolbarNavigationClickEvent event) {
        mDrawerLayout.openDrawer(GravityCompat.START);
    }

    @Override
    public void onSetDrawerStatusEvent(SetDrawerStatusEvent event) {
        if (event.getStatus() == DrawerLayout.LOCK_MODE_UNDEFINED) {
            if (getTopFragment() instanceof MainFragment || getTopFragment() instanceof StarFragment) {
                mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNDEFINED);
            }
        } else {
            mDrawerLayout.setDrawerLockMode(event.getStatus());
        }
    }

    @Override
    public void onOpenWebSiteEvent(OpenWebSiteEvent event) {
        NewsBean newsBean = event.getNewsBean();
        if (mPresenter.isUseSystemBrowser()) {
            if (null != newsBean) {
                String url;
                if (!TextUtils.isEmpty(newsBean.getMobileUrl())) {
                    url = newsBean.getMobileUrl();
                } else {
                    url = newsBean.getUrl();
                }
                if (!TextUtils.isEmpty(url)) {
                    NavigationUtil.openInBrowser(this, event.getUrl());
                }
            } else if (!TextUtils.isEmpty(event.getUrl())) {
                NavigationUtil.openInBrowser(this, event.getUrl());
            }
        } else {
            if (null != newsBean) {
                findFragment(MainFragment.class).start(WebViewFragment.newInstance(newsBean));
            } else if (!TextUtils.isEmpty(event.getUrl()) && !TextUtils.isEmpty(event.getTitle())) {
                findFragment(MainFragment.class).start(WebViewFragment.newInstance(event.getUrl(), event.getTitle()));
            }
        }
    }

    @Override
    public void changeTheme() {
        restartActivity();
    }

    private void restartActivity() {
        Intent intent = getIntent();
        finish();
        startActivity(intent);
    }

    @Override
    public FragmentAnimator onCreateFragmentAnimator() {
        // 设置无动画
        // 设置自定义动画
        return super.onCreateFragmentAnimator();
    }
}


switch(columnIndex) {
            case 2:
                text = placeHolder.getTitle();
                break;
            default:
                break;
        }

/**
 * ****************************************************************************
 *
 *  Contributors:
 *      Daniel Murygin <dm[at]sernet[dot]de> - initial API and implementation
 * ****************************************************************************
 */
package sernet.verinice.bpm.rcp;

import java.text.DateFormat;
import java.util.Hashtable;
import java.util.Map;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.swt.graphics.Image;
import sernet.gs.ui.rcp.main.ImageCache;
import sernet.gs.ui.rcp.main.common.model.PlaceHolder;
import sernet.gs.ui.rcp.main.service.ServiceFactory;
import sernet.verinice.interfaces.IAuthService;
import sernet.verinice.interfaces.bpm.ITask;

/**
 * Label provider for the table in task view.
 *
 * @see sernet.verinice.bpm.rcp.TaskView
 * @author Daniel Murygin <dm[at]sernet[dot]de>
 */
public class TaskLabelProvider implements ITableLabelProvider {

    private static final Map<String, String> PRIO_IMAGE_MAP;

    static {
        PRIO_IMAGE_MAP = new Hashtable<String, String>();
        PRIO_IMAGE_MAP.put(ITask.PRIO_LOW, ImageCache.PRIORITY_LOW);
        PRIO_IMAGE_MAP.put(ITask.PRIO_NORMAL, ImageCache.PRIORITY_NORMAL);
        PRIO_IMAGE_MAP.put(ITask.PRIO_HIGH, ImageCache.PRIORITY_HIGH);
    }

    /**
     * @param onlyMyTasks
     */
    public TaskLabelProvider() {
        super();
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
     */
    @Override
    public Image getColumnImage(Object element, int columnIndex) {
        Image image = null;
        if (element instanceof ITask) {
            ITask task = (ITask) element;
            switch(columnIndex) {
                case 0:
                    image = ImageCache.getInstance().getImage(PRIO_IMAGE_MAP.get(task.getPriority()));
                    break;
                default:
                    break;
            }
        }
        return image;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
     */
    @Override
    public String getColumnText(Object element, int columnIndex) {
        final int maxColumnTextLength = 100;
        String text = null;
        if (element instanceof ITask) {
            ITask task = (ITask) element;
            text = getColumnText(columnIndex, task);
        }
        if (element instanceof PlaceHolder) {
            PlaceHolder placeHolder = (PlaceHolder) element;
            text = getColumnText(columnIndex, placeHolder);
        }
        if (text != null && text.length() > maxColumnTextLength) {
            text = text.substring(0, maxColumnTextLength - 1) + "...";
        }
        return text;
    }

    private String getColumnText(int columnIndex, ITask task) {
        String text = null;
        switch(columnIndex) {
            case 1:
                text = task.getGroupTitle();
                break;
            case 2:
                text = task.getElementTitle();
                break;
            case 3:
                text = task.getProcessName();
                break;
            case 4:
                text = task.getName();
                break;
            case 5:
                IAuthService authService = ServiceFactory.lookupAuthService();
                text = task.getAssignee();
                if (text != null && text.equals(authService.getUsername())) {
                    text = text + " (you)";
                }
                break;
            case 6:
                if (task.getDueDate() != null) {
                    text = DateFormat.getDateInstance().format(task.getDueDate());
                }
                break;
            default:
                break;
        }
        return text;
    }

    private String getColumnText(int columnIndex, PlaceHolder placeHolder) {
        String text = null;

        return text;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
     */
    @Override
    public void addListener(ILabelProviderListener listener) {
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
     */
    @Override
    public void dispose() {
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)
     */
    @Override
    public boolean isLabelProperty(Object element, String property) {
        return false;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
     */
    @Override
    public void removeListener(ILabelProviderListener listener) {
    }
}