问:
Why is php handling for different than foreach?
I made an array $brands inside class Cars, the print_r output looks like this:

```<code>Array ( [0] => Array (  [id] => 1
                        [name] => 'Porsche'
                    )
        [1] => Array (  [id] => 2
                        [name] => 'Bugatti'
                    )
        [2] => Array (  [id] => 3
                        [name] => 'BMW'
                    )
    )
</code>```

But when I'd like to link to a certain brand, I don't want to use strtolower() to make a lowercased hyperlink. I would like to echo $cars->brands[$i]['url'] (instead of strtolower($cars->brands[$i]['name'])).

class Cars {

So I needed to create a for loop, to create the ['url'] key in the array. I thought that a foreach would work:

```<code>foreach ($this->brands as $brand => $row) {
    $row['url'] = strtolower($row['name']);
}
</code>```

But it didn't. Even this did not work: $row['name'] = strtolower($row['name']);.

But this worked, though:

```<code>for ($i = 0; $i < count($this->brands); $i++) {
    $this->brands[$i]['url'] = strtolower($this->brands[$i]['name']);
}
</code>```

}

My question here is: how? why?

答:
because you are overwriting array key('url').

$row is a local copy of $this->brands any changes to $row will not reflect on $this->brands.

change this

```<code>foreach ($this->brands as $brand => $row) {
    $row['url'] = strtolower($row['name']);
}
</code>```

with this

```<code>foreach ($this->brands as $brand => $row) {
    $this->brands[$brand]['url'] = strtolower($row['name']);
}
</code>```

Happy Coding.

Body:
I made an array $brands inside class Cars, the print_r output looks like this:

Array ( [0] => Array (  [id] => 1
                        [name] => 'Porsche'
                    )
        [1] => Array (  [id] => 2
                        [name] => 'Bugatti'
                    )
        [2] => Array (  [id] => 3
                        [name] => 'BMW'
                    )
    )

But when I'd like to link to a certain brand, I don't want to use strtolower() to make a lowercased hyperlink. I would like to echo $cars->brands[$i]['url'] (instead of strtolower($cars->brands[$i]['name'])).

class Cars {

So I needed to create a for loop, to create the ['url'] key in the array. I thought that a foreach would work:

foreach ($this->brands as $brand => $row) {
    $row['url'] = strtolower($row['name']);
}

But it didn't. Even this did not work: $row['name'] = strtolower($row['name']);.

But this worked, though:

for ($i = 0; $i < count($this->brands); $i++) {
    $this->brands[$i]['url'] = strtolower($this->brands[$i]['name']);
}

}

My question here is: how? why?

Body:
because you are overwriting array key('url').

$row is a local copy of $this->brands any changes to $row will not reflect on $this->brands.

change this

foreach ($this->brands as $brand => $row) {
    $row['url'] = strtolower($row['name']);
}

with this

foreach ($this->brands as $brand => $row) {
    $this->brands[$brand]['url'] = strtolower($row['name']);
}

Happy Coding.


来源: stackexchange

问:
WAMP not able to start after accidentally enable or disabled a module for apache
So today I was trying to be fast by navigate to my WAMP's Apache -> Apache Modules to enable the mode rewrite module for my lovely Wordpress site... Instead of click on the module, which I can't find, and I did something with keyboard by input with 'mo...' not wait till the finish my server got restart and apache can no longer started again, also there is no significant error in my apache error log.... I wonder what should I do to fix this?

However there is an error message when I try to enable any of the apache modules
"Could not execute menu item(internal error) [Exception] Could not perform service action: The service has not been started"

my setup is :

Win10

WAMP (with apache 2.4.9)

答:
@Ezeewei You could just have solved this by going to the httpd.conf file and commenting out this line:</p>

```<code>LoadModule ssl_module modules/mod_ssl.so
</code>```

ContentLicense: CC BY-SA 3.0

Body:
@Ezeewei You could just have solved this by going to the httpd.conf file and commenting out this line:

LoadModule ssl_module modules/mod_ssl.so


问:
How to find most recently modified file from all subdirectories in a directory in Python?
I have a directory in which I have many folders, AS WELL as files. I want to write a script that finds the path and name of the most recent file that exists in the directory, either in one of its sub-directories, or in the directory itself. This will be run from VSCode whenever I want to run a program. Earlier I had something like this. It worked ONLY for files in the directory, and not files in sub-directories.

```<code>files = sorted(os.listdir(path), key=os.path.getctime, reverse = True)
for file in files: #Finds most recent file with '.cpp' extension
    if ".cpp" in file:
        last = file
        break
subprocess.call(
    ["g++", "-std=c++14", path + last]
    )
subprocess.call(
    ["open", path + "./a.out"]
)
</code>```

Here's the output of "ls -ltr" in Terminal. The last three lines are for folders.

```<code>-rw-r--r--@  1 tanavya.dimri  staff     2182 Mar 23 16:10 UVa_LEDTest.cpp
-rw-r--r--@  1 tanavya.dimri  staff     4217 Mar 23 16:11 OPC_SiruseriMetro.cpp
-rw-r--r--@  1 tanavya.dimri  staff     2645 Mar 23 16:12 UVa_Password.cpp
-rw-r--r--@  1 tanavya.dimri  staff      940 Mar 23 16:13 UVa_8Queens.cpp
-rw-r--r--@  1 tanavya.dimri  staff     1587 Mar 23 20:57 UVa12405_Scarecrow.cpp
-rw-r--r--@  1 tanavya.dimri  staff     3014 Mar 25 19:58 UVa_Zones.cpp
-rw-r--r--@  1 tanavya.dimri  staff     2733 Mar 25 20:07 YogesMM.cpp
-rw-r--r--@  1 tanavya.dimri  staff     1066 Mar 26 22:33 ChefAndTraingles.cpp
-rw-r--r--@  1 tanavya.dimri  staff      993 Mar 27 07:10 untitled.cpp
-rw-r--r--   1 tanavya.dimri  staff       33 Mar 27 21:42 out.out
-rwxr-xr-x   1 tanavya.dimri  staff    15564 Mar 27 22:54 a.out
drwxr-xr-x   8 tanavya.dimri  staff      272 Mar 27 23:35 SpecificAlgorithms
drwxr-xr-x  25 tanavya.dimri  staff      850 Mar 30 12:49 DynamicProgramming
drwxr-xr-x   5 tanavya.dimri  staff      170 Mar 30 16:27 GraphTheory
</code>```

Maybe in the future, I might have sub-directories INSIDE my sub-directories, so if any suggested script can work in that scenario as well, it would be even more appreciated.

EDIT

I liked both the answers, by Peter and Jean, so thanks!
My file now:

```<code>import os
import subprocess

path = "/Users/tanavya.dimri/Desktop/CompetitiveProgramming/"

most_recent_file = max((os.path.join(root,f) for root,_,the_files in os.walk(path) for f in the_files if f.lower().endswith(".cpp")),key=os.path.getctime)
subprocess.call(
                ["g++", "-std=c++14", most_recent_file]
                )
run_file = max((os.path.join(root,f) for root,_,the_files in os.walk(path) for f in the_files if f.lower() == "a.out"),key=os.path.getctime)
subprocess.call(
                ["open", run_file]
                )
</code>```

It's short and simple, though I also liked the readability of Peter's code.

答:
You can write a generally useful function to yield all file paths in and below a directory, using os.walk:

```<code>def filepaths(directory):
    for root, dirs, filenames in os.walk(directory):
        for filename in filenames:
            yield os.path.join(root, filename)
</code>```

Then you can write a generator to filter out .cpp files, making sure to compare disregarding case, by converting the path to lower case first:

```<code>cpps = (filepath for filepath in filepaths(directory)
        if filepath.lower().endswith('.cpp'))
</code>```

You can use max on the files with a key of os.path.getctime:

```<code>latest = max(cpps, key=os.path.getctime)
</code>```

An advantage of using max is that os.path.getctime only gets called once for each file path. Your solution using sorted was inefficient as you don't really need all the modification times in order, you just want the latest. getctime would be called for each comparison to get the files into order.

Body:
I have a directory in which I have many folders, AS WELL as files. I want to write a script that finds the path and name of the most recent file that exists in the directory, either in one of its sub-directories, or in the directory itself. This will be run from VSCode whenever I want to run a program. Earlier I had something like this. It worked ONLY for files in the directory, and not files in sub-directories.

files = sorted(os.listdir(path), key=os.path.getctime, reverse = True)
for file in files: #Finds most recent file with '.cpp' extension
    if ".cpp" in file:
        last = file
        break
subprocess.call(
    ["g++", "-std=c++14", path + last]
    )
subprocess.call(
    ["open", path + "./a.out"]
)

Here's the output of "ls -ltr" in Terminal. The last three lines are for folders.

-rw-r--r--@  1 tanavya.dimri  staff     2182 Mar 23 16:10 UVa_LEDTest.cpp
-rw-r--r--@  1 tanavya.dimri  staff     4217 Mar 23 16:11 OPC_SiruseriMetro.cpp
-rw-r--r--@  1 tanavya.dimri  staff     2645 Mar 23 16:12 UVa_Password.cpp
-rw-r--r--@  1 tanavya.dimri  staff      940 Mar 23 16:13 UVa_8Queens.cpp
-rw-r--r--@  1 tanavya.dimri  staff     1587 Mar 23 20:57 UVa12405_Scarecrow.cpp
-rw-r--r--@  1 tanavya.dimri  staff     3014 Mar 25 19:58 UVa_Zones.cpp
-rw-r--r--@  1 tanavya.dimri  staff     2733 Mar 25 20:07 YogesMM.cpp
-rw-r--r--@  1 tanavya.dimri  staff     1066 Mar 26 22:33 ChefAndTraingles.cpp
-rw-r--r--@  1 tanavya.dimri  staff      993 Mar 27 07:10 untitled.cpp
-rw-r--r--   1 tanavya.dimri  staff       33 Mar 27 21:42 out.out
-rwxr-xr-x   1 tanavya.dimri  staff    15564 Mar 27 22:54 a.out
drwxr-xr-x   8 tanavya.dimri  staff      272 Mar 27 23:35 SpecificAlgorithms
drwxr-xr-x  25 tanavya.dimri  staff      850 Mar 30 12:49 DynamicProgramming
drwxr-xr-x   5 tanavya.dimri  staff      170 Mar 30 16:27 GraphTheory

Maybe in the future, I might have sub-directories INSIDE my sub-directories, so if any suggested script can work in that scenario as well, it would be even more appreciated.

EDIT

I liked both the answers, by Peter and Jean, so thanks!
My file now:

import os
import subprocess

path = "/Users/tanavya.dimri/Desktop/CompetitiveProgramming/"

most_recent_file = max((os.path.join(root,f) for root,_,the_files in os.walk(path) for f in the_files if f.lower().endswith(".cpp")),key=os.path.getctime)
subprocess.call(
                ["g++", "-std=c++14", most_recent_file]
                )
run_file = max((os.path.join(root,f) for root,_,the_files in os.walk(path) for f in the_files if f.lower() == "a.out"),key=os.path.getctime)
subprocess.call(
                ["open", run_file]
                )

It's short and simple, though I also liked the readability of Peter's code.

Body:
You can write a generally useful function to yield all file paths in and below a directory, using os.walk:

def filepaths(directory):
    for root, dirs, filenames in os.walk(directory):
        for filename in filenames:
            yield os.path.join(root, filename)

Then you can write a generator to filter out .cpp files, making sure to compare disregarding case, by converting the path to lower case first:

cpps = (filepath for filepath in filepaths(directory)
        if filepath.lower().endswith('.cpp'))

You can use max on the files with a key of os.path.getctime:

latest = max(cpps, key=os.path.getctime)

An advantage of using max is that os.path.getctime only gets called once for each file path. Your solution using sorted was inefficient as you don't really need all the modification times in order, you just want the latest. getctime would be called for each comparison to get the files into order.


问:
Spring Boot + Oracle: Hibernate dialect is 9i when in properties it is set to 10g
I'm trying to run a Spring Boot app with an Oracle DB and I specifically set the spring.datasource.platform value to org.hibernate.dialect.Oracle10gDialect.

During runtime I see this message:

```<code>2017-03-30 14:15:34.474  INFO 6664 --- [  restartedMain] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.Oracle9iDialect
</code>```

Why is it showing 9i instead of 10g? Is this something that I am doing wrong, or is this being forced on by my driver version in the pom, or by the  database that I am using?

This is the pom driver:

```<code><dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>11.2.0.4</version>
</dependency>
</code>```

答:
Could you please try with the below property key?

```<code>spring.jpa.database-platform
</code>```

For more info
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html#howto-configure-jpa-properties

Body:
I'm trying to run a Spring Boot app with an Oracle DB and I specifically set the spring.datasource.platform value to org.hibernate.dialect.Oracle10gDialect.

During runtime I see this message:

2017-03-30 14:15:34.474  INFO 6664 --- [  restartedMain] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.Oracle9iDialect

Why is it showing 9i instead of 10g? Is this something that I am doing wrong, or is this being forced on by my driver version in the pom, or by the  database that I am using?

This is the pom driver:

<dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>11.2.0.4</version>
</dependency>

Body:
Could you please try with the below property key?

spring.jpa.database-platform

For more info
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html#howto-configure-jpa-properties


问:
Selenium: Wait for element's width to be greater than X
I have a page that does some processing and displays a progress bar.

I want to press the cancel button when the filling of the progress bar has at least 50% width.

How can I create a custom wait condition ?

```<code>    driver.findElement(By.id('bar')).then(function (stateEl) {
      // driver.wait(until. ?? By.xpath?
    }).then(done);
</code>```

答:
Try the below code,

```<code>driver.wait(function() {
return driver.findElement(progressbar_locator).getAttribute("value")
       .then(function (value) {
          return value >=50;
        })
}, 5000);
</code>```

Here I'm just assuming that the progress bar element will have an attribute named "value" which will change dynamically based on the progress bar percentage. In your case, you need to identify a way to know when the progress bar value gets changed.

Body:
I have a page that does some processing and displays a progress bar.

I want to press the cancel button when the filling of the progress bar has at least 50% width.

How can I create a custom wait condition ?

    driver.findElement(By.id('bar')).then(function (stateEl) {
      // driver.wait(until. ?? By.xpath?
    }).then(done);

Body:
Try the below code,

driver.wait(function() {
return driver.findElement(progressbar_locator).getAttribute("value")
       .then(function (value) {
          return value >=50;
        })
}, 5000);

Here I'm just assuming that the progress bar element will have an attribute named "value" which will change dynamically based on the progress bar percentage. In your case, you need to identify a way to know when the progress bar value gets changed.


问:
Looping Java switch statement
My system is a banking system and I want my program to loop after the user has interacted with one of the processes (withdraw, view balance etc).

After user get result I want to give a chance to continue with another process:

```<code>package smartcode.atm.h.w;

import java.util.Scanner;

public class SmartCodeATMHW {

    public static void main(String[] args) {
        int p;
        int y = 1234;
        int Amount = 500;
        int result;
        int info;
        int f;
        int g;

        Scanner in = new Scanner(System.in);

        for (int i = 0; i < 3; i++) {
            System.out.println("Please enter PIN Number ");
            p = in.nextInt();

            if (p == y) {
                System.out.println("You have entered correct PIN number \n\n*****************");

                profile pr = new profile();
                pr.setName("Prapashtica");
                System.out.println("Welcome mr." + pr.getName());

                //loop from here
                boolean end = false;
                do{
                    System.out.println("\nPress 1 to View Bank Account");
                    System.out.println("Press 2 to Deposit money");
                    System.out.println("Press 3 to Withdraw money");
                    System.out.println("Press 4 to Cancle the Process \n\n********************");
                    info = in.nextInt();

                    switch (info) {
                        case 1:
                            System.out.println("You have  " + Amount + "$ available");
                            return;

                        case 2:
                            System.out.println("You have  " + Amount + "$ available");
                            System.out.println("Please enter the amount you wish to deposit");
                            f = in.nextInt();

                            result = Amount + f;
                            System.out.println("You have  " + result + "$ available");
                            break;
                        case 3:
                            for (int l = 0; l < 3; l++) {
                                System.out.println("You have  " + Amount + "  $ available");
                                System.out.println("Please eter the amount you wish to withdraw");
                                g = in.nextInt();
                                if (g > 500) {
                                    System.out.println("You cannot withdraw more than your current amount");
                                } else {
                                    System.out.println("You have succesfully withdrawed  " + g + " $");
                                    result = Amount - g;

                                    System.out.println("You now have  " + result + "  $ available");
                                }
                            }
                            System.out.println("Your card is now blocked");
                            break;
                        case 4:
                            System.out.println("You have canceled the proccess");
                            break;
                        default:
                            System.out.println("Error \nInvalid number");
                            break;

                    }
                    return;
                }while (end == false);
            } else {
                System.out.println("You have entered incorrect PIN number  \nPlease try again  \n*******************************");
            }
        }
        System.out.println("Your card is now blocked");
    }
}
</code>```

答:
This here:

```<code>for (int i = 0; i < 3; i++) {
</code>```

Around that other loop:

```<code>} while (end == false)
</code>```

is simply bogus.

You want one loop that goes around your "menu"; and that loop ends when the user wants to end.

End of story.

Title: Looping Java switch statement

Body:
My system is a banking system and I want my program to loop after the user has interacted with one of the processes (withdraw, view balance etc).

After user get result I want to give a chance to continue with another process:

package smartcode.atm.h.w;

import java.util.Scanner;

public class SmartCodeATMHW {

    public static void main(String[] args) {
        int p;
        int y = 1234;
        int Amount = 500;
        int result;
        int info;
        int f;
        int g;

        Scanner in = new Scanner(System.in);

        for (int i = 0; i < 3; i++) {
            System.out.println("Please enter PIN Number ");
            p = in.nextInt();

            if (p == y) {
                System.out.println("You have entered correct PIN number \n\n*****************");

                profile pr = new profile();
                pr.setName("Prapashtica");
                System.out.println("Welcome mr." + pr.getName());

                //loop from here
                boolean end = false;
                do{
                    System.out.println("\nPress 1 to View Bank Account");
                    System.out.println("Press 2 to Deposit money");
                    System.out.println("Press 3 to Withdraw money");
                    System.out.println("Press 4 to Cancle the Process \n\n********************");
                    info = in.nextInt();

                    switch (info) {
                        case 1:
                            System.out.println("You have  " + Amount + "$ available");
                            return;

                        case 2:
                            System.out.println("You have  " + Amount + "$ available");
                            System.out.println("Please enter the amount you wish to deposit");
                            f = in.nextInt();

                            result = Amount + f;
                            System.out.println("You have  " + result + "$ available");
                            break;
                        case 3:
                            for (int l = 0; l < 3; l++) {
                                System.out.println("You have  " + Amount + "  $ available");
                                System.out.println("Please eter the amount you wish to withdraw");
                                g = in.nextInt();
                                if (g > 500) {
                                    System.out.println("You cannot withdraw more than your current amount");
                                } else {
                                    System.out.println("You have succesfully withdrawed  " + g + " $");
                                    result = Amount - g;

                                    System.out.println("You now have  " + result + "  $ available");
                                }
                            }
                            System.out.println("Your card is now blocked");
                            break;
                        case 4:
                            System.out.println("You have canceled the proccess");
                            break;
                        default:
                            System.out.println("Error \nInvalid number");
                            break;

                    }
                    return;
                }while (end == false);
            } else {
                System.out.println("You have entered incorrect PIN number  \nPlease try again  \n*******************************");
            }
        }
        System.out.println("Your card is now blocked");
    }
}

Body:
This here:

for (int i = 0; i < 3; i++) {

Around that other loop:

} while (end == false)

is simply bogus.

You want one loop that goes around your "menu"; and that loop ends when the user wants to end.

End of story.


问:
Unable to build the Project with maven dependencies : xalan serialzer issues
Unable to resolve the following issue in maven. I don't know whats wrong with the following :

Unable to build the Project when running the command :
mvn clean install -DskipTests

```<code>Dependency convergence error for xalan:serializer:2.7.1 paths to dependency are:

+-com.org:org-fixtures:1.2.0-SNAPSHOT
  +-com.org:org-engine:4.1-SNAPSHOT
    +-xalan:serializer:2.7.1
and
+-com.org:org-fixtures:1.2.0-SNAPSHOT
  +-com.pack:-seleniumcore:4.1-SNAPSHOT
    +-org.seleniumhq.selenium:selenium-java:2.21.0
      +-org.seleniumhq.selenium:selenium-htmlunit-driver:2.21.0
        +-net.sourceforge.htmlunit:htmlunit:2.9
          +-xalan:xalan:2.7.2
            +-xalan:serializer:2.7.2

[WARNING] Rule 0: org.apache.maven.plugins.enforcer.DependencyConvergence failed
 with message:
Failed while enforcing releasability the error(s) are [
Dependency convergence error for xalan:serializer:2.7.1 paths to dependency are:

+-com.org:org-fixtures:1.2.0-SNAPSHOT
  +-com.org:org-engine:4.1-SNAPSHOT
    +-xalan:serializer:2.7.1
and
+-com.org:org-fixtures:1.2.0-SNAPSHOT
  +-com.org:org-seleniumcore:4.1-SNAPSHOT
    +-org.seleniumhq.selenium:selenium-java:2.21.0
      +-org.seleniumhq.selenium:selenium-htmlunit-driver:2.21.0
        +-net.sourceforge.htmlunit:htmlunit:2.9
          +-xalan:xalan:2.7.2
            +-xalan:serializer:2.7.2
</code>```

Please help!!

答:
You need to exclude one of the xalan dependencies, probably the older one:</p>

```<code><dependency>
  <groupId>com.org</groupId>
  <artifactId>org-engine</artifactId>
  <version>4.1-SNAPSHOT</version>
  <exclusions>
    <exclusion>
      <groupId>xlan</groupId>
      <artifactId>serializer</artifactId>
    </exclusion>
  </exclusions>
</dependency>
</code>```

Body:
Unable to resolve the following issue in maven. I don't know whats wrong with the following :

Unable to build the Project when running the command :
mvn clean install -DskipTests

Dependency convergence error for xalan:serializer:2.7.1 paths to dependency are:

+-com.org:org-fixtures:1.2.0-SNAPSHOT
  +-com.org:org-engine:4.1-SNAPSHOT
    +-xalan:serializer:2.7.1
and
+-com.org:org-fixtures:1.2.0-SNAPSHOT
  +-com.pack:-seleniumcore:4.1-SNAPSHOT
    +-org.seleniumhq.selenium:selenium-java:2.21.0
      +-org.seleniumhq.selenium:selenium-htmlunit-driver:2.21.0
        +-net.sourceforge.htmlunit:htmlunit:2.9
          +-xalan:xalan:2.7.2
            +-xalan:serializer:2.7.2

[WARNING] Rule 0: org.apache.maven.plugins.enforcer.DependencyConvergence failed
 with message:
Failed while enforcing releasability the error(s) are [
Dependency convergence error for xalan:serializer:2.7.1 paths to dependency are:

+-com.org:org-fixtures:1.2.0-SNAPSHOT
  +-com.org:org-engine:4.1-SNAPSHOT
    +-xalan:serializer:2.7.1
and
+-com.org:org-fixtures:1.2.0-SNAPSHOT
  +-com.org:org-seleniumcore:4.1-SNAPSHOT
    +-org.seleniumhq.selenium:selenium-java:2.21.0
      +-org.seleniumhq.selenium:selenium-htmlunit-driver:2.21.0
        +-net.sourceforge.htmlunit:htmlunit:2.9
          +-xalan:xalan:2.7.2
            +-xalan:serializer:2.7.2

Please help!!

Body:
You need to exclude one of the xalan dependencies, probably the older one:

<dependency>
  <groupId>com.org</groupId>
  <artifactId>org-engine</artifactId>
  <version>4.1-SNAPSHOT</version>
  <exclusions>
    <exclusion>
      <groupId>xlan</groupId>
      <artifactId>serializer</artifactId>
    </exclusion>
  </exclusions>
</dependency>


答:
if you want to edit the element being iterated you can add a & before $row

```<code>foreach ($this->brands as $brand => &$row) {
    $row['url'] = strtolower($row['name']);
}
</code>```

but this is not necessary, just access the array from the variable available outside of the foreach loop e.g $this->brands

```<code>foreach ($this->brands as $brand => $row) {
    $this->brands[$brand]['url'] = strtolower($row['name']);
}
</code>```

Title: Why is php handling for different than foreach?

Body:
if you want to edit the element being iterated you can add a & before $row

foreach ($this->brands as $brand => &$row) {
    $row['url'] = strtolower($row['name']);
}

but this is not necessary, just access the array from the variable available outside of the foreach loop e.g $this->brands

foreach ($this->brands as $brand => $row) {
    $this->brands[$brand]['url'] = strtolower($row['name']);
}


问:
On your very first program, which construct hooked you on programming?
To me it was the If statement, I'm psyched up, since then I believed that computers are very intelligent, or I can at least make it appear intelligent because of it.</p>

答:
I remember the first computer problem that truly fascinated me.  It was a problem I got in my highschool programming class.

Write a program that will read a number from the console

Why did that fascinate me?  Well it didn't at first.  I wrote a quick and dirty program that did the deed but then the teacher did something quite unexpected.  She entered "a" into the program and it died a horrible death.

It took me the rest of the day to deal with evil input but eventually I got it working.  This process completely hooked me on the idea of program correctness.

OwnerDisplayName: Michael Buen

ContentLicense: CC BY-SA 2.5

LastEditorDisplayName: Triptych

OwnerDisplayName: JaredPar


问:
Calculate the time stamp of year
Given that I have $num_years, how can I add it to Time()  to get a time stamp $num_years hence?

答:
```<code>echo strftime('%Y %a %d %m, %T', strtotime('+' . $num_years . ' years') );
</code>```

Change strfttime format according your needs.
Check out strtotime man page http://php.net/manual/en/function.strtotime.php

Title: Calculate the time stamp of year

Body:
echo strftime('%Y %a %d %m, %T', strtotime('+' . $num_years . ' years') );

Change strfttime format according your needs.
Check out strtotime man page http://php.net/manual/en/function.strtotime.php


问:
Google FusedProvider does not call onLocationChanged() in an environment without GPS
My app works fine if the area has GPS (such as outside) or in houses/first or second floor buildings but it does not receive a location update if the area is something like the 4th-10th floor of a tall building, is this expected behavior or is this a limitation of location services?

Even with an internet connection on a high floor it still does not receive an update, this makes me believe that it is not falling back to Wi-Fi/mobile networks but I tried setting my Location method to Wi-Fi/Mobile only in the Android settings but it still works in normal environments.

Can anyone give me advice on what is happening? Do location services simply not work at higher altitudes or certain areas with very poor reception? I have not tested it in underground parking areas though.

I am using PRIORITY_HIGH_ACCURACY as my priority.

答:
I am using PRIORITY_HIGH_ACCURACY as my priority.

That's the reason you are not getting Location change inside a building. Because HIGH_ACCURACY gets location from GPS provider. As we know GPS doesn't work well inside houses as it collects location from satellite.

You can try out other options.

PRIORITY_BALANCED_POWER_ACCURACY (About 100 meter)

PRIORITY_LOW_POWER (About 10km)

PRIORITY_NO_POWER (Act as a passive listener )

You may visit here if you havn't yet. Hope this helps.


问:
Is it possible to set 2 urls in get_absolute_url?
I have next task and dont know how to make it.

Web page shows to user list of objects. Every object has 2 button with urls like function_detail and function_change_history. First url need open the page about details of the object and the second url need to open the page about change history. I used get_absolute_url to make second url but dont know how to create first url cause I need to use get_absolute_url again.

models.py:

```<code>@reversion.register()
class Function(models.Model):
    ***FIELDS***

    def get_absolute_url(self):
        return reverse('project:function_change_history', args=[self.project_id, self.code])
</code>```

urls.py:

```<code>url(r'^(?P<project_code>[0-9a-f-]+)/(?P<function_code>[0-9a-f-]+)/change_history/$',
        function_change_history,
        name='function_change_history'),

url(r'^(?P<project_code>[0-9a-f-]+)/(?P<function_code>[0-9a-f-]+)/detail/$',
        function_detail,
        name='function_detail'),
</code>```

Is it possible to set 2 url in get_absolute_url?

答: Finally I found the decision. For function_detail I use get_absolute_url and for function_change_history I use in template {% url 'function_change_history'  project_code=project.code function_code=function.code %}

Body:
I have next task and dont know how to make it.

Web page shows to user list of objects. Every object has 2 button with urls like function_detail and function_change_history. First url need open the page about details of the object and the second url need to open the page about change history. I used get_absolute_url to make second url but dont know how to create first url cause I need to use get_absolute_url again.

models.py:

@reversion.register()
class Function(models.Model):
    ***FIELDS***

    def get_absolute_url(self):
        return reverse('project:function_change_history', args=[self.project_id, self.code])

urls.py:

url(r'^(?P<project_code>[0-9a-f-]+)/(?P<function_code>[0-9a-f-]+)/change_history/$',
        function_change_history,
        name='function_change_history'),

url(r'^(?P<project_code>[0-9a-f-]+)/(?P<function_code>[0-9a-f-]+)/detail/$',
        function_detail,
        name='function_detail'),

Is it possible to set 2 url in get_absolute_url?


问:
Gridview scroll slow
I'm trying to create an gallery app, just to show images to the user.

The app is already working, but the grid scroll is slow and not smooth.

I don't know what else I can do to make performance better. I'm already using LruCache and Async task to load images.

GridAdapter

```<code>package abcde.xyz;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;

import java.util.ArrayList;

/**
 * Created by Lucas on 25/03/2017.
 */

public class GridImagesAdapter extends ArrayAdapter {

    private Context context;
    private int layoutResourceId;
    private ArrayList data = new ArrayList();
    public static LruCache<Integer, Bitmap> mMemoryCache;

    public GridImagesAdapter(Context context, int layoutResourceId, ArrayList<Integer> data) {
        super(context, layoutResourceId, data);
        this.layoutResourceId = layoutResourceId;
        this.context = context;
        this.data = data;

        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

        final int cacheSize = maxMemory / 4;
        if(mMemoryCache == null){
            mMemoryCache = new LruCache<Integer, Bitmap>(cacheSize) {
                @Override
                protected int sizeOf(Integer key, Bitmap bitmap) {
                    return bitmap.getByteCount() / 1024;
                }
            };
        }
        mMemoryCache.evictAll();

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;

        if (row == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);

            ImageView image = (ImageView)row.findViewById(R.id.image);
            final Integer item = (Integer)data.get(position);

            image.setImageBitmap(null);
            ImageGridHandler handler = new ImageGridHandler(context, image);
            handler.execute(item);
        }

        return row;
    }
}
</code>```

ImageGridHandler

```<code>package abcde.xyz;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.ImageView;

import java.lang.ref.WeakReference;

/**
 * Created by Lucas on 29/03/2017.
 */

public class ImageGridHandler extends AsyncTask<Integer, Void, Bitmap> {
    private final WeakReference<ImageView> imageViewReference;
    private Context context;
    public ImageGridHandler(Context context, ImageView img){
        imageViewReference = new WeakReference<ImageView>(img);
        this.context = context;
    }

    @Override
    protected Bitmap doInBackground(Integer... params) {

        return loadBitmap(params[0]);

    }

    @Override
    protected void onPostExecute(Bitmap result) {
        final ImageView imageView = imageViewReference.get();

        if(imageView != null) {
            //imageView.setScaleType(ImageView.ScaleType.CENTER);
            imageView.setImageBitmap(result);
        }
    }

    public void addBitmapToMemoryCache(Integer key, Bitmap bitmap) {
        if (getBitmapFromMemCache(key) == null) {
            GridImagesAdapter.mMemoryCache.put(key, bitmap);
        }
    }

    public Bitmap getBitmapFromMemCache(Integer key) {
        return GridImagesAdapter.mMemoryCache.get(key);
    }

    public Bitmap loadBitmap(Integer resId) {

        Bitmap bitmap = getBitmapFromMemCache(resId);
        if (bitmap == null) {

           Log.d("ImageGridHandler", "Loading: " + resId);
            if(resId != null) {
                bitmap = MediaStore.Images.Thumbnails.getThumbnail(
                        context.getContentResolver(), resId,
                        MediaStore.Images.Thumbnails.MICRO_KIND,
                        null);
                if(bitmap != null) {
                    addBitmapToMemoryCache(resId, bitmap);
                }
            }

            Log.d("GRIDADAPTER", "ImageLoaded");
        }

        return bitmap;
    }

}
</code>```

Layouts

content_main.xml

```<code><?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="umdev.images24.MainActivity"
    tools:showIn="@layout/activity_main">
    <android.support.v4.widget.SwipeRefreshLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/swipeRefresh"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        tools:layout_editor_absoluteY="8dp"
        tools:layout_editor_absoluteX="8dp">

     <GridView
         android:id="@+id/gridView"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:layout_margin="0dp"
         android:drawSelectorOnTop="true"
         android:gravity="center"
         android:columnWidth="100dp"
         android:numColumns="auto_fit"
         android:stretchMode="columnWidth"
         android:verticalSpacing="0dp"
         android:focusable="true"
         android:clickable="true"
         android:fastScrollEnabled="true"/>

    </android.support.v4.widget.SwipeRefreshLayout>
</android.support.constraint.ConstraintLayout>
</code>```

grid_item_layout.xml

```<code><?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="2dp"
    android:background="#fff">

    <ImageView
        android:id="@+id/image"
        android:layout_width="120dp"
        android:layout_height="120dp" />

</LinearLayout>
</code>```

答:
Its not fast and smooth because you are not caching. I had the same issue I used Universal Image loader, Use this library to resize your image in grid view.

Git-Hub Universal Image Loader

It uses url to fetch the image then convert it to bitmap and then resize it. So if you want to just create a simple image gallery. Then you can fetch the sd card image just like you are doing and pass it to universal Image loader's method ImageLoader()

For example -

```<code>String path="file://"+String.valueOf(wholeList.get(i));//Your Image path

    ImageLoader.getInstance().displayImage(path,holder.image,options,new SimpleImageLoadingListener() {
        @Override
        public void onLoadingStarted(String imageUri, View view) {
            holder.progressBar.setProgress(0);
            holder.progressBar.setVisibility(View.VISIBLE);
        }

        @Override
        public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
            holder.progressBar.setVisibility(View.GONE);
        }

        @Override
        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
            holder.progressBar.setVisibility(View.GONE);
        }
    }, new ImageLoadingProgressListener() {
        @Override
        public void onProgressUpdate(String imageUri, View view, int      current, int total) {
            holder.progressBar.setProgress(Math.round(100.0f * current / total));
        }});

    return convertView;
}
private static class ViewHolder {
    ImageView image;
    ProgressBar progressBar;
}
</code>```

**Note: This is not full code it is just a part of it, I suggest you to please check the Git hub Link first **- GitHub Universal Image Loader

Title: Gridview scroll slow

Body:
I'm trying to create an gallery app, just to show images to the user.

The app is already working, but the grid scroll is slow and not smooth.

I don't know what else I can do to make performance better. I'm already using LruCache and Async task to load images.

GridAdapter

package abcde.xyz;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;

import java.util.ArrayList;

/**
 * Created by Lucas on 25/03/2017.
 */

public class GridImagesAdapter extends ArrayAdapter {

    private Context context;
    private int layoutResourceId;
    private ArrayList data = new ArrayList();
    public static LruCache<Integer, Bitmap> mMemoryCache;

    public GridImagesAdapter(Context context, int layoutResourceId, ArrayList<Integer> data) {
        super(context, layoutResourceId, data);
        this.layoutResourceId = layoutResourceId;
        this.context = context;
        this.data = data;

        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

        final int cacheSize = maxMemory / 4;
        if(mMemoryCache == null){
            mMemoryCache = new LruCache<Integer, Bitmap>(cacheSize) {
                @Override
                protected int sizeOf(Integer key, Bitmap bitmap) {
                    return bitmap.getByteCount() / 1024;
                }
            };
        }
        mMemoryCache.evictAll();

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;

        if (row == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);

            ImageView image = (ImageView)row.findViewById(R.id.image);
            final Integer item = (Integer)data.get(position);

            image.setImageBitmap(null);
            ImageGridHandler handler = new ImageGridHandler(context, image);
            handler.execute(item);
        }

        return row;
    }
}

ImageGridHandler

package abcde.xyz;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.ImageView;

import java.lang.ref.WeakReference;

/**
 * Created by Lucas on 29/03/2017.
 */

public class ImageGridHandler extends AsyncTask<Integer, Void, Bitmap> {
    private final WeakReference<ImageView> imageViewReference;
    private Context context;
    public ImageGridHandler(Context context, ImageView img){
        imageViewReference = new WeakReference<ImageView>(img);
        this.context = context;
    }

    @Override
    protected Bitmap doInBackground(Integer... params) {

        return loadBitmap(params[0]);

    }

    @Override
    protected void onPostExecute(Bitmap result) {
        final ImageView imageView = imageViewReference.get();

        if(imageView != null) {
            //imageView.setScaleType(ImageView.ScaleType.CENTER);
            imageView.setImageBitmap(result);
        }
    }

    public void addBitmapToMemoryCache(Integer key, Bitmap bitmap) {
        if (getBitmapFromMemCache(key) == null) {
            GridImagesAdapter.mMemoryCache.put(key, bitmap);
        }
    }

    public Bitmap getBitmapFromMemCache(Integer key) {
        return GridImagesAdapter.mMemoryCache.get(key);
    }

    public Bitmap loadBitmap(Integer resId) {

        Bitmap bitmap = getBitmapFromMemCache(resId);
        if (bitmap == null) {

           Log.d("ImageGridHandler", "Loading: " + resId);
            if(resId != null) {
                bitmap = MediaStore.Images.Thumbnails.getThumbnail(
                        context.getContentResolver(), resId,
                        MediaStore.Images.Thumbnails.MICRO_KIND,
                        null);
                if(bitmap != null) {
                    addBitmapToMemoryCache(resId, bitmap);
                }
            }

            Log.d("GRIDADAPTER", "ImageLoaded");
        }

        return bitmap;
    }

}

Layouts

content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="umdev.images24.MainActivity"
    tools:showIn="@layout/activity_main">
    <android.support.v4.widget.SwipeRefreshLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/swipeRefresh"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        tools:layout_editor_absoluteY="8dp"
        tools:layout_editor_absoluteX="8dp">

     <GridView
         android:id="@+id/gridView"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:layout_margin="0dp"
         android:drawSelectorOnTop="true"
         android:gravity="center"
         android:columnWidth="100dp"
         android:numColumns="auto_fit"
         android:stretchMode="columnWidth"
         android:verticalSpacing="0dp"
         android:focusable="true"
         android:clickable="true"
         android:fastScrollEnabled="true"/>

    </android.support.v4.widget.SwipeRefreshLayout>
</android.support.constraint.ConstraintLayout>

grid_item_layout.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="2dp"
    android:background="#fff">

    <ImageView
        android:id="@+id/image"
        android:layout_width="120dp"
        android:layout_height="120dp" />

</LinearLayout>

Body:
Its not fast and smooth because you are not caching. I had the same issue I used Universal Image loader, Use this library to resize your image in grid view.

Git-Hub Universal Image Loader

It uses url to fetch the image then convert it to bitmap and then resize it. So if you want to just create a simple image gallery. Then you can fetch the sd card image just like you are doing and pass it to universal Image loader's method ImageLoader()

For example -

String path="file://"+String.valueOf(wholeList.get(i));//Your Image path

    ImageLoader.getInstance().displayImage(path,holder.image,options,new SimpleImageLoadingListener() {
        @Override
        public void onLoadingStarted(String imageUri, View view) {
            holder.progressBar.setProgress(0);
            holder.progressBar.setVisibility(View.VISIBLE);
        }

        @Override
        public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
            holder.progressBar.setVisibility(View.GONE);
        }

        @Override
        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
            holder.progressBar.setVisibility(View.GONE);
        }
    }, new ImageLoadingProgressListener() {
        @Override
        public void onProgressUpdate(String imageUri, View view, int      current, int total) {
            holder.progressBar.setProgress(Math.round(100.0f * current / total));
        }});

    return convertView;
}
private static class ViewHolder {
    ImageView image;
    ProgressBar progressBar;
}

**Note: This is not full code it is just a part of it, I suggest you to please check the Git hub Link first **- GitHub Universal Image Loader


问:
Recover deleted branch in GitHub desktop
I'm new to GitHub and have been using GitHub Desktop to collaborate on a group project at uni.
I had cloned a remote repo onto my computer and was working on a branch on it, and had locally committed it several times.
I then accidentally deleted the branch without realising that this would delete all of the files on my computer.
I would really like to be able to recover the lost files as I'd been working on them for a few weeks!

I have seen several posts about using
    git reflog,
but I'm really new to git and have no idea how to access the repo I was working on GitHub Desktop with through git.

Any help would be really appreciated!

答: Solved the problem!! before using git reflog you need to cd into the correct directory first.


问:
How to sort a HashMap by it amount of value in Java
I have declared a HashMap like this:

```<code>Map<Integer,ArrayList<Integer>> numbers = new HashMap<Integer,ArrayList<Integer>>();
</code>```

It has an output like this:

{64=[61, 68, 77], 65=[63, 66, 66, 70], 66=[69, 75, 2], 2=[4], 67=[65, 77], 4=[2]}

How do I count an value amount of its key?

So for 64 will be 3, 65 will be 4 and 66 will be 3

And then get a keys which has top 3 value amount
So the output in this case be like 65 64 66

答:
You can use a reverse-ordered TreeMap to order your Map's keys according to their value's size:

```<code>    SortedMap<Integer,ArrayList<Integer>> sizes = new TreeMap<Integer,ArrayList<Integer>>(Collections.reverseOrder());
    for (Integer key : numbers.keySet()) {
        int size = numbers.get(key).size();
        if (sizes.get(size) == null) {
            sizes.put(size, new ArrayList<Integer>());
        }
        sizes.get(size).add(key);
    }
    System.out.println(sizes.values());
</code>```

This will print:

```<code>[[65], [64, 66], [67], [2, 4]]
</code>```

If you want to remove the [], you can loop over sizes.values() and print only the contents of each contained list, or just print sizes.values().toString().replace("[","").replace("]","")) to remove them from the printed string.

Body:
I have declared a HashMap like this:

Map<Integer,ArrayList<Integer>> numbers = new HashMap<Integer,ArrayList<Integer>>();

It has an output like this:

{64=[61, 68, 77], 65=[63, 66, 66, 70], 66=[69, 75, 2], 2=[4], 67=[65, 77], 4=[2]}

How do I count an value amount of its key?

So for 64 will be 3, 65 will be 4 and 66 will be 3

And then get a keys which has top 3 value amount
So the output in this case be like 65 64 66

Body:
You can use a reverse-ordered TreeMap to order your Map's keys according to their value's size:

    SortedMap<Integer,ArrayList<Integer>> sizes = new TreeMap<Integer,ArrayList<Integer>>(Collections.reverseOrder());
    for (Integer key : numbers.keySet()) {
        int size = numbers.get(key).size();
        if (sizes.get(size) == null) {
            sizes.put(size, new ArrayList<Integer>());
        }
        sizes.get(size).add(key);
    }
    System.out.println(sizes.values());

This will print:

[[65], [64, 66], [67], [2, 4]]

If you want to remove the [], you can loop over sizes.values() and print only the contents of each contained list, or just print sizes.values().toString().replace("[","").replace("]","")) to remove them from the printed string.


答:
You need to work on a reference. Insert a & and it will work

```<code>foreach ($this->brands as $brand => &$row) {
    $row['url'] = strtolower($row['name']);
}
</code>```

or you could work on the original array like:

```<code>foreach ($this->brands as $brand => $row) {
    $this->brands[$brand]['url'] = strtolower($row['name']);
}
</code>```

Body:
I made an array $brands inside class Cars, the print_r output looks like this:

Array ( [0] => Array (  [id] => 1
                        [name] => 'Porsche'
                    )
        [1] => Array (  [id] => 2
                        [name] => 'Bugatti'
                    )
        [2] => Array (  [id] => 3
                        [name] => 'BMW'
                    )
    )

But when I'd like to link to a certain brand, I don't want to use strtolower() to make a lowercased hyperlink. I would like to echo $cars->brands[$i]['url'] (instead of strtolower($cars->brands[$i]['name'])).

class Cars {

So I needed to create a for loop, to create the ['url'] key in the array. I thought that a foreach would work:

foreach ($this->brands as $brand => $row) {
    $row['url'] = strtolower($row['name']);
}

But it didn't. Even this did not work: $row['name'] = strtolower($row['name']);.

But this worked, though:

for ($i = 0; $i < count($this->brands); $i++) {
    $this->brands[$i]['url'] = strtolower($this->brands[$i]['name']);
}

}

My question here is: how? why?

Body:
You need to work on a reference. Insert a & and it will work

foreach ($this->brands as $brand => &$row) {
    $row['url'] = strtolower($row['name']);
}

or you could work on the original array like:

foreach ($this->brands as $brand => $row) {
    $this->brands[$brand]['url'] = strtolower($row['name']);
}


问:
Running a script from a folder on a Tomcat Server
I am trying to run a script on my tomcat webserver. To run the script before on my local machine, this is the code I used.

```<code>String absolutePath = new File(".").getAbsolutePath();
        int last = absolutePath.length()-1;
        absolutePath = absolutePath.substring(0, last);
        String filePath =  "";
        if(osVersion.equalsIgnoreCase("Ubuntu"))
        {
            try (FileReader fr = new FileReader("template.txt");
                    FileWriter fw = new FileWriter("Ubuntu/ubuntu_file.json");) {
                   int c = fr.read();
                   while(c!=-1) {
                       fw.write(c);
                       c = fr.read();
                   }
               } catch(IOException e) {
                   e.printStackTrace();
               }
            filePath = "Ubuntu";
            String fi = absolutePath + filePath;
            System.out.println(fi);//Get the full path.
            // Create ProcessBuilder.
            ProcessBuilder pb = new ProcessBuilder("bash", "-c",
                    "cd "+fi+" ; PACKER_LOG=1 /usr/local/bin/packer  build ubuntu_file.json");

            Process p = pb.start();
</code>```

When I however try to run it on the tomcat webserver, I keep getting this error.

EclipseEE.app/Contents/MacOS/Ubuntu Failed to parse template: open
  ubuntu_file.json: no such file or directory

I am fairly new to Tomcat, and I am just learning it's ins and outs. What tomcat directory should I place my Ubuntu folder (I am assuming it's the webapp directory) in order for tomcat to get the absolute path of the folder and then be able to run the script.

答:
If you have a more or less conventional Tomcat installation then the $CATALINA_HOME environment variable will be set and point to your server installation which will contain at least the following directories:

```<code>$CATALINA_HOME/
   bin/
   conf/
   lib/
   webapps/
</code>```

You can get the value of $CATALINA_HOME via:

```<code>String catalinaHomeDir = System.getenv("CATALINA_HOME");
</code>```

I would be inclined to put your configuration in the conf subdirectory.

If you're running multiple Tomcat instances from the same base then be sure to read the RUNNING.txt file that comes with it because you may need to use $CATALINA_BASE instead.

You may need to set up CATALINA_HOME/BASE in your Eclipse Tomcat Runtime environment when running locally with an Eclipse controlled server.

BTW. This is not a portable solution. If you need to migrate to some other container (such as WildFly or Glassfish) then the absolute path config recommended by others is the way to go.

Body:
I am trying to run a script on my tomcat webserver. To run the script before on my local machine, this is the code I used.

String absolutePath = new File(".").getAbsolutePath();
        int last = absolutePath.length()-1;
        absolutePath = absolutePath.substring(0, last);
        String filePath =  "";
        if(osVersion.equalsIgnoreCase("Ubuntu"))
        {
            try (FileReader fr = new FileReader("template.txt");
                    FileWriter fw = new FileWriter("Ubuntu/ubuntu_file.json");) {
                   int c = fr.read();
                   while(c!=-1) {
                       fw.write(c);
                       c = fr.read();
                   }
               } catch(IOException e) {
                   e.printStackTrace();
               }
            filePath = "Ubuntu";
            String fi = absolutePath + filePath;
            System.out.println(fi);//Get the full path.
            // Create ProcessBuilder.
            ProcessBuilder pb = new ProcessBuilder("bash", "-c",
                    "cd "+fi+" ; PACKER_LOG=1 /usr/local/bin/packer  build ubuntu_file.json");

            Process p = pb.start();

When I however try to run it on the tomcat webserver, I keep getting this error.

EclipseEE.app/Contents/MacOS/Ubuntu Failed to parse template: open
  ubuntu_file.json: no such file or directory

I am fairly new to Tomcat, and I am just learning it's ins and outs. What tomcat directory should I place my Ubuntu folder (I am assuming it's the webapp directory) in order for tomcat to get the absolute path of the folder and then be able to run the script.

Body:
If you have a more or less conventional Tomcat installation then the $CATALINA_HOME environment variable will be set and point to your server installation which will contain at least the following directories:

$CATALINA_HOME/
   bin/
   conf/
   lib/
   webapps/

You can get the value of $CATALINA_HOME via:

String catalinaHomeDir = System.getenv("CATALINA_HOME");

I would be inclined to put your configuration in the conf subdirectory.

If you're running multiple Tomcat instances from the same base then be sure to read the RUNNING.txt file that comes with it because you may need to use $CATALINA_BASE instead.

You may need to set up CATALINA_HOME/BASE in your Eclipse Tomcat Runtime environment when running locally with an Eclipse controlled server.

BTW. This is not a portable solution. If you need to migrate to some other container (such as WildFly or Glassfish) then the absolute path config recommended by others is the way to go.


问:
Json response parser for Array or Object
I am writing a library to consume a Json API and I am facing a design problem when using Gson as the parsing library.

One of the endpoints returns an array of objects if everything goes well like so:

```<code>[
  {
   "name": "John",
   "age" : 21
  },
  {
   "name": "Sarah",
   "age" : 32
  },
]
</code>```

However, the error schema for all the endpoints in the API is an json object instead of an array.

```<code>{
  "errors": [
     {
       "code": 1001,
       "message": "Something blew up"
     }
  ]
}
</code>```

The problem arises when modeling this in POJOs. Because the error schema is common for all the API endpoints, I decided to have an abstract ApiResponse class which will only map the errors attribute

```<code>public abstract class ApiResponse{

  @SerializedName("errors")
  List<ApiResponseError> errors;
}

public class ApiResponseError {

  @SerializedName("code")
  public Integer code;

  @SerializedName("message")
  public String message;
}
</code>```

Now I would like to inherit from ApiResponse to have the error mapping "for free" and a POJO per API endpoint response. However, the top level json object for this response is an array (if the server succeeds to execute the request), so I can not create a new class to map it like I would like it.

I decided to still create a class extending ApiResponse:

```<code>public class ApiResponsePerson extends ApiResponse {

  List<Person> persons;
}
</code>```

And implemented a custom deserializer to correctly parse the json depending on the type of the top level object, and setting it to the correct field on the following class:

```<code>public class DeserializerApiResponsePerson implements JsonDeserializer<ApiResponsePerson> {

  @Override
  public ApiResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

    ApiResponsePerson response = new ApiResponsePerson();
    if (json.isJsonArray()) {
      Type personType = new TypeToken<List<Person>>() {}.getType();
      response.persons = context.deserialize(json, personType);
      return response;
    }
    if (json.isJsonObject()) {
      JsonElement errorJson = json.getAsJsonObject().get("errors");
      Type errorsType = new TypeToken<List<ApiResponseError>>() {}.getType();
      response.errors = context.deserialize(errorJson, errorsType);
      return response;
    }
    throw new JsonParseException("Unexpected Json for 'ApiResponse'");
  }
}
</code>```

Which I will then add to the Gson

```<code>Gson gson = new GsonBuilder()
    .registerTypeAdapter(ApiResponsePerson.class, new DeserializerApiResponsePerson())
    .create();
</code>```

Is there any way to model this POJOs and have Gson recognize this structure without having to manually handle this scenario?
Is there any better way to accomplish this?
Am I missing any scenario where the deserializer might fail or not work as expected?

Thanks

答:
Sometimes API responses do not fit statically typed languages like Java is very well. I would say that if you're facing a problem to align with a not very convenient response format, you have to write more code if you want it to be convenient for you. And in most cases Gson can help in such cases, but not for free.

Is there any way to model this POJOs and have Gson recognize this structure without having to manually handle this scenario?

No. Gson does not mix objects of different structure, so you still have to tell it your intentions.

Is there any better way to accomplish this?

I guess yes, for both modelling the response and implementing the way how such responses are parsed.

Am I missing any scenario where the deserializer might fail or not work as expected?

It's response format sensitive like all deserializers are, so in general it's good enough, but can be improved.

First off, let's consider you can have two cases only: a regular response and an error. This is a classic case, and it can be modelled like that:

abstract class ApiResponse<T> {

    // A bunch of protected methods, no interface needed as we're considering it's a value type and we don't want to expose any of them
    protected abstract boolean isSuccessful();

    protected abstract T getData()
            throws UnsupportedOperationException;

    protected abstract List<ApiResponseError> getErrors()
            throws UnsupportedOperationException;

    // Since we can cover all two cases ourselves, let them all be here in this class
    private ApiResponse() {
    }

    static <T> ApiResponse<T> success(final T data) {
        return new SucceededApiResponse<>(data);
    }

    static <T> ApiResponse<T> failure(final List<ApiResponseError> errors) {
        @SuppressWarnings("unchecked")
        final ApiResponse<T> castApiResponse = (ApiResponse<T>) new FailedApiResponse(errors);
        return castApiResponse;
    }

    // Despite those three protected methods can be technically public, let's encapsulate the state
    final void accept(final IApiResponseConsumer<? super T> consumer) {
        if ( isSuccessful() ) {
            consumer.acceptSuccess(getData());
        } else {
            consumer.acceptFailure(getErrors());
        }
    }

    // And make a couple of return-friendly accept methods
    final T acceptOrNull() {
        if ( !isSuccessful() ) {
            return null;
        }
        return getData();
    }

    final T acceptOrNull(final Consumer<? super List<ApiResponseError>> errorsConsumer) {
        if ( !isSuccessful() ) {
            errorsConsumer.accept(getErrors());
            return null;
        }
        return getData();
    }

    private static final class SucceededApiResponse<T>
            extends ApiResponse<T> {

        private final T data;

        private SucceededApiResponse(final T data) {
            this.data = data;
        }

        @Override
        protected boolean isSuccessful() {
            return true;
        }

        @Override
        protected T getData() {
            return data;
        }

        @Override
        protected List<ApiResponseError> getErrors()
                throws UnsupportedOperationException {
            throw new UnsupportedOperationException();
        }

    }

    private static final class FailedApiResponse
            extends ApiResponse<Void> {

        private final List<ApiResponseError> errors;

        private FailedApiResponse(final List<ApiResponseError> errors) {
            this.errors = errors;
        }

        @Override
        protected boolean isSuccessful() {
            return false;
        }

        @Override
        protected List<ApiResponseError> getErrors() {
            return errors;
        }

        @Override
        protected Void getData()
                throws UnsupportedOperationException {
            throw new UnsupportedOperationException();
        }

    }

}
```

<pre class="lang-java prettyprint-override"><code>interface IApiResponseConsumer<T> {

    void acceptSuccess(T data);

    void acceptFailure(List<ApiResponseError> errors);

}
</code>```

A trivial mapping for errors:

final class ApiResponseError {

    // Since incoming DTO are read-only data bags in most-most cases, even getters may be noise here
    // Gson can strip off the final modifier easily
    // However, primitive values are inlined by javac, so we're cheating javac with Integer.valueOf
    final int code = Integer.valueOf(0);
    final String message = null;

}
```

<p>And some values too:</p>

<pre class="lang-java prettyprint-override"><code>final class Person {

    final String name = null;
    final int age = Integer.valueOf(0);

}
</code>```

The second component is a special type adapter to tell Gson how the API responses must be deserialized. Note that type adapter, unlike JsonSerializer and JsonDeserializer work in streaming fashion not requiring the whole JSON model (JsonElement) to be stored in memory, thus you can save memory and improve the performance for large JSON documents.

final class ApiResponseTypeAdapterFactory
        implements TypeAdapterFactory {

    // No state, so it can be instantiated once
    private static final TypeAdapterFactory apiResponseTypeAdapterFactory = new ApiResponseTypeAdapterFactory();

    // Type tokens are effective value types and can be instantiated once per parameterization
    private static final TypeToken<List<ApiResponseError>> apiResponseErrorsType = new TypeToken<List<ApiResponseError>>() {
    };

    private ApiResponseTypeAdapterFactory() {
    }

    static TypeAdapterFactory getApiResponseTypeAdapterFactory() {
        return apiResponseTypeAdapterFactory;
    }

    @Override
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
        // Is it ApiResponse, a class we can handle?
        if ( ApiResponse.class.isAssignableFrom(typeToken.getRawType()) ) {
            // Trying to resolve its parameterization
            final Type typeParameter = getTypeParameter0(typeToken.getType());
            // And asking Gson for the success and failure type adapters to use downstream parsers
            final TypeAdapter<?> successTypeAdapter = gson.getDelegateAdapter(this, TypeToken.get(typeParameter));
            final TypeAdapter<List<ApiResponseError>> failureTypeAdapter = gson.getDelegateAdapter(this, apiResponseErrorsType);
            @SuppressWarnings("unchecked")
            final TypeAdapter<T> castTypeAdapter = (TypeAdapter<T>) new ApiResponseTypeAdapter<>(successTypeAdapter, failureTypeAdapter);
            return castTypeAdapter;
        }
        return null;
    }

    private static Type getTypeParameter0(final Type type) {
        // Is this type parameterized?
        if ( !(type instanceof ParameterizedType) ) {
            // No, it's raw
            return Object.class;
        }
        final ParameterizedType parameterizedType = (ParameterizedType) type;
        return parameterizedType.getActualTypeArguments()[0];
    }

    private static final class ApiResponseTypeAdapter<T>
            extends TypeAdapter<ApiResponse<T>> {

        private final TypeAdapter<T> successTypeAdapter;
        private final TypeAdapter<List<ApiResponseError>> failureTypeAdapter;

        private ApiResponseTypeAdapter(final TypeAdapter<T> successTypeAdapter, final TypeAdapter<List<ApiResponseError>> failureTypeAdapter) {
            this.successTypeAdapter = successTypeAdapter;
            this.failureTypeAdapter = failureTypeAdapter;
        }

        @Override
        public void write(final JsonWriter out, final ApiResponse<T> value)
                throws UnsupportedOperationException {
            throw new UnsupportedOperationException();
        }

        @Override
        public ApiResponse<T> read(final JsonReader in)
                throws IOException {
            final JsonToken token = in.peek();
            switch ( token ) {
            case BEGIN_ARRAY:
                // Is it array? Assuming that the responses come as arrays only
                // Otherwise a more complex parsing is required probably replaced with JsonDeserializer for some cases
                // So reading the next value (entire array) and wrapping it up in an API response with the success-on state
                return success(successTypeAdapter.read(in));
            case BEGIN_OBJECT:
                // Otherwise it's probably an error object?
                in.beginObject();
                final String name = in.nextName();
                if ( !name.equals("errors") ) {
                    // Let it fail fast, what if a successful response would be here?
                    throw new MalformedJsonException("Expected errors` but was " + name);
                }
                // Constructing a failed response object and terminating the error object
                final ApiResponse<T> failure = failure(failureTypeAdapter.read(in));
                in.endObject();
                return failure;
            // A matter of style, but just to show the intention explicitly and make IntelliJ IDEA "switch on enums with missing case" to not report warnings here
            case END_ARRAY:
            case END_OBJECT:
            case NAME:
            case STRING:
            case NUMBER:
            case BOOLEAN:
            case NULL:
            case END_DOCUMENT:
                throw new MalformedJsonException("Unexpected token: " + token);
            default:
                throw new AssertionError(token);
            }
        }

    }

}
```

<p>Now, how it all can be put together. Note that the responses do not expose their internals explicitly but rather requiring consumers to accept making its privates really encapsulated. </p>

<pre class="lang-java prettyprint-override"><code>public final class Q43113283 {

    private Q43113283() {
    }

    private static final String SUCCESS_JSON = "[{\"name\":\"John\",\"age\":21},{\"name\":\"Sarah\",\"age\":32}]";
    private static final String FAILURE_JSON = "{\"errors\":[{\"code\":1001,\"message\":\"Something blew up\"}]}";

    private static final Gson gson = new GsonBuilder()
            .registerTypeAdapterFactory(getApiResponseTypeAdapterFactory())
            .create();

    // Assuming that the Type instance is immutable under the hood so it might be cached
    private static final Type personsApiResponseType = new TypeToken<ApiResponse<List<Person>>>() {
    }.getType();

    @SuppressWarnings("unchecked")
    public static void main(final String... args) {
        final ApiResponse<Iterable<Person>> successfulResponse = gson.fromJson(SUCCESS_JSON, personsApiResponseType);
        final ApiResponse<Iterable<Person>> failedResponse = gson.fromJson(FAILURE_JSON, personsApiResponseType);
        useFullyCallbackApproach(successfulResponse, failedResponse);
        useSemiCallbackApproach(successfulResponse, failedResponse);
        useNoCallbackApproach(successfulResponse, failedResponse);
    }

    private static void useFullyCallbackApproach(final ApiResponse<Iterable<Person>>... responses) {
        System.out.println("<FULL CALLBACKS>");
        final IApiResponseConsumer<Iterable<Person>> handler = new IApiResponseConsumer<Iterable<Person>>() {
            @Override
            public void acceptSuccess(final Iterable<Person> people) {
                dumpPeople(people);
            }

            @Override
            public void acceptFailure(final List<ApiResponseError> errors) {
                dumpErrors(errors);
            }
        };
        Stream.of(responses)
                .forEach(response -> response.accept(handler));
    }

    private static void useSemiCallbackApproach(final ApiResponse<Iterable<Person>>... responses) {
        System.out.println("<SEMI CALLBACKS>");
        Stream.of(responses)
                .forEach(response -> {
                    final Iterable<Person> people = response.acceptOrNull(Q43113283::dumpErrors);
                    if ( people != null ) {
                        dumpPeople(people);
                    }
                });
    }

    private static void useNoCallbackApproach(final ApiResponse<Iterable<Person>>... responses) {
        System.out.println("<NO CALLBACKS>");
        Stream.of(responses)
                .forEach(response -> {
                    final Iterable<Person> people = response.acceptOrNull();
                    if ( people != null ) {
                        dumpPeople(people);
                    }
                });
    }

    private static void dumpPeople(final Iterable<Person> people) {
        for ( final Person person : people ) {
            System.out.println(person.name + " (" + person.age + ")");
        }
    }

    private static void dumpErrors(final Iterable<ApiResponseError> errors) {
        for ( final ApiResponseError error : errors ) {
            System.err.println("ERROR: " + error.code + " " + error.message);
        }
    }

}
</code>```

The code above will produce:

<FULL CALLBACKS>

  John (21)

  Sarah (32)

  ERROR: 1001 Something blew up

  <SEMI CALLBACKS>

  John (21)

  Sarah (32)

  ERROR: 1001 Something blew up

  <NO CALLBACKS>

  John (21)

  Sarah (32)

Body:
I am writing a library to consume a Json API and I am facing a design problem when using Gson as the parsing library.

One of the endpoints returns an array of objects if everything goes well like so:

[
  {
   "name": "John",
   "age" : 21
  },
  {
   "name": "Sarah",
   "age" : 32
  },
]

However, the error schema for all the endpoints in the API is an json object instead of an array.

{
  "errors": [
     {
       "code": 1001,
       "message": "Something blew up"
     }
  ]
}

The problem arises when modeling this in POJOs. Because the error schema is common for all the API endpoints, I decided to have an abstract ApiResponse class which will only map the errors attribute

public abstract class ApiResponse{

  @SerializedName("errors")
  List<ApiResponseError> errors;
}

public class ApiResponseError {

  @SerializedName("code")
  public Integer code;

  @SerializedName("message")
  public String message;
}

Now I would like to inherit from ApiResponse to have the error mapping "for free" and a POJO per API endpoint response. However, the top level json object for this response is an array (if the server succeeds to execute the request), so I can not create a new class to map it like I would like it.

I decided to still create a class extending ApiResponse:

public class ApiResponsePerson extends ApiResponse {

  List<Person> persons;
}

And implemented a custom deserializer to correctly parse the json depending on the type of the top level object, and setting it to the correct field on the following class:

public class DeserializerApiResponsePerson implements JsonDeserializer<ApiResponsePerson> {

  @Override
  public ApiResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

    ApiResponsePerson response = new ApiResponsePerson();
    if (json.isJsonArray()) {
      Type personType = new TypeToken<List<Person>>() {}.getType();
      response.persons = context.deserialize(json, personType);
      return response;
    }
    if (json.isJsonObject()) {
      JsonElement errorJson = json.getAsJsonObject().get("errors");
      Type errorsType = new TypeToken<List<ApiResponseError>>() {}.getType();
      response.errors = context.deserialize(errorJson, errorsType);
      return response;
    }
    throw new JsonParseException("Unexpected Json for 'ApiResponse'");
  }
}

Which I will then add to the Gson

Gson gson = new GsonBuilder()
    .registerTypeAdapter(ApiResponsePerson.class, new DeserializerApiResponsePerson())
    .create();

Is there any way to model this POJOs and have Gson recognize this structure without having to manually handle this scenario?
Is there any better way to accomplish this?
Am I missing any scenario where the deserializer might fail or not work as expected?

Thanks

Body:
Sometimes API responses do not fit statically typed languages like Java is very well. I would say that if you're facing a problem to align with a not very convenient response format, you have to write more code if you want it to be convenient for you. And in most cases Gson can help in such cases, but not for free.

Is there any way to model this POJOs and have Gson recognize this structure without having to manually handle this scenario?

No. Gson does not mix objects of different structure, so you still have to tell it your intentions.

Is there any better way to accomplish this?

I guess yes, for both modelling the response and implementing the way how such responses are parsed.

Am I missing any scenario where the deserializer might fail or not work as expected?

It's response format sensitive like all deserializers are, so in general it's good enough, but can be improved.

First off, let's consider you can have two cases only: a regular response and an error. This is a classic case, and it can be modelled like that:

abstract class ApiResponse<T> {

    // A bunch of protected methods, no interface needed as we're considering it's a value type and we don't want to expose any of them
    protected abstract boolean isSuccessful();

    protected abstract T getData()
            throws UnsupportedOperationException;

    protected abstract List<ApiResponseError> getErrors()
            throws UnsupportedOperationException;

    // Since we can cover all two cases ourselves, let them all be here in this class
    private ApiResponse() {
    }

    static <T> ApiResponse<T> success(final T data) {
        return new SucceededApiResponse<>(data);
    }

    static <T> ApiResponse<T> failure(final List<ApiResponseError> errors) {
        @SuppressWarnings("unchecked")
        final ApiResponse<T> castApiResponse = (ApiResponse<T>) new FailedApiResponse(errors);
        return castApiResponse;
    }

    // Despite those three protected methods can be technically public, let's encapsulate the state
    final void accept(final IApiResponseConsumer<? super T> consumer) {
        if ( isSuccessful() ) {
            consumer.acceptSuccess(getData());
        } else {
            consumer.acceptFailure(getErrors());
        }
    }

    // And make a couple of return-friendly accept methods
    final T acceptOrNull() {
        if ( !isSuccessful() ) {
            return null;
        }
        return getData();
    }

    final T acceptOrNull(final Consumer<? super List<ApiResponseError>> errorsConsumer) {
        if ( !isSuccessful() ) {
            errorsConsumer.accept(getErrors());
            return null;
        }
        return getData();
    }

    private static final class SucceededApiResponse<T>
            extends ApiResponse<T> {

        private final T data;

        private SucceededApiResponse(final T data) {
            this.data = data;
        }

        @Override
        protected boolean isSuccessful() {
            return true;
        }

        @Override
        protected T getData() {
            return data;
        }

        @Override
        protected List<ApiResponseError> getErrors()
                throws UnsupportedOperationException {
            throw new UnsupportedOperationException();
        }

    }

    private static final class FailedApiResponse
            extends ApiResponse<Void> {

        private final List<ApiResponseError> errors;

        private FailedApiResponse(final List<ApiResponseError> errors) {
            this.errors = errors;
        }

        @Override
        protected boolean isSuccessful() {
            return false;
        }

        @Override
        protected List<ApiResponseError> getErrors() {
            return errors;
        }

        @Override
        protected Void getData()
                throws UnsupportedOperationException {
            throw new UnsupportedOperationException();
        }

    }

}

interface IApiResponseConsumer<T> {

    void acceptSuccess(T data);

    void acceptFailure(List<ApiResponseError> errors);

}

A trivial mapping for errors:

final class ApiResponseError {

    // Since incoming DTO are read-only data bags in most-most cases, even getters may be noise here
    // Gson can strip off the final modifier easily
    // However, primitive values are inlined by javac, so we're cheating javac with Integer.valueOf
    final int code = Integer.valueOf(0);
    final String message = null;

}

And some values too:

final class Person {

    final String name = null;
    final int age = Integer.valueOf(0);

}

The second component is a special type adapter to tell Gson how the API responses must be deserialized. Note that type adapter, unlike JsonSerializer and JsonDeserializer work in streaming fashion not requiring the whole JSON model (JsonElement) to be stored in memory, thus you can save memory and improve the performance for large JSON documents.

final class ApiResponseTypeAdapterFactory
        implements TypeAdapterFactory {

    // No state, so it can be instantiated once
    private static final TypeAdapterFactory apiResponseTypeAdapterFactory = new ApiResponseTypeAdapterFactory();

    // Type tokens are effective value types and can be instantiated once per parameterization
    private static final TypeToken<List<ApiResponseError>> apiResponseErrorsType = new TypeToken<List<ApiResponseError>>() {
    };

    private ApiResponseTypeAdapterFactory() {
    }

    static TypeAdapterFactory getApiResponseTypeAdapterFactory() {
        return apiResponseTypeAdapterFactory;
    }

    @Override
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
        // Is it ApiResponse, a class we can handle?
        if ( ApiResponse.class.isAssignableFrom(typeToken.getRawType()) ) {
            // Trying to resolve its parameterization
            final Type typeParameter = getTypeParameter0(typeToken.getType());
            // And asking Gson for the success and failure type adapters to use downstream parsers
            final TypeAdapter<?> successTypeAdapter = gson.getDelegateAdapter(this, TypeToken.get(typeParameter));
            final TypeAdapter<List<ApiResponseError>> failureTypeAdapter = gson.getDelegateAdapter(this, apiResponseErrorsType);
            @SuppressWarnings("unchecked")
            final TypeAdapter<T> castTypeAdapter = (TypeAdapter<T>) new ApiResponseTypeAdapter<>(successTypeAdapter, failureTypeAdapter);
            return castTypeAdapter;
        }
        return null;
    }

    private static Type getTypeParameter0(final Type type) {
        // Is this type parameterized?
        if ( !(type instanceof ParameterizedType) ) {
            // No, it's raw
            return Object.class;
        }
        final ParameterizedType parameterizedType = (ParameterizedType) type;
        return parameterizedType.getActualTypeArguments()[0];
    }

    private static final class ApiResponseTypeAdapter<T>
            extends TypeAdapter<ApiResponse<T>> {

        private final TypeAdapter<T> successTypeAdapter;
        private final TypeAdapter<List<ApiResponseError>> failureTypeAdapter;

        private ApiResponseTypeAdapter(final TypeAdapter<T> successTypeAdapter, final TypeAdapter<List<ApiResponseError>> failureTypeAdapter) {
            this.successTypeAdapter = successTypeAdapter;
            this.failureTypeAdapter = failureTypeAdapter;
        }

        @Override
        public void write(final JsonWriter out, final ApiResponse<T> value)
                throws UnsupportedOperationException {
            throw new UnsupportedOperationException();
        }

        @Override
        public ApiResponse<T> read(final JsonReader in)
                throws IOException {
            final JsonToken token = in.peek();
            switch ( token ) {
            case BEGIN_ARRAY:
                // Is it array? Assuming that the responses come as arrays only
                // Otherwise a more complex parsing is required probably replaced with JsonDeserializer for some cases
                // So reading the next value (entire array) and wrapping it up in an API response with the success-on state
                return success(successTypeAdapter.read(in));
            case BEGIN_OBJECT:
                // Otherwise it's probably an error object?
                in.beginObject();
                final String name = in.nextName();
                if ( !name.equals("errors") ) {
                    // Let it fail fast, what if a successful response would be here?
                    throw new MalformedJsonException("Expected errors` but was " + name);
                }
                // Constructing a failed response object and terminating the error object
                final ApiResponse<T> failure = failure(failureTypeAdapter.read(in));
                in.endObject();
                return failure;
            // A matter of style, but just to show the intention explicitly and make IntelliJ IDEA "switch on enums with missing case" to not report warnings here
            case END_ARRAY:
            case END_OBJECT:
            case NAME:
            case STRING:
            case NUMBER:
            case BOOLEAN:
            case NULL:
            case END_DOCUMENT:
                throw new MalformedJsonException("Unexpected token: " + token);
            default:
                throw new AssertionError(token);
            }
        }

    }

}

Now, how it all can be put together. Note that the responses do not expose their internals explicitly but rather requiring consumers to accept making its privates really encapsulated.

public final class Q43113283 {

    private Q43113283() {
    }

    private static final String SUCCESS_JSON = "[{\"name\":\"John\",\"age\":21},{\"name\":\"Sarah\",\"age\":32}]";
    private static final String FAILURE_JSON = "{\"errors\":[{\"code\":1001,\"message\":\"Something blew up\"}]}";

    private static final Gson gson = new GsonBuilder()
            .registerTypeAdapterFactory(getApiResponseTypeAdapterFactory())
            .create();

    // Assuming that the Type instance is immutable under the hood so it might be cached
    private static final Type personsApiResponseType = new TypeToken<ApiResponse<List<Person>>>() {
    }.getType();

    @SuppressWarnings("unchecked")
    public static void main(final String... args) {
        final ApiResponse<Iterable<Person>> successfulResponse = gson.fromJson(SUCCESS_JSON, personsApiResponseType);
        final ApiResponse<Iterable<Person>> failedResponse = gson.fromJson(FAILURE_JSON, personsApiResponseType);
        useFullyCallbackApproach(successfulResponse, failedResponse);
        useSemiCallbackApproach(successfulResponse, failedResponse);
        useNoCallbackApproach(successfulResponse, failedResponse);
    }

    private static void useFullyCallbackApproach(final ApiResponse<Iterable<Person>>... responses) {
        System.out.println("<FULL CALLBACKS>");
        final IApiResponseConsumer<Iterable<Person>> handler = new IApiResponseConsumer<Iterable<Person>>() {
            @Override
            public void acceptSuccess(final Iterable<Person> people) {
                dumpPeople(people);
            }

            @Override
            public void acceptFailure(final List<ApiResponseError> errors) {
                dumpErrors(errors);
            }
        };
        Stream.of(responses)
                .forEach(response -> response.accept(handler));
    }

    private static void useSemiCallbackApproach(final ApiResponse<Iterable<Person>>... responses) {
        System.out.println("<SEMI CALLBACKS>");
        Stream.of(responses)
                .forEach(response -> {
                    final Iterable<Person> people = response.acceptOrNull(Q43113283::dumpErrors);
                    if ( people != null ) {
                        dumpPeople(people);
                    }
                });
    }

    private static void useNoCallbackApproach(final ApiResponse<Iterable<Person>>... responses) {
        System.out.println("<NO CALLBACKS>");
        Stream.of(responses)
                .forEach(response -> {
                    final Iterable<Person> people = response.acceptOrNull();
                    if ( people != null ) {
                        dumpPeople(people);
                    }
                });
    }

    private static void dumpPeople(final Iterable<Person> people) {
        for ( final Person person : people ) {
            System.out.println(person.name + " (" + person.age + ")");
        }
    }

    private static void dumpErrors(final Iterable<ApiResponseError> errors) {
        for ( final ApiResponseError error : errors ) {
            System.err.println("ERROR: " + error.code + " " + error.message);
        }
    }

}

The code above will produce:

<FULL CALLBACKS>

  John (21)

  Sarah (32)

  ERROR: 1001 Something blew up

  <SEMI CALLBACKS>

  John (21)

  Sarah (32)

  ERROR: 1001 Something blew up

  <NO CALLBACKS>

  John (21)

  Sarah (32)


问:
Gremlin Java : Get Vertices by max Edge count
Suppose we have a graph like this.

```<code>(User)-[:KNOWS]->(Friend)
</code>```

I want to count all outgoing relationship from User and group them by user, then add some condition to filter. (Like more than 10 Knows)
This is what I did,

```<code>g.V().hasLabel("Friend").in("KNOWS").hasLabel("User").groupCount().next()
</code>```

This is returning a map, so I can add the condition to filter the results. My question is , do we have any efficient alternative way to do this ?

答:
I am not sure if I understood your question correctly, but it sounds like you just want to filter all users based on their number of outgoing edges with the label knows.
In that case you can directly start at the User vertices and filter them based on the number of their KNOWS edges instead of doing a groupCount:

```<code>g.V().hasLabel('User').where(outE('KNOWS').count().is(gt(10)))
</code>```

Until now I ignored any performance constrains. But as Paul Jackson mentioned in his comment it is not efficient to execute such a query in OLTP mode like this. Neo4j will probably iterate over all vertices, check whether they have the label User and then count their KNOWS edges.

You basically have two options to speed this up:

As Paul Jackson suggested: Add the edge count as a property to the vertices, pre-compute it and then index this property or

Use something like Spark-Gremlin if you really want to compute the edge count on the fly.

Body:
Suppose we have a graph like this.

(User)-[:KNOWS]->(Friend)

I want to count all outgoing relationship from User and group them by user, then add some condition to filter. (Like more than 10 Knows)
This is what I did,

g.V().hasLabel("Friend").in("KNOWS").hasLabel("User").groupCount().next()

This is returning a map, so I can add the condition to filter the results. My question is , do we have any efficient alternative way to do this ?

Body:
I am not sure if I understood your question correctly, but it sounds like you just want to filter all users based on their number of outgoing edges with the label knows.
In that case you can directly start at the User vertices and filter them based on the number of their KNOWS edges instead of doing a groupCount:

g.V().hasLabel('User').where(outE('KNOWS').count().is(gt(10)))

Until now I ignored any performance constrains. But as Paul Jackson mentioned in his comment it is not efficient to execute such a query in OLTP mode like this. Neo4j will probably iterate over all vertices, check whether they have the label User and then count their KNOWS edges.

You basically have two options to speed this up:

As Paul Jackson suggested: Add the edge count as a property to the vertices, pre-compute it and then index this property or

Use something like Spark-Gremlin if you really want to compute the edge count on the fly.

ContentLicense: CC BY-SA 4.0


问:
How to start solr server in hybris 5.7 in standalone mode?
Unable to start solr server in hybris 5.7 so search is not working . How to start solr server in hybris 5.7 in standalone mode.</p>

答:
In hybris\bin\ext-commerce\solrserver\resources\solr\binrun solr start.

Note that it's the path from version 6. The installation dir might be different, it is the location where the Solr installation bundle has been extracted.

Take a look at the README in solr/server to have the details about the config,log dir etc...

Also take a look at solr -help

Usage: solr COMMAND OPTIONS
         where COMMAND is one of: start, stop, restart, healthcheck, create, create_core, create_collection, delete, version, upconfig, downconfig

Standalone server example (start Solr running in the background on port 8984):
      solr start -p 8984

SolrCloud example (start Solr running in SolrCloud mode using localhost:2181 to connect to Zookeeper, with 1g max heap size and remote Java debug options enabled):

solr start -c -m 1g -z localhost:2181 -a "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044"

Pass -help after any COMMAND to see command-specific usage information,
    such as:    solr start -help or solr stop -help


问:
Store Tags in SQL and Retrieve it
I have a started to learn php & mysql and currently i`m thinking about possibility how to store and retrieve tags for some products.

I would like to assigne tags for specified products and after that display using while method or similiar

At the first step i was thinking to store it in one field, but i have not idea how to retrive it every words as unical item.

```<code>CREATE TABLE `products` (
  `id` int(11) NOT NULL,
  `brand_id` int(11) NOT NULL,
  `category_id` int(11) NOT NULL,
  `product_name` text COLLATE utf8_unicode_ci NOT NULL,
  `product_description` text COLLATE utf8_unicode_ci NOT NULL,
  `product_keywords` text COLLATE utf8_unicode_ci NOT NULL,
  `product_image` text COLLATE utf8_unicode_ci NOT NULL,
  `product_specification` text COLLATE utf8_unicode_ci NOT NULL,
  `product_spec_link` text COLLATE utf8_unicode_ci NOT NULL,
  `product_webstie` text COLLATE utf8_unicode_ci NOT NULL,
  `status` text COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
</code>```

Any ideas ?

I read here that the best way is to create separate table for this purpose and assign them to the specific product ID, but currently i cant imagine it, how it will work when i want to add new tag for it.

答:
After many of research time i think i found the best way to realize my idea.
First we have to do separate table for tags and create relationships with other tables using many to many or one to many option, depends of way which i want to use.
In case of multiple products which will have multiple tags which can be repeated then i have to use relationships many to many.

Please correct me if i made mistake.

Title: Store Tags in SQL and Retrieve it

Body:
I have a started to learn php & mysql and currently i`m thinking about possibility how to store and retrieve tags for some products.

I would like to assigne tags for specified products and after that display using while method or similiar

At the first step i was thinking to store it in one field, but i have not idea how to retrive it every words as unical item.

CREATE TABLE `products` (
  `id` int(11) NOT NULL,
  `brand_id` int(11) NOT NULL,
  `category_id` int(11) NOT NULL,
  `product_name` text COLLATE utf8_unicode_ci NOT NULL,
  `product_description` text COLLATE utf8_unicode_ci NOT NULL,
  `product_keywords` text COLLATE utf8_unicode_ci NOT NULL,
  `product_image` text COLLATE utf8_unicode_ci NOT NULL,
  `product_specification` text COLLATE utf8_unicode_ci NOT NULL,
  `product_spec_link` text COLLATE utf8_unicode_ci NOT NULL,
  `product_webstie` text COLLATE utf8_unicode_ci NOT NULL,
  `status` text COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Any ideas ?

I read here that the best way is to create separate table for this purpose and assign them to the specific product ID, but currently i cant imagine it, how it will work when i want to add new tag for it.