问:
Recursive traversal of 2d array to find unique paths
I need to traverse a 2D-Array of 0's (which represent open pathways) and 1's which represent walls. I have to calculate the number of unique paths from (0,0) to (N-1,N-1) of an NxN Grid. I have written a recursive method to do this however i cannot figure out why the traversal part of my method (i.e the straight, left and right movements) are not working as expected:

```<code>    public static void TraversePath(int [][] Grid, boolean[][] isTraversed, int column, int row) {
    if(row < 0 || column < 0 || row > Grid[0].length || column > Grid[0].length )
        return; // if you go out of bounds
    if(isTraversed[column][row] == true)
        return; // if you have already been to the point
    if(Grid[column][row]==1) {
        isTraversed[column][row] = true; // if the current point is a wall mark it as traversed
        return;
    }
    if(Grid[column][row]!=1 && (row == Grid[0].length-1 && column == Grid[0].length-1)) { //if you get to an endpoint that isn't a wall
        uniquePaths++; //counter that tallys the unique paths
        isTraversed[column][row] = true;
        return;
    }

    TraversePath(Grid,column,row+1);//Straight
    TraversePath(Grid,column-1, row);//Left
    TraversePath(Grid,column+1, row);//Right

}

public static void main(String[] args) {
    int [][]Grid = new int[][]
            {
        {0,1,1,0},
        {0,0,1,0},
        {0,0,0,0},
        {0,1,1,0}
            };
    boolean[][] isTraversed = new boolean[Grid.length][Grid.length];
    for(int i = 0; i < Grid.length; i++) {
        for(int j = 0; j< Grid.length; j++)
            isTraversed[i][j] = false;
    }
    TraversePath(Grid,isTraversed,0,0);
    System.out.println(uniquePaths);

}
</code>```

I keep getting a StackOverFlow error (hey, sounds familiar) when I run this code. I figure it probably has something to do with how I am marking the edges as visited in the isTraversed boolean graph but I am not sure. Any help would be super appreciated.

This is the main method that I'm using to test the array, it's a simple 4x4 grid with 2 unique paths to (3,3).

答:
Your Stack Overflow Error is caused by the fact that you can continuously move left then right again. Assuming that you could only move in the positive directions, you could make a very simple recursive function using dynamic programing to prevent you from getting a Stack Overflow error.

```<code>public static int possiblePaths(int[][] grid, int x,int y,int [][] dp){
    if(x<0||x>=grid.length||y<0||y>=grid[0].length)
        return 0;
    if(dp[x][y]==-1){
        dp[x][y]=possiblePaths(grid,x+1,y,dp)+possiblePaths(grid,x,y+1,dp);
    }
    return dp[x][y];
}

public static void main(String[] args) {
    int [][]Grid = new int[][]
            {
        {0,1,1,0},
        {0,0,1,0},
        {0,0,0,0},
        {0,1,1,0}
            };
    int [][] dp = new int[Grid.length][Grid[0].length];
    for(int i = 0; i < Grid.length; i++) {
        for(int j = 0; j< Grid[0].length; j++)
            if(Grid[i][j]==1)
                dp[i][j]=0;
            else
                dp[i][j]=-1;
    }
    dp[Grid.length-1][Grid[0].length-1]=0;
    System.out.println(possiblePaths(Grid,0,0,dp));

}
</code>```

What this basically states that the amount of ways to get from (x,y) to the end is the sum of # of paths from (x+1,y) and # of paths from (x,y+1) and remembers these numbers in the dp (Dynamic Programing) array so you do not need to recalculate them. In the dp array, the cells where there are walls are set to 0 because there are 0 ways to get to the end from the wall.

Body:
I need to traverse a 2D-Array of 0's (which represent open pathways) and 1's which represent walls. I have to calculate the number of unique paths from (0,0) to (N-1,N-1) of an NxN Grid. I have written a recursive method to do this however i cannot figure out why the traversal part of my method (i.e the straight, left and right movements) are not working as expected:

    public static void TraversePath(int [][] Grid, boolean[][] isTraversed, int column, int row) {
    if(row < 0 || column < 0 || row > Grid[0].length || column > Grid[0].length )
        return; // if you go out of bounds
    if(isTraversed[column][row] == true)
        return; // if you have already been to the point
    if(Grid[column][row]==1) {
        isTraversed[column][row] = true; // if the current point is a wall mark it as traversed
        return;
    }
    if(Grid[column][row]!=1 && (row == Grid[0].length-1 && column == Grid[0].length-1)) { //if you get to an endpoint that isn't a wall
        uniquePaths++; //counter that tallys the unique paths
        isTraversed[column][row] = true;
        return;
    }

    TraversePath(Grid,column,row+1);//Straight
    TraversePath(Grid,column-1, row);//Left
    TraversePath(Grid,column+1, row);//Right

}

public static void main(String[] args) {
    int [][]Grid = new int[][]
            {
        {0,1,1,0},
        {0,0,1,0},
        {0,0,0,0},
        {0,1,1,0}
            };
    boolean[][] isTraversed = new boolean[Grid.length][Grid.length];
    for(int i = 0; i < Grid.length; i++) {
        for(int j = 0; j< Grid.length; j++)
            isTraversed[i][j] = false;
    }
    TraversePath(Grid,isTraversed,0,0);
    System.out.println(uniquePaths);

}

I keep getting a StackOverFlow error (hey, sounds familiar) when I run this code. I figure it probably has something to do with how I am marking the edges as visited in the isTraversed boolean graph but I am not sure. Any help would be super appreciated.

This is the main method that I'm using to test the array, it's a simple 4x4 grid with 2 unique paths to (3,3).

Body:
Your Stack Overflow Error is caused by the fact that you can continuously move left then right again. Assuming that you could only move in the positive directions, you could make a very simple recursive function using dynamic programing to prevent you from getting a Stack Overflow error.

public static int possiblePaths(int[][] grid, int x,int y,int [][] dp){
    if(x<0||x>=grid.length||y<0||y>=grid[0].length)
        return 0;
    if(dp[x][y]==-1){
        dp[x][y]=possiblePaths(grid,x+1,y,dp)+possiblePaths(grid,x,y+1,dp);
    }
    return dp[x][y];
}

public static void main(String[] args) {
    int [][]Grid = new int[][]
            {
        {0,1,1,0},
        {0,0,1,0},
        {0,0,0,0},
        {0,1,1,0}
            };
    int [][] dp = new int[Grid.length][Grid[0].length];
    for(int i = 0; i < Grid.length; i++) {
        for(int j = 0; j< Grid[0].length; j++)
            if(Grid[i][j]==1)
                dp[i][j]=0;
            else
                dp[i][j]=-1;
    }
    dp[Grid.length-1][Grid[0].length-1]=0;
    System.out.println(possiblePaths(Grid,0,0,dp));

}

What this basically states that the amount of ways to get from (x,y) to the end is the sum of # of paths from (x+1,y) and # of paths from (x,y+1) and remembers these numbers in the dp (Dynamic Programing) array so you do not need to recalculate them. In the dp array, the cells where there are walls are set to 0 because there are 0 ways to get to the end from the wall.


来源: stackexchange

问:
Programmatically picking up phonecall
I have a door telephone on our office building. When somebody presses the button it calls a telephone number for which we have a simcard. Right now that simcard is in a cellphone. Everytime we have a meeting at our office, we have to pick up the phone and press 3 to open the door. I'm looking for a solution to be able to programatically pick up the phone and press the 3. Does any such software exist? I have googled but found nothing.

TLDR; I need some software (and a sim card reader) that can programmatically pick up the phone when it rings and respond with a 3 on the numpad.

The OS doesn't matter.

Not sure if Stackoverflow is the right place to ask. Let me know if you have suggestions for other better places to ask.

答:
Another possible solution:

Setup voicemail for that SIM card, and when you are asked to leave your voicemail message (the message which is played to whoever gets to the voicemail) just press the button #3.

When you want, use call forwarding to redirect all calls to the voicemail. Alternatively, turn off the phone (on most cellular networks this will redirect all calls to the voicemail).

ContentLicense: CC BY-SA 3.0

Title: Programmatically picking up phonecall


问:
Convert Array of Dictionary to custom object swift
I have:

```<code>    let countries : [[String : Any]] = [
            [
                "name" : "Afghanistan",
                "dial_code": "+93",
                "code": "AF"
            ],
            [
                "name": "Aland Islands",
                "dial_code": "+358",
                "code": "AX"
            ],
            [
                "name": "Albania",
                "dial_code": "+355",
                "code": "AL"
            ],
            [
                "name": "Algeria",
                "dial_code": "+213",
                "code": "DZ"
            ]
]
</code>```

I want to add all this array of dictionary to my custom object like

```<code>let country:[Country] = countries
</code>```

My custom object looks like this:

```<code>class Country: NSObject {
        let name: String
        let dial_code : String
        let code: String

        init(name: String, dial_code: String, code: String) {
            self.name = name
            self.dial_code = dial_code
            self.code = code
        }
    }
</code>```

I understand that I need a loop thru the array but idk what is the next step. Would be great to have an example.

答:
You should make your Country conform to Codable protocol, convert your dictionary to JSON data using JSONSerialization and then just decode the Data using JSONDecoder, note that you can set its keyDecodingStrategy property to convertFromSnakeCase auto avoid the need to declare custom coding keys like dial_Code:

```<code>struct Country: Codable {
    let name: String
    let dialCode : String
    let code: String
}
</code>```

```<code>do {
    let json = try JSONSerialization.data(withJSONObject: countries)
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let decodedCountries = try decoder.decode([Country].self, from: json)
    decodedCountries.forEach{print($0)}
} catch {
    print(error)
}
</code>```

Country(name: "Afghanistan", dialCode: "+93", code: "AF")

Country(name: "Aland Islands", dialCode: "+358", code: "AX")

Country(name: "Albania", dialCode: "+355", code: "AL")

Country(name: "Algeria", dialCode: "+213", code: "DZ")

Body:
I have:

    let countries : [[String : Any]] = [
            [
                "name" : "Afghanistan",
                "dial_code": "+93",
                "code": "AF"
            ],
            [
                "name": "Aland Islands",
                "dial_code": "+358",
                "code": "AX"
            ],
            [
                "name": "Albania",
                "dial_code": "+355",
                "code": "AL"
            ],
            [
                "name": "Algeria",
                "dial_code": "+213",
                "code": "DZ"
            ]
]

I want to add all this array of dictionary to my custom object like

let country:[Country] = countries

My custom object looks like this:

class Country: NSObject {
        let name: String
        let dial_code : String
        let code: String

        init(name: String, dial_code: String, code: String) {
            self.name = name
            self.dial_code = dial_code
            self.code = code
        }
    }

I understand that I need a loop thru the array but idk what is the next step. Would be great to have an example.

Body:
You should make your Country conform to Codable protocol, convert your dictionary to JSON data using JSONSerialization and then just decode the Data using JSONDecoder, note that you can set its keyDecodingStrategy property to convertFromSnakeCase auto avoid the need to declare custom coding keys like dial_Code:

struct Country: Codable {
    let name: String
    let dialCode : String
    let code: String
}

do {
    let json = try JSONSerialization.data(withJSONObject: countries)
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let decodedCountries = try decoder.decode([Country].self, from: json)
    decodedCountries.forEach{print($0)}
} catch {
    print(error)
}

Country(name: "Afghanistan", dialCode: "+93", code: "AF")

Country(name: "Aland Islands", dialCode: "+358", code: "AX")

Country(name: "Albania", dialCode: "+355", code: "AL")

Country(name: "Algeria", dialCode: "+213", code: "DZ")

ContentLicense: CC BY-SA 4.0


问:
Get image from image view and then crop (Android Image Cropper Library)
Hi I have been using Android Image Cropper library, though I have been able to crop images from getting them from the gallery.

But how would I start the image crop activity if I would just get the image from a Imageview and not selecting from the gallery or camera?

I have researched but you can only start the crop activity when using a image URI but maybe someone else has been able to do it.

This is my acitivty:

```<code>  private Uri mCropImageUri;

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    txtExtracted = (TextView) findViewById(R.id.txtRetrieved);

    btnStartCrop = (Button) findViewById(R.id.btnStartCrop);

    imageView = (ImageView) findViewById(R.id.imgView);

    View v1 = getWindow().getDecorView().getRootView();
    v1.setDrawingCacheEnabled(true);
    Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
    imageView.setImageBitmap(bitmap);

   btnStartCrop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

        }
    });
  }

@Override
@SuppressLint("NewApi")
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
        CropImage.ActivityResult result = CropImage.getActivityResult(data);
        if (resultCode == RESULT_OK) {
            ((ImageView) findViewById(R.id.quick_start_cropped_image)).setImageURI(result.getUri());
            Toast.makeText(this, "Cropping successful, Sample: " + result.getSampleSize(), Toast.LENGTH_LONG).show();
        } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
            Toast.makeText(this, "Cropping failed: " + result.getError(), Toast.LENGTH_LONG).show();
        }
    }
}

private void startCropImageActivity(Uri imageUri) {
    CropImage.activity(imageUri)
            .setGuidelines(CropImageView.Guidelines.ON)
            .setMultiTouchEnabled(true)
            .start(this);
}
</code>```

Thanks in advance for any help regarding this, and if anyone has opinions or better ways to go it will be greatly appreciated :D

答:
Can you try with picaso.</p>

```<code>@Override
@SuppressLint("NewApi")
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
        CropImage.ActivityResult result = CropImage.getActivityResult(data);
        if (resultCode == RESULT_OK) {

            Picasso.with(this)
                .load(result.getUri())
                .into(((ImageView) findViewById(R.id.quick_start_cropped_image)));

        } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
            Toast.makeText(this, "Cropping failed: " + result.getError(), Toast.LENGTH_LONG).show();
        }
    }
}
</code>```

Body:
Hi I have been using Android Image Cropper library, though I have been able to crop images from getting them from the gallery.

But how would I start the image crop activity if I would just get the image from a Imageview and not selecting from the gallery or camera?

I have researched but you can only start the crop activity when using a image URI but maybe someone else has been able to do it.

This is my acitivty:

  private Uri mCropImageUri;

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    txtExtracted = (TextView) findViewById(R.id.txtRetrieved);

    btnStartCrop = (Button) findViewById(R.id.btnStartCrop);

    imageView = (ImageView) findViewById(R.id.imgView);

    View v1 = getWindow().getDecorView().getRootView();
    v1.setDrawingCacheEnabled(true);
    Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
    imageView.setImageBitmap(bitmap);

   btnStartCrop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

        }
    });
  }

@Override
@SuppressLint("NewApi")
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
        CropImage.ActivityResult result = CropImage.getActivityResult(data);
        if (resultCode == RESULT_OK) {
            ((ImageView) findViewById(R.id.quick_start_cropped_image)).setImageURI(result.getUri());
            Toast.makeText(this, "Cropping successful, Sample: " + result.getSampleSize(), Toast.LENGTH_LONG).show();
        } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
            Toast.makeText(this, "Cropping failed: " + result.getError(), Toast.LENGTH_LONG).show();
        }
    }
}

private void startCropImageActivity(Uri imageUri) {
    CropImage.activity(imageUri)
            .setGuidelines(CropImageView.Guidelines.ON)
            .setMultiTouchEnabled(true)
            .start(this);
}

Thanks in advance for any help regarding this, and if anyone has opinions or better ways to go it will be greatly appreciated :D

Body:
Can you try with picaso.

@Override
@SuppressLint("NewApi")
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
        CropImage.ActivityResult result = CropImage.getActivityResult(data);
        if (resultCode == RESULT_OK) {

            Picasso.with(this)
                .load(result.getUri())
                .into(((ImageView) findViewById(R.id.quick_start_cropped_image)));

        } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
            Toast.makeText(this, "Cropping failed: " + result.getError(), Toast.LENGTH_LONG).show();
        }
    }
}


问:
How to programatically add/remove nodes from main graph in Tensorboard?
Tensorboard seems to arbitrarily select which nodes belong to the main graph and which do not. During graph visualization I can manually add/remove the nodes but it is tedious to do it every run.

Is there a way to programmatically embed this information (which nodes belong on the main graph) during writing the graph summary?

答:
According to this github issue , it's not feasible at the moment.

And according to this quote :

Thanks @lightcatcher for the suggestion. @danmane, please take a look
  at this issue. If it is something we will not do in the short-term
  maybe mark it contributions welcome. If it is something you are
  planning to include in your plugin API anyways, please close the issue
  to keep the backlog clear.

, and the status of the issue (contributions:welcomed), it's not something that is to be expected in the short term.


问:
Control Size increases on Korean OS
I have a windows Form that has a Label control specified with fixed size. It's Autosize value is true and the maximum size contains the same value for width as the width of the control, so that, the control only increases it's height if the need be. This works fine on English OS, but when this is deployed on say Korean OS, the width increases and crosses the maximum limit set in the form.

I have played with Autoscalemode with all the values - Font, DPI, None, Inherit, but doesn't change a thing. What could be wrong with it and How can we overcome this problem.

答:
Yes, it increases and actually is well known (in some circles) behavior. There is some problem with how font are measured (probably fallback font is measured instead of the one you defined).

Instead of setting the size to fixed, I would use TableLayoutPanel as layout manager for this control/form/whatever and allow it to actually resize. You'll need to play with it a bit, but from my experience adding empty distance column works (provided that you have at least one percentage column). This is a bit tricky, but I managed to fix similar defect this way.

ContentLicense: CC BY-SA 2.5

Title: Control Size increases on Korean OS


问:
Eliminate Duplicate IDs in SQL Server View
i am creating this view from different tables . but the problem in view some of the IDS are repeated . i want to eliminate repeated ID from it .how can i do that .I know i have to use Distinct keyword but how can i use it here ?</p>

```<code> SELECT        dbo.Dispatch.Date, dbo.Dispatch.ID AS Dispatch_ID, dbo.Dispatch.Demand_ID AS Dispatch_DemandID, dbo.Dispatch.Full_Weight, dbo.Dispatch.Empty_Weight, dbo.Dispatch.Status, dbo.Dispatch.PDate,
                         dbo.Customer.Name AS CustomerName, dbo.Demand.ID AS Demand_ID, dbo.Material.Bulk_Bags, dbo.Material.Type AS MaterialType, dbo.Material.Name AS MaterialName,
                         dbo.[Order].Order_ID AS Order_Order_ID, dbo.[Order].Order_Date, dbo.Dispatch.PYear, dbo.Dispatch.PWeek, dbo.Dispatch.PMonth, dbo.[Order].Total_Quantity, dbo.[Order].RatePerTon, dbo.[Order].Discount,
                         dbo.[Order].Final_Cost, dbo.[Order].Payment_Mode, dbo.[Order].Tax, dbo.[Order].Added_Value, dbo.Dispatch.Full_Weight - dbo.Dispatch.Empty_Weight AS DeliveredQuantity, dbo.Demand.Order_ID,
                         dbo.Total_Amount_Status.Total_Amount, dbo.Total_Amount_Status.Amount_status
FROM                     dbo.Dispatch INNER JOIN
                         dbo.Demand ON dbo.Dispatch.Demand_ID = dbo.Demand.ID INNER JOIN
                         dbo.[Order] ON dbo.Demand.Order_ID = dbo.[Order].Order_ID INNER JOIN
                         dbo.Material ON dbo.[Order].Material_ID = dbo.Material.ID INNER JOIN
                         dbo.Customer ON dbo.[Order].Customer_ID = dbo.Customer.ID LEFT OUTER JOIN
                         dbo.Total_Amount_Status ON dbo.[Order].Order_ID = dbo.Total_Amount_Status.Order_ID
WHERE        (dbo.Dispatch.Status = 'EXIT') AND (dbo.Dispatch.Date = CONVERT(DATETIME, '2017-12-06 00:00:00', 102)) order by Dispatch.ID desc
</code>```

答:
You can use the ROW_NUMBER() OVER(PARTITION BY XX ORDER BY XX) Function and then select the rows which returns 1.

This should be done by using your Primary keys to identify a unique row.

Example could be like:

SQL Code

```<code>    with cte as ( SELECT        dbo.Dispatch.Date, dbo.Dispatch.ID AS Dispatch_ID, dbo.Dispatch.Demand_ID AS Dispatch_DemandID, dbo.Dispatch.Full_Weight, dbo.Dispatch.Empty_Weight, dbo.Dispatch.Status, dbo.Dispatch.PDate,
                         dbo.Customer.Name AS CustomerName, dbo.Demand.ID AS Demand_ID, dbo.Material.Bulk_Bags, dbo.Material.Type AS MaterialType, dbo.Material.Name AS MaterialName,
                         dbo.[Order].Order_ID AS Order_Order_ID, dbo.[Order].Order_Date, dbo.Dispatch.PYear, dbo.Dispatch.PWeek, dbo.Dispatch.PMonth, dbo.[Order].Total_Quantity, dbo.[Order].RatePerTon, dbo.[Order].Discount,
                         dbo.[Order].Final_Cost, dbo.[Order].Payment_Mode, dbo.[Order].Tax, dbo.[Order].Added_Value, dbo.Dispatch.Full_Weight - dbo.Dispatch.Empty_Weight AS DeliveredQuantity, dbo.Demand.Order_ID,
                         dbo.Total_Amount_Status.Total_Amount, dbo.Total_Amount_Status.Amount_status
                         ,ROW_NUMBER() OVER(PARTITION BY dbo.Dispatch.ID order by dbo.Dispatch.ID) as rn
FROM                     dbo.Dispatch INNER JOIN
                         dbo.Demand ON dbo.Dispatch.Demand_ID = dbo.Demand.ID INNER JOIN
                         dbo.[Order] ON dbo.Demand.Order_ID = dbo.[Order].Order_ID INNER JOIN
                         dbo.Material ON dbo.[Order].Material_ID = dbo.Material.ID INNER JOIN
                         dbo.Customer ON dbo.[Order].Customer_ID = dbo.Customer.ID LEFT OUTER JOIN
                         dbo.Total_Amount_Status ON dbo.[Order].Order_ID = dbo.Total_Amount_Status.Order_ID
WHERE        (dbo.Dispatch.Status = 'EXIT') AND (dbo.Dispatch.Date = CONVERT(DATETIME, '2017-12-06 00:00:00', 102))

)

select * from CTE
where rn = 1
order by Dispatch_ID desc
</code>```

Body:
i am creating this view from different tables . but the problem in view some of the IDS are repeated . i want to eliminate repeated ID from it .how can i do that .I know i have to use Distinct keyword but how can i use it here ?

 SELECT        dbo.Dispatch.Date, dbo.Dispatch.ID AS Dispatch_ID, dbo.Dispatch.Demand_ID AS Dispatch_DemandID, dbo.Dispatch.Full_Weight, dbo.Dispatch.Empty_Weight, dbo.Dispatch.Status, dbo.Dispatch.PDate,
                         dbo.Customer.Name AS CustomerName, dbo.Demand.ID AS Demand_ID, dbo.Material.Bulk_Bags, dbo.Material.Type AS MaterialType, dbo.Material.Name AS MaterialName,
                         dbo.[Order].Order_ID AS Order_Order_ID, dbo.[Order].Order_Date, dbo.Dispatch.PYear, dbo.Dispatch.PWeek, dbo.Dispatch.PMonth, dbo.[Order].Total_Quantity, dbo.[Order].RatePerTon, dbo.[Order].Discount,
                         dbo.[Order].Final_Cost, dbo.[Order].Payment_Mode, dbo.[Order].Tax, dbo.[Order].Added_Value, dbo.Dispatch.Full_Weight - dbo.Dispatch.Empty_Weight AS DeliveredQuantity, dbo.Demand.Order_ID,
                         dbo.Total_Amount_Status.Total_Amount, dbo.Total_Amount_Status.Amount_status
FROM                     dbo.Dispatch INNER JOIN
                         dbo.Demand ON dbo.Dispatch.Demand_ID = dbo.Demand.ID INNER JOIN
                         dbo.[Order] ON dbo.Demand.Order_ID = dbo.[Order].Order_ID INNER JOIN
                         dbo.Material ON dbo.[Order].Material_ID = dbo.Material.ID INNER JOIN
                         dbo.Customer ON dbo.[Order].Customer_ID = dbo.Customer.ID LEFT OUTER JOIN
                         dbo.Total_Amount_Status ON dbo.[Order].Order_ID = dbo.Total_Amount_Status.Order_ID
WHERE        (dbo.Dispatch.Status = 'EXIT') AND (dbo.Dispatch.Date = CONVERT(DATETIME, '2017-12-06 00:00:00', 102)) order by Dispatch.ID desc

Body:
You can use the ROW_NUMBER() OVER(PARTITION BY XX ORDER BY XX) Function and then select the rows which returns 1.

This should be done by using your Primary keys to identify a unique row.

Example could be like:

SQL Code

    with cte as ( SELECT        dbo.Dispatch.Date, dbo.Dispatch.ID AS Dispatch_ID, dbo.Dispatch.Demand_ID AS Dispatch_DemandID, dbo.Dispatch.Full_Weight, dbo.Dispatch.Empty_Weight, dbo.Dispatch.Status, dbo.Dispatch.PDate,
                         dbo.Customer.Name AS CustomerName, dbo.Demand.ID AS Demand_ID, dbo.Material.Bulk_Bags, dbo.Material.Type AS MaterialType, dbo.Material.Name AS MaterialName,
                         dbo.[Order].Order_ID AS Order_Order_ID, dbo.[Order].Order_Date, dbo.Dispatch.PYear, dbo.Dispatch.PWeek, dbo.Dispatch.PMonth, dbo.[Order].Total_Quantity, dbo.[Order].RatePerTon, dbo.[Order].Discount,
                         dbo.[Order].Final_Cost, dbo.[Order].Payment_Mode, dbo.[Order].Tax, dbo.[Order].Added_Value, dbo.Dispatch.Full_Weight - dbo.Dispatch.Empty_Weight AS DeliveredQuantity, dbo.Demand.Order_ID,
                         dbo.Total_Amount_Status.Total_Amount, dbo.Total_Amount_Status.Amount_status
                         ,ROW_NUMBER() OVER(PARTITION BY dbo.Dispatch.ID order by dbo.Dispatch.ID) as rn
FROM                     dbo.Dispatch INNER JOIN
                         dbo.Demand ON dbo.Dispatch.Demand_ID = dbo.Demand.ID INNER JOIN
                         dbo.[Order] ON dbo.Demand.Order_ID = dbo.[Order].Order_ID INNER JOIN
                         dbo.Material ON dbo.[Order].Material_ID = dbo.Material.ID INNER JOIN
                         dbo.Customer ON dbo.[Order].Customer_ID = dbo.Customer.ID LEFT OUTER JOIN
                         dbo.Total_Amount_Status ON dbo.[Order].Order_ID = dbo.Total_Amount_Status.Order_ID
WHERE        (dbo.Dispatch.Status = 'EXIT') AND (dbo.Dispatch.Date = CONVERT(DATETIME, '2017-12-06 00:00:00', 102))

)

select * from CTE
where rn = 1
order by Dispatch_ID desc


问:
Perform join on two tables in HQL
Consider table A and B. Entire column in table A and only one column in table B need to be taken.Previously,a named query is created with which entire column values of table A are taken. Now i need to include one column of table B too.

In DAO class,below is code

```<code>X x=null
 Query query = getEntityManager().createNamedQuery("AAA").setParameter("serialID",val);
 x=(X) query.getSingleResult()
</code>```

And in DTO class, AAA is part of class X which refers to table A. The query of AAA is below:

```<code>select X from A X where COLUMNVAL= serialID;
</code>```

Now, table B also has COLUMNVAL too and i need to consider value of xyz column from that table.Consider xyz is mapped in class Q.

I tried the below query for which i got classcast exception as java.lang.object cannot be cast to A

```<code>select X, Q.xyz from A X, B Q where X.COLUMNVAL = Q.COLUMNVAL AND X.COLUMNVAL=serialID
</code>```

Please favour how to proceed further. A has huge number of columns so ResultList is not preferred.

答:
I tried the below query for which i got classcast exception as
  java.lang.object cannot be cast to A

select X, Q.xyz from A X, B Q where X.COLUMNVAL = Q.COLUMNVAL AND
  X.COLUMNVAL=serialID

if you wish to use that query, you'll non get objects of class A, but instead an Array of Object where the first element is an object of class and the second element is the value Q.xyz

so you should use

```<code>Object[] x;
x=(Object[]) query.getSingleResult()
</code>```

Title: Perform join on two tables in HQL

Body:
Consider table A and B. Entire column in table A and only one column in table B need to be taken.Previously,a named query is created with which entire column values of table A are taken. Now i need to include one column of table B too.

In DAO class,below is code

X x=null
 Query query = getEntityManager().createNamedQuery("AAA").setParameter("serialID",val);
 x=(X) query.getSingleResult()

And in DTO class, AAA is part of class X which refers to table A. The query of AAA is below:

select X from A X where COLUMNVAL= serialID;

Now, table B also has COLUMNVAL too and i need to consider value of xyz column from that table.Consider xyz is mapped in class Q.

I tried the below query for which i got classcast exception as java.lang.object cannot be cast to A

select X, Q.xyz from A X, B Q where X.COLUMNVAL = Q.COLUMNVAL AND X.COLUMNVAL=serialID

Please favour how to proceed further. A has huge number of columns so ResultList is not preferred.

Body:
I tried the below query for which i got classcast exception as
  java.lang.object cannot be cast to A

select X, Q.xyz from A X, B Q where X.COLUMNVAL = Q.COLUMNVAL AND
  X.COLUMNVAL=serialID

if you wish to use that query, you'll non get objects of class A, but instead an Array of Object where the first element is an object of class and the second element is the value Q.xyz

so you should use

Object[] x;
x=(Object[]) query.getSingleResult()


问:
Expression of type list(object) doesn't conform to expected list scala
Supposedly I have the following

```<code>case class test {
                   a:string
                   b: string
                   c: Int
                   d: Int }

var temp = List(test("lol","lel",1,2))
var total = List(test)

total = total:::temp //this doesn't work because temp is of type [test] while total is of type [test.type]
</code>```

I do not understand the difference.
The reason I want to use this is that I want to have a running list where elements will be conditionally added in a loop.
So in this instance, total should initially an empty list which takes test objects. How do I do this?

Any feedback is appreciated!

答:
You are looking for total = List.empty[test] rather than List(test).
The former creates an empty list of type List[test], the latter is a one-element list of type List[test.type] (test.type is not the same as test - it is its own object, representing the type of instances of test).

Also, do not use var. They are evil, and not really needed in scala in 99% of uses-cases. Just pretend that keyword does not exist at all, until you get enough of a grip at the language to be able to confidently distinguish the other 1%.

Body:
Supposedly I have the following

case class test {
                   a:string
                   b: string
                   c: Int
                   d: Int }

var temp = List(test("lol","lel",1,2))
var total = List(test)

total = total:::temp //this doesn't work because temp is of type [test] while total is of type [test.type]

I do not understand the difference.
The reason I want to use this is that I want to have a running list where elements will be conditionally added in a loop.
So in this instance, total should initially an empty list which takes test objects. How do I do this?

Any feedback is appreciated!


问:
Imageview not on correct row after scrolling in Recyclerview
I have an app that displays my e-mail via microsoft graph api.
Everything but 1 things i working fine so far. When the list first loads in, all info is correctly displayed, but when i scroll down, then back up. The imageview of the attachement sits on the wrong rows. It just displays on rows without attachement. In the adapter i have an if clausule which says to only show the image in the row if the hasAttachement value is "true".. I really don't get why it is redrawin the image in the wrongs rows..

The method where i set the attachement is called:
setBijlage() in MessagesAdapter

EDIT: If i click the row in my app, that row displays correctly again (gains an icon if it has attachement, and deletes it if it doesn't)

MailActivity.java

```<code>public class MailActivity extends AppCompatActivityRest implements SwipeRefreshLayout.OnRefreshListener, MessagesAdapter.MessageAdapterListener {

    private String currentFolder;
    private String currentUser;
    private List<Message> messages = new ArrayList<>();
    private RecyclerView recyclerView;
    private MessagesAdapter mAdapter;
    private SwipeRefreshLayout swipeRefreshLayout;
    private ActionModeCallback actionModeCallback;
    private ActionMode actionMode;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_mail);
        super.onCreate(savedInstanceState);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        currentFolder = getString(R.string.inbox);
        currentUser = getIntent().getStringExtra("USER_EMAIL");
        setActionBarMail(currentFolder, currentUser);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
        swipeRefreshLayout.setOnRefreshListener(this);

        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));

        actionModeCallback = new ActionModeCallback();

        // show loader and fetch messages
        swipeRefreshLayout.post(
                new Runnable() {
                    @Override
                    public void run() {
                        getAllMails(15);
                    }
                }
        );
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_search) {
            Toast.makeText(getApplicationContext(), "Search...", Toast.LENGTH_SHORT).show();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void processResponse(OutlookObjectCall outlookObjectCall, JSONObject response) {

        switch (outlookObjectCall) {
            case READUSER: {
                System.out.println("reading user");
            } break;
            case READMAIL: {
                messages.clear();

                JSONObject list = response;
                try {
                    JSONArray mails = list.getJSONArray("value");
                    Type listType = new TypeToken<List<Message>>() {
                    }.getType();
                    messages = new Gson().fromJson(String.valueOf(mails), listType);
                    for (Message message : messages) {
                        message.setColor(getRandomMaterialColor("400"));
                    }
                    System.out.println(messages.get(2).getFrom().getEmailAddress().getName());

                    mAdapter = new MessagesAdapter(this, messages, this);
                    recyclerView.setAdapter(mAdapter);

                } catch (JSONException e) {
                    e.printStackTrace();
                }

                mAdapter.notifyDataSetChanged();
                swipeRefreshLayout.setRefreshing(false);

            }
            break;
            case SENDMAIL: {
                System.out.println("Just send a mail." );
            }
        }
    }

    @Override
    public void onRefresh() {
        // swipe refresh is performed, fetch the messages again
        getAllMails(15);
    }

    @Override
    public void onIconClicked(int position) {
        if (actionMode == null) {
            actionMode = startSupportActionMode(actionModeCallback);
        }

        toggleSelection(position);
    }

    @Override
    public void onIconImportantClicked(int position) {
        // Star icon is clicked,
        // mark the message as important
        Message message = messages.get(position);
        message.setImportance("normal");
        messages.set(position, message);
        mAdapter.notifyDataSetChanged();
    }

    @Override
    public void onMessageRowClicked(int position) {
        // verify whether action mode is enabled or not
        // if enabled, change the row state to activated
        if (mAdapter.getSelectedItemCount() > 0) {
            enableActionMode(position);
        } else {
            // read the message which removes bold from the row
            Message message = messages.get(position);
            message.setIsRead("true");
            messages.set(position, message);
            mAdapter.notifyDataSetChanged();

            Toast.makeText(getApplicationContext(), "Read: " + message.getBodyPreview(), Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRowLongClicked(int position) {
        // long press is performed, enable action mode
        enableActionMode(position);
    }

    private void enableActionMode(int position) {
        if (actionMode == null) {
            actionMode = startSupportActionMode(actionModeCallback);
        }
        toggleSelection(position);
    }

    private void toggleSelection(int position) {
        mAdapter.toggleSelection(position);
        int count = mAdapter.getSelectedItemCount();

        if (count == 0) {
            actionMode.finish();
        } else {
            actionMode.setTitle(String.valueOf(count));
            actionMode.invalidate();
        }
    }

    private class ActionModeCallback implements ActionMode.Callback {
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            mode.getMenuInflater().inflate(R.menu.menu_action_mode, menu);

            // disable swipe refresh if action mode is enabled
            swipeRefreshLayout.setEnabled(false);
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()) {
                case R.id.action_delete:
                    // delete all the selected messages
                    deleteMessages();
                    mode.finish();
                    return true;

                default:
                    return false;
            }
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            mAdapter.clearSelections();
            swipeRefreshLayout.setEnabled(true);
            actionMode = null;
            recyclerView.post(new Runnable() {
                @Override
                public void run() {
                    mAdapter.resetAnimationIndex();
                    // mAdapter.notifyDataSetChanged();
                }
            });
        }
    }

    // deleting the messages from recycler view
    private void deleteMessages() {
        mAdapter.resetAnimationIndex();
        List<Integer> selectedItemPositions =
                mAdapter.getSelectedItems();
        for (int i = selectedItemPositions.size() - 1; i >= 0; i--) {
            mAdapter.removeData(selectedItemPositions.get(i));
        }
        mAdapter.notifyDataSetChanged();
    }

    private void setActionBarMail(String title, String subtitle) {
        getSupportActionBar().setTitle(title);
        getSupportActionBar().setSubtitle(subtitle);
    }

    private void getAllMails(int aantalMails) {
        swipeRefreshLayout.setRefreshing(true);
        try {
            new GraphAPI().getRequest(OutlookObjectCall.READMAIL, this, "/inbox/messages?$top=" + aantalMails);

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private int getRandomMaterialColor(String typeColor) {
        int returnColor = Color.GRAY;
        int arrayId = getResources().getIdentifier("mdcolor_" + typeColor, "array", getPackageName());

        if (arrayId != 0) {
            TypedArray colors = getResources().obtainTypedArray(arrayId);
            int index = (int) (Math.random() * colors.length());
            returnColor = colors.getColor(index, Color.GRAY);
            colors.recycle();
        }
        return returnColor;
    }
</code>```

MessagesAdapter.java

```<code>public class MessagesAdapter extends RecyclerView.Adapter<MessagesAdapter.MyViewHolder> {
    private Context mContext;
    private List<Message> messages;
    private MessageAdapterListener listener;
    private SparseBooleanArray selectedItems;

    // array used to perform multiple animation at once
    private SparseBooleanArray animationItemsIndex;
    private boolean reverseAllAnimations = false;

    // index is used to animate only the selected row
    // dirty fix, find a better solution
    private static int currentSelectedIndex = -1;

    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener {
        public TextView from, subject, message, iconText, timestamp;
        public ImageView iconImp, imgProfile, imgBijlage;
        public LinearLayout messageContainer;
        public RelativeLayout iconContainer, iconBack, iconFront;

        public MyViewHolder(View view) {
            super(view);
            from = (TextView) view.findViewById(R.id.from);
            subject = (TextView) view.findViewById(R.id.txt_primary);
            message = (TextView) view.findViewById(R.id.txt_secondary);
            iconText = (TextView) view.findViewById(R.id.icon_text);
            timestamp = (TextView) view.findViewById(R.id.timestamp);
            iconBack = (RelativeLayout) view.findViewById(R.id.icon_back);
            iconFront = (RelativeLayout) view.findViewById(R.id.icon_front);
            iconImp = (ImageView) view.findViewById(R.id.icon_star);
            imgProfile = (ImageView) view.findViewById(R.id.icon_profile);
            messageContainer = (LinearLayout) view.findViewById(R.id.message_container);
            iconContainer = (RelativeLayout) view.findViewById(R.id.icon_container);
            imgBijlage = (ImageView) view.findViewById(R.id.icon_attachement);
            view.setOnLongClickListener(this);
        }

        @Override
        public boolean onLongClick(View view) {
            listener.onRowLongClicked(getAdapterPosition());
            view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
            return true;
        }
    }

    public MessagesAdapter(Context mContext, List<Message> messages, MessageAdapterListener listener) {
        this.mContext = mContext;
        this.messages = messages;
        this.listener = listener;
        selectedItems = new SparseBooleanArray();
        animationItemsIndex = new SparseBooleanArray();
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.message_list_row, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        Message message = messages.get(position);

        // displaying text view data
        holder.from.setText(message.getFrom().getEmailAddress().getName());
        holder.subject.setText(message.getSubject());
        holder.message.setText(message.getBodyPreview());
        System.out.println("EMAIL: " + position + " HAS ATTACHEMENT: " + message.getHasAttachments());
        setBijlage(message, holder);
        try {
            setDate(message, holder);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        // displaying the first letter of From in icon text
        holder.iconText.setText(message.getFrom().getEmailAddress().getName().substring(0, 1));

        // change the row state to activated
        holder.itemView.setActivated(selectedItems.get(position, false));

        // change the font style depending on message read status
        applyReadStatus(holder, message);

        // handle message star
        applyImportant(holder, message);

        // handle icon animation
        applyIconAnimation(holder, position);

        // display profile image
        applyProfilePicture(holder, message);

        // apply click events
        applyClickEvents(holder, position);
    }

    private void setDate(Message message, MyViewHolder holder) throws ParseException {
        String stringDate = message.getReceivedDateTime();
        String COMPARE_FORMAT = "yyyy/MM/dd";
        String OUTPUT_FORMAT_NOT_TODAY = "dd MMM";
        String JSON_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
        SimpleDateFormat dateFormat = new SimpleDateFormat(COMPARE_FORMAT);
        SimpleDateFormat formatter = new SimpleDateFormat(JSON_FORMAT);
        SimpleDateFormat defaultFormat = new SimpleDateFormat(OUTPUT_FORMAT_NOT_TODAY);

        //today date (check if today)
        Date today = new Date();
        String currentDate = dateFormat.format(today);
        //hours (if today
        Date date = formatter.parse(stringDate);
        formatter.applyPattern(COMPARE_FORMAT);
        String mailDate = formatter.format(date);
        //dd/month (if not today)

        boolean is24 = DateFormat.is24HourFormat(mContext);

        if (mailDate.equals(currentDate)) {
            if (is24) {
                SimpleDateFormat outputFormat = new SimpleDateFormat("HH:mm");
                holder.timestamp.setText(outputFormat.format(date));
            } else {
                SimpleDateFormat outputFormat = new SimpleDateFormat("hh:mm a");
                holder.timestamp.setText(outputFormat.format(date));
            }
        } else {
            holder.timestamp.setText(defaultFormat.format(date));
        }
    }

    private void setBijlage(Message message, MyViewHolder holder){
        //set bijlage
        if (message.getHasAttachments().toLowerCase().equals("true")){
            holder.imgBijlage.setImageResource(R.drawable.ic_bijlage);
        }
    }

    private void applyClickEvents(MyViewHolder holder, final int position) {
        holder.iconContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onIconClicked(position);
            }
        });

        holder.iconImp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onIconImportantClicked(position);
            }
        });

        holder.messageContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onMessageRowClicked(position);
            }
        });

        holder.messageContainer.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                listener.onRowLongClicked(position);
                view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
                return true;
            }
        });
    }

    private void applyProfilePicture(MyViewHolder holder, Message message) {
            holder.imgProfile.setImageResource(R.drawable.bg_circle);
            holder.imgProfile.setColorFilter(message.getColor());
            holder.iconText.setVisibility(View.VISIBLE);

    }

    private void applyIconAnimation(MyViewHolder holder, int position) {
        if (selectedItems.get(position, false)) {
            holder.iconFront.setVisibility(View.GONE);
            resetIconYAxis(holder.iconBack);
            holder.iconBack.setVisibility(View.VISIBLE);
            holder.iconBack.setAlpha(1);
            if (currentSelectedIndex == position) {
                FlipAnimator.flipView(mContext, holder.iconBack, holder.iconFront, true);
                resetCurrentIndex();
            }
        } else {
            holder.iconBack.setVisibility(View.GONE);
            resetIconYAxis(holder.iconFront);
            holder.iconFront.setVisibility(View.VISIBLE);
            holder.iconFront.setAlpha(1);
            if ((reverseAllAnimations && animationItemsIndex.get(position, false)) || currentSelectedIndex == position) {
                FlipAnimator.flipView(mContext, holder.iconBack, holder.iconFront, false);
                resetCurrentIndex();
            }
        }
    }

    // As the views will be reused, sometimes the icon appears as
    // flipped because older view is reused. Reset the Y-axis to 0
    private void resetIconYAxis(View view) {
        if (view.getRotationY() != 0) {
            view.setRotationY(0);
        }
    }

    public void resetAnimationIndex() {
        reverseAllAnimations = false;
        animationItemsIndex.clear();
    }

    @Override
    public long getItemId(int position) {
        return messages.get(position).getAutoId();
    }

    private void applyImportant(MyViewHolder holder, Message message) {
        if (message.getImportance().toLowerCase().equals("high")) {
            holder.iconImp.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_star_black_24dp));
            holder.iconImp.setColorFilter(ContextCompat.getColor(mContext, R.color.icon_tint_selected));
        } else {
            holder.iconImp.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_star_border_black_24dp));
            holder.iconImp.setColorFilter(ContextCompat.getColor(mContext, R.color.icon_tint_normal));
        }
    }

    private void applyReadStatus(MyViewHolder holder, Message message) {
        if (message.getIsRead().toLowerCase().equals("true")) {
            holder.from.setTypeface(null, Typeface.NORMAL);
            holder.subject.setTypeface(null, Typeface.NORMAL);
            holder.from.setTextColor(ContextCompat.getColor(mContext, R.color.subject));
            holder.subject.setTextColor(ContextCompat.getColor(mContext, R.color.message));
        } else {
            holder.from.setTypeface(null, Typeface.BOLD);
            holder.subject.setTypeface(null, Typeface.BOLD);
            holder.from.setTextColor(ContextCompat.getColor(mContext, R.color.from));
            holder.subject.setTextColor(ContextCompat.getColor(mContext, R.color.subject));
        }
    }

    @Override
    public int getItemCount() {
        return messages.size();
    }

    public void toggleSelection(int pos) {
        currentSelectedIndex = pos;
        if (selectedItems.get(pos, false)) {
            selectedItems.delete(pos);
            animationItemsIndex.delete(pos);
        } else {
            selectedItems.put(pos, true);
            animationItemsIndex.put(pos, true);
        }
        notifyItemChanged(pos);
    }

    public void clearSelections() {
        reverseAllAnimations = true;
        selectedItems.clear();
        notifyDataSetChanged();
    }

    public int getSelectedItemCount() {
        return selectedItems.size();
    }

    public List<Integer> getSelectedItems() {
        List<Integer> items =
                new ArrayList<>(selectedItems.size());
        for (int i = 0; i < selectedItems.size(); i++) {
            items.add(selectedItems.keyAt(i));
        }
        return items;
    }

    public void removeData(int position) {
        messages.remove(position);
        resetCurrentIndex();
    }

    private void resetCurrentIndex() {
        currentSelectedIndex = -1;
    }

    public interface MessageAdapterListener {
        void onIconClicked(int position);

        void onIconImportantClicked(int position);

        void onMessageRowClicked(int position);

        void onRowLongClicked(int position);
    }
}
</code>```

答:
That's occours because the recyclerView reuses the references of the rows and in your case, some rows doesnt have any reference in holder.imgBijlage, causing missbehavior.
To solve this, put holder.imgBijlage.setImageResource(R.drawable.ic_bijlage); inside onBindViewHolder and change setBijlage to:

```<code> if (message.getHasAttachments().toLowerCase().equals("true")){
        holder.imgBijlage.setVisibility(View.VISIBLE);
 }else {
        holder.imgBijlage.setVisibility(View.INVISIBLE);
 }
</code>```

Your icon will be hidden when there is no attachement

Body:
I have an app that displays my e-mail via microsoft graph api.
Everything but 1 things i working fine so far. When the list first loads in, all info is correctly displayed, but when i scroll down, then back up. The imageview of the attachement sits on the wrong rows. It just displays on rows without attachement. In the adapter i have an if clausule which says to only show the image in the row if the hasAttachement value is "true".. I really don't get why it is redrawin the image in the wrongs rows..

The method where i set the attachement is called:
setBijlage() in MessagesAdapter

EDIT: If i click the row in my app, that row displays correctly again (gains an icon if it has attachement, and deletes it if it doesn't)

MailActivity.java

public class MailActivity extends AppCompatActivityRest implements SwipeRefreshLayout.OnRefreshListener, MessagesAdapter.MessageAdapterListener {

    private String currentFolder;
    private String currentUser;
    private List<Message> messages = new ArrayList<>();
    private RecyclerView recyclerView;
    private MessagesAdapter mAdapter;
    private SwipeRefreshLayout swipeRefreshLayout;
    private ActionModeCallback actionModeCallback;
    private ActionMode actionMode;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_mail);
        super.onCreate(savedInstanceState);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        currentFolder = getString(R.string.inbox);
        currentUser = getIntent().getStringExtra("USER_EMAIL");
        setActionBarMail(currentFolder, currentUser);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
        swipeRefreshLayout.setOnRefreshListener(this);

        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));

        actionModeCallback = new ActionModeCallback();

        // show loader and fetch messages
        swipeRefreshLayout.post(
                new Runnable() {
                    @Override
                    public void run() {
                        getAllMails(15);
                    }
                }
        );
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_search) {
            Toast.makeText(getApplicationContext(), "Search...", Toast.LENGTH_SHORT).show();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void processResponse(OutlookObjectCall outlookObjectCall, JSONObject response) {

        switch (outlookObjectCall) {
            case READUSER: {
                System.out.println("reading user");
            } break;
            case READMAIL: {
                messages.clear();

                JSONObject list = response;
                try {
                    JSONArray mails = list.getJSONArray("value");
                    Type listType = new TypeToken<List<Message>>() {
                    }.getType();
                    messages = new Gson().fromJson(String.valueOf(mails), listType);
                    for (Message message : messages) {
                        message.setColor(getRandomMaterialColor("400"));
                    }
                    System.out.println(messages.get(2).getFrom().getEmailAddress().getName());

                    mAdapter = new MessagesAdapter(this, messages, this);
                    recyclerView.setAdapter(mAdapter);

                } catch (JSONException e) {
                    e.printStackTrace();
                }

                mAdapter.notifyDataSetChanged();
                swipeRefreshLayout.setRefreshing(false);

            }
            break;
            case SENDMAIL: {
                System.out.println("Just send a mail." );
            }
        }
    }

    @Override
    public void onRefresh() {
        // swipe refresh is performed, fetch the messages again
        getAllMails(15);
    }

    @Override
    public void onIconClicked(int position) {
        if (actionMode == null) {
            actionMode = startSupportActionMode(actionModeCallback);
        }

        toggleSelection(position);
    }

    @Override
    public void onIconImportantClicked(int position) {
        // Star icon is clicked,
        // mark the message as important
        Message message = messages.get(position);
        message.setImportance("normal");
        messages.set(position, message);
        mAdapter.notifyDataSetChanged();
    }

    @Override
    public void onMessageRowClicked(int position) {
        // verify whether action mode is enabled or not
        // if enabled, change the row state to activated
        if (mAdapter.getSelectedItemCount() > 0) {
            enableActionMode(position);
        } else {
            // read the message which removes bold from the row
            Message message = messages.get(position);
            message.setIsRead("true");
            messages.set(position, message);
            mAdapter.notifyDataSetChanged();

            Toast.makeText(getApplicationContext(), "Read: " + message.getBodyPreview(), Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRowLongClicked(int position) {
        // long press is performed, enable action mode
        enableActionMode(position);
    }

    private void enableActionMode(int position) {
        if (actionMode == null) {
            actionMode = startSupportActionMode(actionModeCallback);
        }
        toggleSelection(position);
    }

    private void toggleSelection(int position) {
        mAdapter.toggleSelection(position);
        int count = mAdapter.getSelectedItemCount();

        if (count == 0) {
            actionMode.finish();
        } else {
            actionMode.setTitle(String.valueOf(count));
            actionMode.invalidate();
        }
    }

    private class ActionModeCallback implements ActionMode.Callback {
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            mode.getMenuInflater().inflate(R.menu.menu_action_mode, menu);

            // disable swipe refresh if action mode is enabled
            swipeRefreshLayout.setEnabled(false);
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()) {
                case R.id.action_delete:
                    // delete all the selected messages
                    deleteMessages();
                    mode.finish();
                    return true;

                default:
                    return false;
            }
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            mAdapter.clearSelections();
            swipeRefreshLayout.setEnabled(true);
            actionMode = null;
            recyclerView.post(new Runnable() {
                @Override
                public void run() {
                    mAdapter.resetAnimationIndex();
                    // mAdapter.notifyDataSetChanged();
                }
            });
        }
    }

    // deleting the messages from recycler view
    private void deleteMessages() {
        mAdapter.resetAnimationIndex();
        List<Integer> selectedItemPositions =
                mAdapter.getSelectedItems();
        for (int i = selectedItemPositions.size() - 1; i >= 0; i--) {
            mAdapter.removeData(selectedItemPositions.get(i));
        }
        mAdapter.notifyDataSetChanged();
    }

    private void setActionBarMail(String title, String subtitle) {
        getSupportActionBar().setTitle(title);
        getSupportActionBar().setSubtitle(subtitle);
    }

    private void getAllMails(int aantalMails) {
        swipeRefreshLayout.setRefreshing(true);
        try {
            new GraphAPI().getRequest(OutlookObjectCall.READMAIL, this, "/inbox/messages?$top=" + aantalMails);

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private int getRandomMaterialColor(String typeColor) {
        int returnColor = Color.GRAY;
        int arrayId = getResources().getIdentifier("mdcolor_" + typeColor, "array", getPackageName());

        if (arrayId != 0) {
            TypedArray colors = getResources().obtainTypedArray(arrayId);
            int index = (int) (Math.random() * colors.length());
            returnColor = colors.getColor(index, Color.GRAY);
            colors.recycle();
        }
        return returnColor;
    }

MessagesAdapter.java

public class MessagesAdapter extends RecyclerView.Adapter<MessagesAdapter.MyViewHolder> {
    private Context mContext;
    private List<Message> messages;
    private MessageAdapterListener listener;
    private SparseBooleanArray selectedItems;

    // array used to perform multiple animation at once
    private SparseBooleanArray animationItemsIndex;
    private boolean reverseAllAnimations = false;

    // index is used to animate only the selected row
    // dirty fix, find a better solution
    private static int currentSelectedIndex = -1;

    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener {
        public TextView from, subject, message, iconText, timestamp;
        public ImageView iconImp, imgProfile, imgBijlage;
        public LinearLayout messageContainer;
        public RelativeLayout iconContainer, iconBack, iconFront;

        public MyViewHolder(View view) {
            super(view);
            from = (TextView) view.findViewById(R.id.from);
            subject = (TextView) view.findViewById(R.id.txt_primary);
            message = (TextView) view.findViewById(R.id.txt_secondary);
            iconText = (TextView) view.findViewById(R.id.icon_text);
            timestamp = (TextView) view.findViewById(R.id.timestamp);
            iconBack = (RelativeLayout) view.findViewById(R.id.icon_back);
            iconFront = (RelativeLayout) view.findViewById(R.id.icon_front);
            iconImp = (ImageView) view.findViewById(R.id.icon_star);
            imgProfile = (ImageView) view.findViewById(R.id.icon_profile);
            messageContainer = (LinearLayout) view.findViewById(R.id.message_container);
            iconContainer = (RelativeLayout) view.findViewById(R.id.icon_container);
            imgBijlage = (ImageView) view.findViewById(R.id.icon_attachement);
            view.setOnLongClickListener(this);
        }

        @Override
        public boolean onLongClick(View view) {
            listener.onRowLongClicked(getAdapterPosition());
            view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
            return true;
        }
    }

    public MessagesAdapter(Context mContext, List<Message> messages, MessageAdapterListener listener) {
        this.mContext = mContext;
        this.messages = messages;
        this.listener = listener;
        selectedItems = new SparseBooleanArray();
        animationItemsIndex = new SparseBooleanArray();
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.message_list_row, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        Message message = messages.get(position);

        // displaying text view data
        holder.from.setText(message.getFrom().getEmailAddress().getName());
        holder.subject.setText(message.getSubject());
        holder.message.setText(message.getBodyPreview());
        System.out.println("EMAIL: " + position + " HAS ATTACHEMENT: " + message.getHasAttachments());
        setBijlage(message, holder);
        try {
            setDate(message, holder);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        // displaying the first letter of From in icon text
        holder.iconText.setText(message.getFrom().getEmailAddress().getName().substring(0, 1));

        // change the row state to activated
        holder.itemView.setActivated(selectedItems.get(position, false));

        // change the font style depending on message read status
        applyReadStatus(holder, message);

        // handle message star
        applyImportant(holder, message);

        // handle icon animation
        applyIconAnimation(holder, position);

        // display profile image
        applyProfilePicture(holder, message);

        // apply click events
        applyClickEvents(holder, position);
    }

    private void setDate(Message message, MyViewHolder holder) throws ParseException {
        String stringDate = message.getReceivedDateTime();
        String COMPARE_FORMAT = "yyyy/MM/dd";
        String OUTPUT_FORMAT_NOT_TODAY = "dd MMM";
        String JSON_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
        SimpleDateFormat dateFormat = new SimpleDateFormat(COMPARE_FORMAT);
        SimpleDateFormat formatter = new SimpleDateFormat(JSON_FORMAT);
        SimpleDateFormat defaultFormat = new SimpleDateFormat(OUTPUT_FORMAT_NOT_TODAY);

        //today date (check if today)
        Date today = new Date();
        String currentDate = dateFormat.format(today);
        //hours (if today
        Date date = formatter.parse(stringDate);
        formatter.applyPattern(COMPARE_FORMAT);
        String mailDate = formatter.format(date);
        //dd/month (if not today)

        boolean is24 = DateFormat.is24HourFormat(mContext);

        if (mailDate.equals(currentDate)) {
            if (is24) {
                SimpleDateFormat outputFormat = new SimpleDateFormat("HH:mm");
                holder.timestamp.setText(outputFormat.format(date));
            } else {
                SimpleDateFormat outputFormat = new SimpleDateFormat("hh:mm a");
                holder.timestamp.setText(outputFormat.format(date));
            }
        } else {
            holder.timestamp.setText(defaultFormat.format(date));
        }
    }

    private void setBijlage(Message message, MyViewHolder holder){
        //set bijlage
        if (message.getHasAttachments().toLowerCase().equals("true")){
            holder.imgBijlage.setImageResource(R.drawable.ic_bijlage);
        }
    }

    private void applyClickEvents(MyViewHolder holder, final int position) {
        holder.iconContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onIconClicked(position);
            }
        });

        holder.iconImp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onIconImportantClicked(position);
            }
        });

        holder.messageContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onMessageRowClicked(position);
            }
        });

        holder.messageContainer.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                listener.onRowLongClicked(position);
                view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
                return true;
            }
        });
    }

    private void applyProfilePicture(MyViewHolder holder, Message message) {
            holder.imgProfile.setImageResource(R.drawable.bg_circle);
            holder.imgProfile.setColorFilter(message.getColor());
            holder.iconText.setVisibility(View.VISIBLE);

    }

    private void applyIconAnimation(MyViewHolder holder, int position) {
        if (selectedItems.get(position, false)) {
            holder.iconFront.setVisibility(View.GONE);
            resetIconYAxis(holder.iconBack);
            holder.iconBack.setVisibility(View.VISIBLE);
            holder.iconBack.setAlpha(1);
            if (currentSelectedIndex == position) {
                FlipAnimator.flipView(mContext, holder.iconBack, holder.iconFront, true);
                resetCurrentIndex();
            }
        } else {
            holder.iconBack.setVisibility(View.GONE);
            resetIconYAxis(holder.iconFront);
            holder.iconFront.setVisibility(View.VISIBLE);
            holder.iconFront.setAlpha(1);
            if ((reverseAllAnimations && animationItemsIndex.get(position, false)) || currentSelectedIndex == position) {
                FlipAnimator.flipView(mContext, holder.iconBack, holder.iconFront, false);
                resetCurrentIndex();
            }
        }
    }

    // As the views will be reused, sometimes the icon appears as
    // flipped because older view is reused. Reset the Y-axis to 0
    private void resetIconYAxis(View view) {
        if (view.getRotationY() != 0) {
            view.setRotationY(0);
        }
    }

    public void resetAnimationIndex() {
        reverseAllAnimations = false;
        animationItemsIndex.clear();
    }

    @Override
    public long getItemId(int position) {
        return messages.get(position).getAutoId();
    }

    private void applyImportant(MyViewHolder holder, Message message) {
        if (message.getImportance().toLowerCase().equals("high")) {
            holder.iconImp.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_star_black_24dp));
            holder.iconImp.setColorFilter(ContextCompat.getColor(mContext, R.color.icon_tint_selected));
        } else {
            holder.iconImp.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_star_border_black_24dp));
            holder.iconImp.setColorFilter(ContextCompat.getColor(mContext, R.color.icon_tint_normal));
        }
    }

    private void applyReadStatus(MyViewHolder holder, Message message) {
        if (message.getIsRead().toLowerCase().equals("true")) {
            holder.from.setTypeface(null, Typeface.NORMAL);
            holder.subject.setTypeface(null, Typeface.NORMAL);
            holder.from.setTextColor(ContextCompat.getColor(mContext, R.color.subject));
            holder.subject.setTextColor(ContextCompat.getColor(mContext, R.color.message));
        } else {
            holder.from.setTypeface(null, Typeface.BOLD);
            holder.subject.setTypeface(null, Typeface.BOLD);
            holder.from.setTextColor(ContextCompat.getColor(mContext, R.color.from));
            holder.subject.setTextColor(ContextCompat.getColor(mContext, R.color.subject));
        }
    }

    @Override
    public int getItemCount() {
        return messages.size();
    }

    public void toggleSelection(int pos) {
        currentSelectedIndex = pos;
        if (selectedItems.get(pos, false)) {
            selectedItems.delete(pos);
            animationItemsIndex.delete(pos);
        } else {
            selectedItems.put(pos, true);
            animationItemsIndex.put(pos, true);
        }
        notifyItemChanged(pos);
    }

    public void clearSelections() {
        reverseAllAnimations = true;
        selectedItems.clear();
        notifyDataSetChanged();
    }

    public int getSelectedItemCount() {
        return selectedItems.size();
    }

    public List<Integer> getSelectedItems() {
        List<Integer> items =
                new ArrayList<>(selectedItems.size());
        for (int i = 0; i < selectedItems.size(); i++) {
            items.add(selectedItems.keyAt(i));
        }
        return items;
    }

    public void removeData(int position) {
        messages.remove(position);
        resetCurrentIndex();
    }

    private void resetCurrentIndex() {
        currentSelectedIndex = -1;
    }

    public interface MessageAdapterListener {
        void onIconClicked(int position);

        void onIconImportantClicked(int position);

        void onMessageRowClicked(int position);

        void onRowLongClicked(int position);
    }
}

Body:
That's occours because the recyclerView reuses the references of the rows and in your case, some rows doesnt have any reference in holder.imgBijlage, causing missbehavior.
To solve this, put holder.imgBijlage.setImageResource(R.drawable.ic_bijlage); inside onBindViewHolder and change setBijlage to:

 if (message.getHasAttachments().toLowerCase().equals("true")){
        holder.imgBijlage.setVisibility(View.VISIBLE);
 }else {
        holder.imgBijlage.setVisibility(View.INVISIBLE);
 }

Your icon will be hidden when there is no attachement


问:
File is downloading without extension?
I am trying to download a PDF file but when i click on the download button it downloads the file without extension. That is there is no PDF extension with the file when i download it!

Action:

```<code>public function executeDownload(sfWebRequest $request) {
        $this->ebook_id = $request->getParameter('ebook', $this->default_ebook);
        $this->ebook = $this->ebooks[$this->ebook_id];

        if (!is_array($this->ebook))
            return;

        // Allow user to download the ebook (and make sure there is no other output)
        $this->setLayout(false);
        sfConfig::set('sf_web_debug', false);
        $content = sfConfig::get('sf_root_dir').'/web'.$this->ebook['ebook'];
        //echo "<p>PDF: $content</p>"; var_export(filesize($content));exit;
        // Check if the file exists
        $this->forward404Unless(file_exists($content));

        // Record the download for this eBook
        $c = new Criteria();
        $c->add(EbookDownloadsPeer::EBOOK_SLUG, $this->ebook_id);
        $ebook = EbookDownloadsPeer::doSelectOne($c);

        $ebook->setLastDownloaded(time());
        $ebook->setEbookDownloads($ebook->getEbookDownloads()+1);
        $ebook->save();

        // Adding the file to the Response object
        $content_type = (in_array($this->ebook_id, array('readyourbody', 'whyamifatigued', 'nutrientsfromfood'))) ? 'application/pdf': 'image/jpeg';

        $this->getResponse()->clearHttpHeaders();
        $this->getResponse()->setHttpHeader('Pragma: public', true);
        $this->getResponse()->setContentType($content_type);
        $this->getResponse()->setHttpHeader('Content-Disposition', 'attachment; filename="'.$this->ebook['name'].'"');
        $this->getResponse()->setHttpHeader('Content-Length', filesize($content));
        $this->getResponse()->sendHttpHeaders();
        $this->getResponse()->setContent(readfile($content));

        return sfView::NONE;
    }
</code>```

Template:

```<code> <div class="cyan3 txt-large txt-c">
      <?php echo link_to('Click here','ebooks/download?ebook='.$ebook_id,'') ?> to <?php echo link_to('download it now','ebooks/download?ebook='.$ebook_id,'') ?>!
        </div><br />
    </div>
</code>```

答:
Please append .pdf as extension to your ebook name.

It will work.

Title: File is downloading without extension?

Body:
I am trying to download a PDF file but when i click on the download button it downloads the file without extension. That is there is no PDF extension with the file when i download it!

Action:

public function executeDownload(sfWebRequest $request) {
        $this->ebook_id = $request->getParameter('ebook', $this->default_ebook);
        $this->ebook = $this->ebooks[$this->ebook_id];

        if (!is_array($this->ebook))
            return;

        // Allow user to download the ebook (and make sure there is no other output)
        $this->setLayout(false);
        sfConfig::set('sf_web_debug', false);
        $content = sfConfig::get('sf_root_dir').'/web'.$this->ebook['ebook'];
        //echo "
PDF: $content
"; var_export(filesize($content));exit;
        // Check if the file exists
        $this->forward404Unless(file_exists($content));

        // Record the download for this eBook
        $c = new Criteria();
        $c->add(EbookDownloadsPeer::EBOOK_SLUG, $this->ebook_id);
        $ebook = EbookDownloadsPeer::doSelectOne($c);

        $ebook->setLastDownloaded(time());
        $ebook->setEbookDownloads($ebook->getEbookDownloads()+1);
        $ebook->save();

        // Adding the file to the Response object
        $content_type = (in_array($this->ebook_id, array('readyourbody', 'whyamifatigued', 'nutrientsfromfood'))) ? 'application/pdf': 'image/jpeg';

        $this->getResponse()->clearHttpHeaders();
        $this->getResponse()->setHttpHeader('Pragma: public', true);
        $this->getResponse()->setContentType($content_type);
        $this->getResponse()->setHttpHeader('Content-Disposition', 'attachment; filename="'.$this->ebook['name'].'"');
        $this->getResponse()->setHttpHeader('Content-Length', filesize($content));
        $this->getResponse()->sendHttpHeaders();
        $this->getResponse()->setContent(readfile($content));

        return sfView::NONE;
    }

Template:

      <?php echo link_to('Click here','ebooks/download?ebook='.$ebook_id,'') ?> to <?php echo link_to('download it now','ebooks/download?ebook='.$ebook_id,'') ?>!


问:
Perl XML::Compile "error: too few 'any' elements, got 0 for minimum 1 at person#any"
somehow could not get XML::Compile working with very simple XSD file that contains

```<code><xs:any />
</code>```

without it it works perfect. Looks like I am missing something very simple.

Here is test1.xsd file:

```<code><?xml version="1.0" encoding="UTF-8"?>
<xs:schema  xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="firstname" type="xs:string"/>
      <xs:element name="lastname" type="xs:string"/>
      <xs:any />
    </xs:sequence>
  </xs:complexType>
</xs:element></xs:schema>
</code>```

Here is test1.pl:

```<code>#!/usr/bin/perl

use warnings;
use strict;

use XML::Compile::Schema;
use XML::LibXML::Reader;

my @specs  = ('test1.xsd');
my $schema = XML::Compile::Schema->new(\@specs);

my $data =
{
     firstname => 'Alex',
     lastname => 'Muster',
     email => 'amuster@abc.com',
};

my $doc    = XML::LibXML::Document->new('1.0', 'UTF-8');
my $write  = $schema->compile(WRITER => 'person');
my $xml    = $write->($doc, $data);

$doc->setDocumentElement($xml);
print $doc->toString(1);
</code>```

Error message is:

```<code>error: too few 'any' elements, got 0 for minimum 1 at person#any
</code>```

答:
You can't put <xs:any /> into a schema and expect the writer to randomly come up with some sort of XML element just to make it valid

Every item in the schema must have a name so that data for it can be provided

If you remove the <xs:any /> you will get this semi-successful result

mistake: tag `email' not used at person
<?xml version="1.0" encoding="UTF-8"?>
<person>
  <firstname>Alex</firstname>
  <lastname>Muster</lastname>
</person>
```

<p>which is saying that it has nowhere to put the <code>email</code> information. The other elements, however, are created correctly</p>

<p>If you have in mind something specific you want to be generated for the <code><xs:any /></code> then it looks like you can
specify the behaviour you want for the <code>any_type</code> option. The documentation says this about it</p>

<pre class="lang-none prettyprint-override"><code>any_type => CODE
       [1.07] how to handle "anyType" type elements. Supported values
       depends on the backend, specializations of
       XML::Compile::Translate.
</code>```

I'm sorry, the documentation for XML::Compile::Translate says "Currently only supported for the reader. " so you can't specify what is generated for the <xs:any /> element when writing XML

Body:
somehow could not get XML::Compile working with very simple XSD file that contains

<xs:any />

without it it works perfect. Looks like I am missing something very simple.

Here is test1.xsd file:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema  xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="firstname" type="xs:string"/>
      <xs:element name="lastname" type="xs:string"/>
      <xs:any />
    </xs:sequence>
  </xs:complexType>
</xs:element></xs:schema>

Here is test1.pl:

#!/usr/bin/perl

use warnings;
use strict;

use XML::Compile::Schema;
use XML::LibXML::Reader;

my @specs  = ('test1.xsd');
my $schema = XML::Compile::Schema->new(\@specs);

my $data =
{
     firstname => 'Alex',
     lastname => 'Muster',
     email => 'amuster@abc.com',
};

my $doc    = XML::LibXML::Document->new('1.0', 'UTF-8');
my $write  = $schema->compile(WRITER => 'person');
my $xml    = $write->($doc, $data);

$doc->setDocumentElement($xml);
print $doc->toString(1);

Error message is:

error: too few 'any' elements, got 0 for minimum 1 at person#any

Body:
You can't put <xs:any /> into a schema and expect the writer to randomly come up with some sort of XML element just to make it valid

Every item in the schema must have a name so that data for it can be provided

If you remove the <xs:any /> you will get this semi-successful result

mistake: tag `email' not used at person
<?xml version="1.0" encoding="UTF-8"?>
<person>
  <firstname>Alex</firstname>
  <lastname>Muster</lastname>
</person>

which is saying that it has nowhere to put the email information. The other elements, however, are created correctly

If you have in mind something specific you want to be generated for the <xs:any /> then it looks like you can
specify the behaviour you want for the any_type option. The documentation says this about it

any_type => CODE
       [1.07] how to handle "anyType" type elements. Supported values
       depends on the backend, specializations of
       XML::Compile::Translate.

I'm sorry, the documentation for XML::Compile::Translate says "Currently only supported for the reader. " so you can't specify what is generated for the <xs:any /> element when writing XML


问:
Bulk collect into array and error handling in DBMS_OUTPUT
I am copying data from table A to table B. In table A I have four columns for countries (EN, ES, RU, UK). The column per country is a separate row in table B. In addition, each row in table B must be duplicated and receive the next sequence number.

Table A - my cursor

```<code>+---------+---------+---------+---------+---------+
| Company |   EN    |   ES    |   RU    |   UK    |
+---------+---------+---------+---------+---------+
| Intel   | 123 345 | 453 343 | 444 101 | 110 232 |
+---------+---------+---------+---------+---------+
</code>```

Table B

```<code>+---------+---------+-----+
| Company | Country | SEQ |
+---------+---------+-----+
| Intel   | 123 345 |   0 |
| Intel   | 123 345 |   1 |
| Intel   | 453 343 |   0 |
| Intel   | 453 343 |   1 |
| INTEL   | 444 101 |   0 |
| INTEL   | 444 101 |   1 |
| INTEL   | 110 232 |   0 |
| INTEL   | 110 232 |   1 |
+---------+---------+-----+
</code>```

In table A I have 1,000,000 rows.

In Table B, I should have 1,000,000 (rows) x 4 (country) x 2 (seq) = 8,000,000.

I prepared the procedure for inserting data.

```<code>BEGIN

OPEN my_cursor;
    LOOP
        EXIT WHEN my_cursor%notfound;
        FETCH my_cursor BULK COLLECT INTO TAB LIMIT 500;

        FOR y in 0..1 LOOP

                FORALL x IN TAB.first..TAB.last
                    INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."EN", y);

                FORALL x IN TAB.first..TAB.last
                    INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."ES", y);

                FORALL x IN TAB.first..TAB.last
                    INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."RU", y);

                FORALL x IN TAB.first..TAB.last
                    INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."UK", y);

        END LOOP;

        COMMIT;
    END LOOP;
CLOSE my_cursor;

END;
</code>```

In the case of a DML error in table B, I have to return the value of variables from array (tab) together with the error code in DBMS_OUTPUT
for example:

```<code>DBMS_OUTPUT.PUT_LINE(tab(x)."company" || ' ' || tab(x)."UK" || SQLERRM);
</code>```

Is it possible to handle such errors? How can I implement such a solution?
.

答:
Yes, you can handle such errors and continue with all the insert using SAVE EXCEPTIONS with FORALL as below :
PLSQL raises ORA:24381 after all the statement is executed.

```<code>BEGIN
FORALL x IN TAB.first..TAB.last SAVE EXCEPTIONS
                    INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."EN", y);
EXCEPTION
WHEN OTHERS THEN
 IF sqlcode = -24381
     FOR indx IN 1 .. SQL%BULK_EXCEPTIONS.COUNT
         LOOP
            DBMS_OUTPUT.put_line (
                  SQL%BULK_EXCEPTIONS (indx).ERROR_INDEX
               || ‘: ‘
               || SQL%BULK_EXCEPTIONS (indx).ERROR_CODE);
         END LOOP;
else
raise;
end if;
END;
</code>```

Body:
I am copying data from table A to table B. In table A I have four columns for countries (EN, ES, RU, UK). The column per country is a separate row in table B. In addition, each row in table B must be duplicated and receive the next sequence number.

Table A - my cursor

+---------+---------+---------+---------+---------+
| Company |   EN    |   ES    |   RU    |   UK    |
+---------+---------+---------+---------+---------+
| Intel   | 123 345 | 453 343 | 444 101 | 110 232 |
+---------+---------+---------+---------+---------+

Table B

+---------+---------+-----+
| Company | Country | SEQ |
+---------+---------+-----+
| Intel   | 123 345 |   0 |
| Intel   | 123 345 |   1 |
| Intel   | 453 343 |   0 |
| Intel   | 453 343 |   1 |
| INTEL   | 444 101 |   0 |
| INTEL   | 444 101 |   1 |
| INTEL   | 110 232 |   0 |
| INTEL   | 110 232 |   1 |
+---------+---------+-----+

In table A I have 1,000,000 rows.

In Table B, I should have 1,000,000 (rows) x 4 (country) x 2 (seq) = 8,000,000.

I prepared the procedure for inserting data.

BEGIN

OPEN my_cursor;
    LOOP
        EXIT WHEN my_cursor%notfound;
        FETCH my_cursor BULK COLLECT INTO TAB LIMIT 500;

        FOR y in 0..1 LOOP

                FORALL x IN TAB.first..TAB.last
                    INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."EN", y);

                FORALL x IN TAB.first..TAB.last
                    INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."ES", y);

                FORALL x IN TAB.first..TAB.last
                    INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."RU", y);

                FORALL x IN TAB.first..TAB.last
                    INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."UK", y);

        END LOOP;

        COMMIT;
    END LOOP;
CLOSE my_cursor;

END;

In the case of a DML error in table B, I have to return the value of variables from array (tab) together with the error code in DBMS_OUTPUT
for example:

DBMS_OUTPUT.PUT_LINE(tab(x)."company" || ' ' || tab(x)."UK" || SQLERRM);

Is it possible to handle such errors? How can I implement such a solution?
.

Body:
Yes, you can handle such errors and continue with all the insert using SAVE EXCEPTIONS with FORALL as below :
PLSQL raises ORA:24381 after all the statement is executed.

BEGIN
FORALL x IN TAB.first..TAB.last SAVE EXCEPTIONS
                    INSERT INTO table_B ("company","country","seq") VALUES (tab(x)."company", tab(x)."EN", y);
EXCEPTION
WHEN OTHERS THEN
 IF sqlcode = -24381
     FOR indx IN 1 .. SQL%BULK_EXCEPTIONS.COUNT
         LOOP
            DBMS_OUTPUT.put_line (
                  SQL%BULK_EXCEPTIONS (indx).ERROR_INDEX
               || ‘: ‘
               || SQL%BULK_EXCEPTIONS (indx).ERROR_CODE);
         END LOOP;
else
raise;
end if;
END;


问:
Node.js app fails to connect using socket.io-client

Background

I have a Node.js server using socket.io that accepts connections from clients via HTTPS.

I know this server works as I am able to connect to it via browser.

Problem

The problem is that I can't create a node app to connect to this server as a client.

I am using the following code:

```<code>const io = require("socket.io-client");

const socket = io.connect("https://my.website.com:3002", { secure: true, reconnect: true });

socket.on("connect", function(){
    console.log("connected");
});

socket.on("disconnect", function(){
    console.log("disconnected");
});

socket.on("error", console.error);
</code>```

The server registers no connections, and this app logs no errors. It would seem that I am connecting to the wrong server, but this same URL works just fine when I use a browser.

Research

I have searched github and the official docs for an answer. Even similar questions from stackoverflow seem to not work:

Node.js client for a socket.io server

https://www.npmjs.com/package/socket.io-client

https://github.com/socketio/socket.io-client/issues/828

Question

What am I doing wrong ?

答:
Answer

After realising, that not all errors feed into the "error" event ( special thanks to @RolandStarke ) I found that I was having a consistent XHR pool request:

```<code>{ Error: xhr poll error
    at XHR.Transport.onError (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transport.js:64:13)
    at Request.<anonymous> (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transports/polling-xhr.js:128:10)
    at Request.Emitter.emit (/Users/pedro/Workspace/backend-stresser/node_modules/component-emitter/index.js:133:20)
    at Request.onError (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transports/polling-xhr.js:310:8)
    at Timeout._onTimeout (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transports/polling-xhr.js:257:18)
    at ontimeout (timers.js:469:11)
    at tryOnTimeout (timers.js:304:5)
    at Timer.listOnTimeout (timers.js:264:5) type: 'TransportError', description: 503 }
</code>```

Once I had this information, I made a quick search and found a solution to this issue, which seems to be a bug:

https://github.com/socketio/socket.io-client/issues/1097

The code I am now using is:

```<code>const socket = io.connect("https://my.website.com:3002", { secure: true, reconnection: true, rejectUnauthorized: false });
</code>```

And it works as expected.

Body:
Background

I have a Node.js server using socket.io that accepts connections from clients via HTTPS.

I know this server works as I am able to connect to it via browser.

Problem

The problem is that I can't create a node app to connect to this server as a client.

I am using the following code:

const io = require("socket.io-client");

const socket = io.connect("https://my.website.com:3002", { secure: true, reconnect: true });

socket.on("connect", function(){
    console.log("connected");
});

socket.on("disconnect", function(){
    console.log("disconnected");
});

socket.on("error", console.error);

The server registers no connections, and this app logs no errors. It would seem that I am connecting to the wrong server, but this same URL works just fine when I use a browser.

Research

I have searched github and the official docs for an answer. Even similar questions from stackoverflow seem to not work:

Node.js client for a socket.io server

https://www.npmjs.com/package/socket.io-client

https://github.com/socketio/socket.io-client/issues/828

Question

What am I doing wrong ?

Body:
Answer

After realising, that not all errors feed into the "error" event ( special thanks to @RolandStarke ) I found that I was having a consistent XHR pool request:

{ Error: xhr poll error
    at XHR.Transport.onError (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transport.js:64:13)
    at Request.<anonymous> (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transports/polling-xhr.js:128:10)
    at Request.Emitter.emit (/Users/pedro/Workspace/backend-stresser/node_modules/component-emitter/index.js:133:20)
    at Request.onError (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transports/polling-xhr.js:310:8)
    at Timeout._onTimeout (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transports/polling-xhr.js:257:18)
    at ontimeout (timers.js:469:11)
    at tryOnTimeout (timers.js:304:5)
    at Timer.listOnTimeout (timers.js:264:5) type: 'TransportError', description: 503 }

Once I had this information, I made a quick search and found a solution to this issue, which seems to be a bug:

https://github.com/socketio/socket.io-client/issues/1097

The code I am now using is:

const socket = io.connect("https://my.website.com:3002", { secure: true, reconnection: true, rejectUnauthorized: false });

And it works as expected.


问:
Is there a Zend Tool command for scaffolding?
Does Zend Tool have a zf command that does the same as this Ruby on Rails command:

```<code>ruby script/generate scaffold ModelName [field:type field:type ...]
</code>```

In other words, can Zend Tool create resources that already contain the code for CRUD actions?

答:
There is no official ZF Command to scaffold.

There are two proposals for this

http://framework.zend.com/wiki/display/ZFPROP/Zend_Controller_Front_Scaffold

http://framework.zend.com/wiki/display/ZFPROP/Zend_Controller_Scaffolding+-+Alex+Oroshchuk

The first one is from 2007 and does not seem to be maintainend any longer. The second one looks like it's more active.

Body:
Does Zend Tool have a zf command that does the same as this Ruby on Rails command:

ruby script/generate scaffold ModelName [field:type field:type ...]

In other words, can Zend Tool create resources that already contain the code for CRUD actions?