From 138f90f5fc28390611191d1b2e37105f0e910b8a Mon Sep 17 00:00:00 2001 From: Christian Dresen <info@draycoding.de> Date: Mon, 29 Jun 2015 01:54:10 +0200 Subject: [PATCH] no message --- WarpDrinkApi/pom.xml | 26 ++++++ .../java/ms/itsecteam/warpdrink/Database.java | 37 +++++++++ .../java/ms/itsecteam/warpdrink/Servlet.java | 25 ++++++ .../java/ms/itsecteam/warpdrink/UserDao.java | 55 +++++++++++++ .../ms/itsecteam/warpdrink/objects/User.java | 23 +++++- .../warpdrink/provider/UserProvider.java | 60 ++++++++++++-- .../src/main/webapp/WEB-INF/web.out.xml | 0 WarpDrinkApi/src/main/webapp/WEB-INF/web.xml | 2 +- WarpDrinkApp/.idea/gradle.xml | 4 +- WarpDrinkApp/.idea/misc.xml | 2 +- WarpDrinkApp/.idea/vcs.xml | 2 +- WarpDrinkApp/app/app.iml | 13 +-- WarpDrinkApp/app/build.gradle | 9 ++- .../app/libs/codepath-oauth-0.4.1.jar | Bin 25162 -> 0 bytes WarpDrinkApp/app/src/main/AndroidManifest.xml | 2 +- .../ms/itsecteam/warpdrink/MainActivity.java | 32 ++++---- .../ms/itsecteam/warpdrink/data/DataApi.java | 26 +++--- .../itsecteam/warpdrink/data/RestClient.java | 70 ---------------- .../warpdrink/data/objects/Setting.java | 2 +- .../warpdrink/data/objects/User.java | 6 +- .../data/rest/RequestSingleObject.java | 37 +++++++++ .../warpdrink/data/rest/RequestUserList.java | 50 ++++++++++++ .../warpdrink/data/rest/RestClient.java | 76 ++++++++++++++++++ .../data/rest/http/HttpGetRequest.java | 42 ++++++++++ .../data/rest/http/HttpPostRequest.java | 49 +++++++++++ .../data/rest/http/HttpPutRequest.java | 49 +++++++++++ .../warpdrink/dialogs/ChargeCustomDialog.java | 2 + .../warpdrink/dialogs/ChargeDialog.java | 2 + .../warpdrink/dialogs/NewUserDialog.java | 1 + WarpDrinkApp/build.gradle | 5 +- 30 files changed, 582 insertions(+), 127 deletions(-) create mode 100644 WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/Database.java create mode 100644 WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/Servlet.java create mode 100644 WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/UserDao.java delete mode 100644 WarpDrinkApi/src/main/webapp/WEB-INF/web.out.xml delete mode 100644 WarpDrinkApp/app/libs/codepath-oauth-0.4.1.jar delete mode 100644 WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/RestClient.java create mode 100644 WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RequestSingleObject.java create mode 100644 WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RequestUserList.java create mode 100644 WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RestClient.java create mode 100644 WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpGetRequest.java create mode 100644 WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpPostRequest.java create mode 100644 WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpPutRequest.java diff --git a/WarpDrinkApi/pom.xml b/WarpDrinkApi/pom.xml index 1fbc940..fa9c9f2 100644 --- a/WarpDrinkApi/pom.xml +++ b/WarpDrinkApi/pom.xml @@ -40,8 +40,34 @@ <artifactId>cxf-rt-rs-security-oauth2</artifactId> <version>2.7.5</version> </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>1.7.1</version> + </dependency> + <dependency> + <groupId>com.j256.ormlite</groupId> + <artifactId>ormlite-jdbc</artifactId> + <version>4.48</version> + </dependency> + <dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>5.1.35</version> + </dependency> + + </dependencies> <build> <finalName>warpdrink</finalName> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.7</source> + <target>1.7</target> + </configuration> + </plugin> + </plugins> </build> </project> diff --git a/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/Database.java b/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/Database.java new file mode 100644 index 0000000..a0f96c7 --- /dev/null +++ b/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/Database.java @@ -0,0 +1,37 @@ +package ms.itsecteam.warpdrink; + +import java.sql.SQLException; + +import com.j256.ormlite.jdbc.JdbcConnectionSource; +import com.j256.ormlite.support.ConnectionSource; + +public class Database { + private static Database instance; + private ConnectionSource connectionSource; + + private Database() { + try { + this.connectionSource = new JdbcConnectionSource("jdbc:mysql://localhost/dev","root",""); + System.out.println(this.connectionSource); + System.out.println(this.connectionSource.isOpen()); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public static Database getInstance() { + if (instance == null) { + instance = new Database(); + } + return instance; + } + + + public ConnectionSource getConnectionSource() { + return connectionSource; + } + + public void setConnectionSource(ConnectionSource connectionSource) { + this.connectionSource = connectionSource; + } +} diff --git a/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/Servlet.java b/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/Servlet.java new file mode 100644 index 0000000..dfda6b2 --- /dev/null +++ b/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/Servlet.java @@ -0,0 +1,25 @@ +package ms.itsecteam.warpdrink; + +import java.sql.SQLException; + +import ms.itsecteam.warpdrink.objects.User; + +public class Servlet extends com.sun.jersey.spi.container.servlet.ServletContainer{ + + /** + * + */ + private static final long serialVersionUID = 1L; + + + public Servlet() { + super(); + Database.getInstance(); + try { + UserDao.getInstance().saveUser(new User("Hans",3.0)); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/UserDao.java b/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/UserDao.java new file mode 100644 index 0000000..3153563 --- /dev/null +++ b/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/UserDao.java @@ -0,0 +1,55 @@ +package ms.itsecteam.warpdrink; + +import java.sql.SQLException; +import java.util.List; + +import ms.itsecteam.warpdrink.objects.User; + +import com.j256.ormlite.dao.BaseDaoImpl; +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.dao.DaoManager; +import com.j256.ormlite.support.ConnectionSource; +import com.j256.ormlite.table.TableUtils; + +public class UserDao extends BaseDaoImpl<User, String>{ + + private static UserDao instance; + private ConnectionSource connectionSource; + private Dao<User, String> userDao; + + private UserDao() throws SQLException { + super(User.class); + this.connectionSource = Database.getInstance().getConnectionSource(); + TableUtils.createTableIfNotExists(this.connectionSource, User.class); + this.userDao = DaoManager.createDao(this.connectionSource, User.class); + } + + public static UserDao getInstance() throws SQLException { + if (instance == null) { + instance = new UserDao(); + } + return instance; + } + public void saveUser(User user) throws SQLException { + this.userDao.createOrUpdate(user); + } + public List<User> getAllUsers() throws SQLException { + return this.userDao.queryForAll(); + } + public User getUser(int userid) throws SQLException { + List<User> result = this.userDao.queryForEq("userid", userid); + if (!result.isEmpty()) + return result.get(0); + return null; + } + public User getUser(String name) throws SQLException { + List<User> result = this.userDao.queryForEq("name", name); + if (!result.isEmpty()) + return result.get(0); + return null; + } + + + + +} \ No newline at end of file diff --git a/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/objects/User.java b/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/objects/User.java index 1efbff1..d71008e 100644 --- a/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/objects/User.java +++ b/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/objects/User.java @@ -2,21 +2,28 @@ package ms.itsecteam.warpdrink.objects; import javax.xml.bind.annotation.XmlRootElement; -@SuppressWarnings("restriction") +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + @XmlRootElement +@DatabaseTable(tableName = "users") public class User { - + + @DatabaseField(generatedId = true) private int userid; + + @DatabaseField(columnName = "name",unique = true, canBeNull = false) private String name; + + @DatabaseField(columnName = "credit") private double credit; public User() { super(); } - public User(int userid, String name, double credit) { + public User(String name, double credit) { super(); - this.userid = userid; this.name = name; this.credit = credit; } @@ -48,4 +55,12 @@ public class User { public String toString() { return "[Name: "+this.name+", Credit:"+this.credit+"]"; } + + @Override + public boolean equals(Object other) { + if (other == null || other.getClass() != getClass()) { + return false; + } + return name.equals(((User) other).name); + } } diff --git a/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/provider/UserProvider.java b/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/provider/UserProvider.java index 841f45f..c04259f 100644 --- a/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/provider/UserProvider.java +++ b/WarpDrinkApi/src/main/java/ms/itsecteam/warpdrink/provider/UserProvider.java @@ -1,29 +1,73 @@ package ms.itsecteam.warpdrink.provider; -import java.util.ArrayList; +import java.sql.SQLException; import java.util.List; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; +import com.google.gson.Gson; + +import ms.itsecteam.warpdrink.UserDao; import ms.itsecteam.warpdrink.objects.User; @Path("user") public class UserProvider { + List<User> users; + + public UserProvider() { + try { + users = UserDao.getInstance().getAllUsers(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @GET @Path("/all") @Produces(MediaType.APPLICATION_JSON) - public List<User> getUsers() { - List<User> users = new ArrayList<User>(); - users.add(new User(1,"Hugo",1.0)); - users.add(new User(2,"Frank",0.5)); - users.add(new User(3,"Martin",0.5)); - return users; + public String getUsers() { + List<User> users; + try { + users = UserDao.getInstance().getAllUsers(); + if(users != null){ + return new Gson().toJson(users,users.getClass()); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return ""; } + @GET @Path("/{userid}") @Produces(MediaType.APPLICATION_JSON) public User getUser(@PathParam("userid") int userid) { - return new User(userid,"Hugo",1.0); + try { + return UserDao.getInstance().getUser(userid); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + @POST + @Path("/{userid}") + @Produces(MediaType.APPLICATION_JSON) + public void setUser(@PathParam("userid") int userid, @FormParam("credit") double credit) throws SQLException { + User user = UserDao.getInstance().getUser(userid); + user.setCredit(credit); + UserDao.getInstance().saveUser(user); + } + @PUT + @Path("/create") + @Produces(MediaType.APPLICATION_JSON) + public User createUser(@FormParam("name") String name) throws SQLException { + if(UserDao.getInstance().getUser(name) == null){ + User user = new User(name,0.0); + UserDao.getInstance().saveUser(user); + return user; + } + return null; } } \ No newline at end of file diff --git a/WarpDrinkApi/src/main/webapp/WEB-INF/web.out.xml b/WarpDrinkApi/src/main/webapp/WEB-INF/web.out.xml deleted file mode 100644 index e69de29..0000000 diff --git a/WarpDrinkApi/src/main/webapp/WEB-INF/web.xml b/WarpDrinkApi/src/main/webapp/WEB-INF/web.xml index bf12269..8f6bce9 100644 --- a/WarpDrinkApi/src/main/webapp/WEB-INF/web.xml +++ b/WarpDrinkApi/src/main/webapp/WEB-INF/web.xml @@ -5,7 +5,7 @@ <web-app> <servlet> <servlet-name>REST Service</servlet-name> - <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> + <servlet-class>ms.itsecteam.warpdrink.Servlet</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>ms.itsecteam.warpdrink.provider</param-value> diff --git a/WarpDrinkApp/.idea/gradle.xml b/WarpDrinkApp/.idea/gradle.xml index 3068cd4..3ec5955 100644 --- a/WarpDrinkApp/.idea/gradle.xml +++ b/WarpDrinkApp/.idea/gradle.xml @@ -5,8 +5,8 @@ <GradleProjectSettings> <option name="distributionType" value="LOCAL" /> <option name="externalProjectPath" value="$PROJECT_DIR$" /> - <option name="gradleHome" value="C:\Program Files\Android\Android Studio\gradle\gradle-2.2.1" /> - <option name="gradleJvm" value="1.8" /> + <option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.2.1" /> + <option name="gradleJvm" value="1.7" /> <option name="modules"> <set> <option value="$PROJECT_DIR$" /> diff --git a/WarpDrinkApp/.idea/misc.xml b/WarpDrinkApp/.idea/misc.xml index e284b1d..f6607a5 100644 --- a/WarpDrinkApp/.idea/misc.xml +++ b/WarpDrinkApp/.idea/misc.xml @@ -13,7 +13,7 @@ <ConfirmationsSetting value="0" id="Add" /> <ConfirmationsSetting value="0" id="Remove" /> </component> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/build/classes" /> </component> <component name="ProjectType"> diff --git a/WarpDrinkApp/.idea/vcs.xml b/WarpDrinkApp/.idea/vcs.xml index 6c0b863..6564d52 100644 --- a/WarpDrinkApp/.idea/vcs.xml +++ b/WarpDrinkApp/.idea/vcs.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="VcsDirectoryMappings"> - <mapping directory="$PROJECT_DIR$/.." vcs="Git" /> + <mapping directory="" vcs="" /> </component> </project> \ No newline at end of file diff --git a/WarpDrinkApp/app/app.iml b/WarpDrinkApp/app/app.iml index fbe226f..89bc1db 100644 --- a/WarpDrinkApp/app/app.iml +++ b/WarpDrinkApp/app/app.iml @@ -86,19 +86,20 @@ <excludeFolder url="file://$MODULE_DIR$/build/outputs" /> <excludeFolder url="file://$MODULE_DIR$/build/tmp" /> </content> - <orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" /> + <orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" /> <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="library" exported="" name="codepath-oauth-0.4.1" level="project" /> <orderEntry type="library" exported="" name="scribe-codepath-0.0.3" level="project" /> <orderEntry type="library" exported="" name="activeandroid-3.0" level="project" /> - <orderEntry type="library" exported="" name="codepath-utils" level="project" /> - <orderEntry type="library" exported="" name="jackson-databind-2.0.1" level="project" /> <orderEntry type="library" exported="" name="jackson-core-2.0.1" level="project" /> - <orderEntry type="library" exported="" name="jackson-annotations-2.0.1" level="project" /> <orderEntry type="library" exported="" name="support-annotations-22.2.0" level="project" /> <orderEntry type="library" exported="" name="support-v4-22.2.0" level="project" /> <orderEntry type="library" exported="" name="spring-android-rest-template-1.0.1.RELEASE" level="project" /> - <orderEntry type="library" exported="" name="spring-android-core-1.0.1.RELEASE" level="project" /> <orderEntry type="library" exported="" name="appcompat-v7-22.2.0" level="project" /> + <orderEntry type="library" exported="" name="gson-1.7.2" level="project" /> + <orderEntry type="library" exported="" name="codepath-utils" level="project" /> + <orderEntry type="library" exported="" name="jackson-databind-2.0.1" level="project" /> + <orderEntry type="library" exported="" name="httpclient-android-4.3.5.1" level="project" /> + <orderEntry type="library" exported="" name="jackson-annotations-2.0.1" level="project" /> + <orderEntry type="library" exported="" name="spring-android-core-1.0.1.RELEASE" level="project" /> </component> </module> \ No newline at end of file diff --git a/WarpDrinkApp/app/build.gradle b/WarpDrinkApp/app/build.gradle index 01399bd..e2b6e48 100644 --- a/WarpDrinkApp/app/build.gradle +++ b/WarpDrinkApp/app/build.gradle @@ -1,8 +1,8 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 22 - buildToolsVersion "23.0.0 rc2" + compileSdkVersion 21 + buildToolsVersion '23.0.0 rc2' defaultConfig { applicationId "ms.itsecteam.warpdrink" @@ -28,8 +28,11 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + compile fileTree(include: ['*.jar'], dir: 'libs') compile 'com.android.support:appcompat-v7:22.2.0' compile 'com.fasterxml.jackson.core:jackson-databind:2.0.1' compile 'org.springframework.android:spring-android-rest-template:1.0.1.RELEASE' + compile 'com.google.code.gson:gson:1.7.2' + compile group: 'org.apache.httpcomponents' , name: 'httpclient-android' , version: '4.3.5.1' + } diff --git a/WarpDrinkApp/app/libs/codepath-oauth-0.4.1.jar b/WarpDrinkApp/app/libs/codepath-oauth-0.4.1.jar deleted file mode 100644 index 9b92c0a1451d8b4c3d4d7395f9020a1187218fa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25162 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%0Db@{QGSy@YmKV_)VF9$^~r= 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 diff --git a/WarpDrinkApp/app/src/main/AndroidManifest.xml b/WarpDrinkApp/app/src/main/AndroidManifest.xml index 93792b6..4e628c4 100644 --- a/WarpDrinkApp/app/src/main/AndroidManifest.xml +++ b/WarpDrinkApp/app/src/main/AndroidManifest.xml @@ -14,7 +14,7 @@ <meta-data android:name="AA_DB_VERSION" android:value="5" /> <meta-data android:name="AA_MODELS" - android:value="ms.itsecteam.warpdrink.data.User" /> + android:value="ms.itsecteam.warpdrink.data.objects.User" /> <activity android:name=".MainActivity" android:label="@string/app_name" diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/MainActivity.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/MainActivity.java index 118683b..d831c3e 100644 --- a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/MainActivity.java +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/MainActivity.java @@ -2,8 +2,10 @@ package ms.itsecteam.warpdrink; import android.app.AlertDialog; import android.content.DialogInterface; +import android.provider.ContactsContract; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; +import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; @@ -19,11 +21,12 @@ import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.ListIterator; import ms.itsecteam.warpdrink.data.DataApi; -import ms.itsecteam.warpdrink.data.RestClient; +import ms.itsecteam.warpdrink.data.rest.RestClient; import ms.itsecteam.warpdrink.data.objects.User; import ms.itsecteam.warpdrink.dialogs.ChargeDialog; import ms.itsecteam.warpdrink.dialogs.NewUserDialog; @@ -51,12 +54,6 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - User.deleteAll(); - new User(2, "hans", 100.0).save(); - new User(3, "meier", 10.0).save(); - new User(3, "merten", 1.0).save(); - new User(4, "dieter", 1.0).save(); - new User(5, "detlef", 0.5).save(); getWindow().addFlags(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); setContentView(R.layout.activity_main); @@ -76,8 +73,9 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe this.lstOrdered = (ListView) findViewById(R.id.lstOrdered); this.lstOrdered.setAdapter(this.lstAdapter); + this.users = User.getAll(); - this.atxvAdapter = new ArrayAdapter(this, android.R.layout.select_dialog_item, users); + this.atxvAdapter = new ArrayAdapter(this, android.R.layout.select_dialog_item, this.users); this.atxvName = (AutoCompleteTextView) findViewById(R.id.atxvName); this.atxvName.setAdapter(atxvAdapter); @@ -88,8 +86,9 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe this.btnLogout.setVisibility(View.INVISIBLE); this.enableControls(false); - RestClient restClient = RestClient.getInstance(); - restClient.getUser(); + + DataApi.getInstance().refreshUserData(); + } private void setCurrentUser(User user) { @@ -195,7 +194,8 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe new NewUserDialog(this).show(); break; case R.id.btnRefresh: - Toast.makeText(this,"refresh" ,Toast.LENGTH_LONG).show(); + DataApi.getInstance().refreshUserData(); + Toast.makeText(this,"Refresh successful" ,Toast.LENGTH_LONG).show(); break; } } @@ -204,11 +204,10 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction()==KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { if(this.atxvAdapter.getCount() == 1) { - setCurrentUser((User) this.atxvAdapter.getItem(0)); + setCurrentUser(DataApi.getInstance().remoteGetUser(((User) this.atxvAdapter.getItem(0)).getUserid())); this.atxvName.setText(this.atxvAdapter.getItem(0).toString()); + this.atxvName.dismissDropDown(); } - - setCurrentUser(User.getByName(this.atxvName.getText().toString())); return true; } return false; @@ -216,13 +215,14 @@ public class MainActivity extends ActionBarActivity implements View.OnClickListe @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - setCurrentUser((User) this.atxvAdapter.getItem(position)); + setCurrentUser(DataApi.getInstance().remoteGetUser(((User) this.atxvAdapter.getItem(position)).getUserid())); } @Override public void onClick(DialogInterface dialog, int which) { - this.currentUser.setCredit(this.currentUser.getCredit()-this.getTotal()); + this.currentUser.setCredit(this.currentUser.getCredit() - this.getTotal()); this.currentUser.save(); + RestClient.getInstance().saveUserCredit(this.currentUser); this.clearCurrentUser(); } public boolean onOptionsItemSelected(MenuItem item) { diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/DataApi.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/DataApi.java index 22a909e..d5ca1bc 100644 --- a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/DataApi.java +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/DataApi.java @@ -2,9 +2,12 @@ package ms.itsecteam.warpdrink.data; import android.util.Log; import java.util.Arrays; +import java.util.List; +import java.util.ListIterator; import ms.itsecteam.warpdrink.MainActivity; import ms.itsecteam.warpdrink.data.objects.User; +import ms.itsecteam.warpdrink.data.rest.RestClient; public class DataApi { @@ -31,24 +34,29 @@ public class DataApi { if(User.getByName(name) == null) { User u = new User(); u.setName(name); - u.save(); - remoteSaveNewUser(u); - localRefreshUserData(); + RestClient.getInstance().createUser(u); + //u.save(); + refreshUserData(); return true; } return false; } - public void localRefreshUserData() { - Log.d("App", Arrays.toString(User.getAll().toArray())); + public void refreshUserData() { + List<User> u = RestClient.getInstance().getAllUser(); + if(u == null) + return; + User.deleteAll(); + ListIterator<User> ui = u.listIterator(); + while(ui.hasNext()) { + ui.next().save(); + } + Log.d("App", Arrays.toString(u.toArray())); mainActivity.refreshUsers(); } - private boolean remoteSaveNewUser(User u) { - return true; - } public User remoteGetUser(int userid) { - return new User(); + return RestClient.getInstance().getUser(userid); } } diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/RestClient.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/RestClient.java deleted file mode 100644 index bce08f6..0000000 --- a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/RestClient.java +++ /dev/null @@ -1,70 +0,0 @@ -package ms.itsecteam.warpdrink.data; - -import android.os.AsyncTask; -import android.util.Log; - -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.web.client.RestTemplate; - -import ms.itsecteam.warpdrink.MainActivity; -import ms.itsecteam.warpdrink.data.objects.User; - -public class RestClient { - - private static RestClient instance; - private MainActivity mainActivity; - private RestClient() {} - - public static RestClient getInstance () { - if (RestClient.instance == null) { - RestClient.instance = new RestClient(); - } - return RestClient.instance; - } - - public MainActivity getMainActivity() { - return mainActivity; - } - - public void setMainActivity(MainActivity mainActivity) { - this.mainActivity = mainActivity; - } - - public void getUser() { - new HttpRequestTask<User>().initTask("user/4",User.class).execute(); - } - - private class HttpRequestTask<T> extends AsyncTask<Object, Void, T> { - String url; - Class<T> clazz; - public HttpRequestTask initTask(String url, Class<T> clazz) { - this.url = "http://10.0.2.2:8080/warpdrink/rest/"; - - this.url += url; - this.clazz=clazz; - return this; - } - @Override - protected T doInBackground(Object... params) { - try { - RestTemplate restTemplate = new RestTemplate(); - restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); - T ret = restTemplate.getForObject(this.url, clazz); - - return ret; - } catch (Exception e) { - Log.e("MainActivity", e.getMessage(), e); - } - - return null; - } - - @Override - protected void onPostExecute(T result) { - Log.e("MainActivity", ((User) result).getName()); - } - - } - -} - diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/objects/Setting.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/objects/Setting.java index 2ae4ad1..46efb14 100644 --- a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/objects/Setting.java +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/objects/Setting.java @@ -8,7 +8,7 @@ import com.activeandroid.query.Select; import java.util.List; -@Table(name = "Users") +@Table(name = "Settings") public class Setting extends Model { @Column(name = "key") diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/objects/User.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/objects/User.java index ed159e1..764f381 100644 --- a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/objects/User.java +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/objects/User.java @@ -13,11 +13,13 @@ public class User extends Model { @Column(name = "userid") private int userid; - @Column(name = "name") - private String name; + @Column(name = "credit") private double credit; + @Column(name = "name") + private String name; + public User() { super(); } diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RequestSingleObject.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RequestSingleObject.java new file mode 100644 index 0000000..565853c --- /dev/null +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RequestSingleObject.java @@ -0,0 +1,37 @@ +package ms.itsecteam.warpdrink.data.rest; + +import android.os.AsyncTask; +import android.util.Log; + +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +public class RequestSingleObject<T> extends AsyncTask<Object, Void, T> { + String url; + Class<T> clazz; + public RequestSingleObject initTask(String url, Class<T> clazz) { + this.url = "http://10.0.2.2:8080/warpdrink/rest/"; + + this.url += url; + this.clazz=clazz; + return this; + } + @Override + protected T doInBackground(Object... params) { + try { + RestTemplate restTemplate = new RestTemplate(); + restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); + T ret = restTemplate.getForObject(this.url, clazz); + + return ret; + } catch (Exception e) { + Log.e("MainActivity", e.getMessage(), e); + } + + return null; + } + + @Override + protected void onPostExecute(T result) { } + +} diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RequestUserList.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RequestUserList.java new file mode 100644 index 0000000..4338dfe --- /dev/null +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RequestUserList.java @@ -0,0 +1,50 @@ +package ms.itsecteam.warpdrink.data.rest; + +import android.os.AsyncTask; +import android.util.Log; + +import com.google.gson.Gson; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Arrays; +import java.util.List; + +import ms.itsecteam.warpdrink.data.objects.User; + +public class RequestUserList extends AsyncTask<Object, Void, List<User>> { + String url; + public RequestUserList initTask(String url) { + this.url = "http://10.0.2.2:8080/warpdrink/rest/"; + this.url += url; + return this; + } + @Override + protected List<User> doInBackground(Object... params) { + User[] x; + try { + String line; + String response=""; + OutputStreamWriter writer; + BufferedReader reader; + HttpURLConnection conn; + try { + conn = (HttpURLConnection) new URL(this.url).openConnection(); + conn.setDoOutput(true); + reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); + while ((line = reader.readLine()) != null) { response += line; } + Log.d("TV",response); + x = new Gson().fromJson(response, User[].class); + reader.close(); + return Arrays.asList(x); + } catch (Exception e) { Log.d("TV",e.toString()); } + } catch (Exception e) { + Log.e("MainActivity", e.getMessage(), e); + } + return null; + } + +} diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RestClient.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RestClient.java new file mode 100644 index 0000000..ed89a3f --- /dev/null +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/RestClient.java @@ -0,0 +1,76 @@ +package ms.itsecteam.warpdrink.data.rest; + +import android.util.Log; + +import com.google.gson.Gson; + +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import ms.itsecteam.warpdrink.MainActivity; +import ms.itsecteam.warpdrink.data.objects.User; +import ms.itsecteam.warpdrink.data.rest.http.HttpGetRequest; +import ms.itsecteam.warpdrink.data.rest.http.HttpPostRequest; +import ms.itsecteam.warpdrink.data.rest.http.HttpPutRequest; + +public class RestClient { + + private static RestClient instance; + private MainActivity mainActivity; + private RestClient() {} + + public static RestClient getInstance () { + if (RestClient.instance == null) { + RestClient.instance = new RestClient(); + } + return RestClient.instance; + } + + public User getUser(int userid) { + try { + User u = (User) new RequestSingleObject<User>().initTask("user/"+userid,User.class).execute().get(); + Log.d("TV",u.getName()); + return u; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + public List<User> getAllUser() { + try { + String response = new HttpGetRequest().initTask("user/all").execute().get(); + return Arrays.asList(new Gson().fromJson(response, User[].class)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + public void saveUserCredit(User u) { + List<NameValuePair> postParams = new ArrayList<NameValuePair>(2); + postParams.add(new BasicNameValuePair("credit", String.valueOf(u.getCredit()))); + new HttpPostRequest().initTask("/user/"+u.getUserid(),postParams).execute(); + } + public boolean createUser(User u) { + List<NameValuePair> postParams = new ArrayList<NameValuePair>(2); + postParams.add(new BasicNameValuePair("name", u.getName())); + try { + String response = new HttpPutRequest().initTask("/user/create",postParams).execute().get(); + if(response != "") { + u = new Gson().fromJson(response, User.class); + if(u.getUserid() != 0) { + u.save(); + return true; + } + } + + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } +} + diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpGetRequest.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpGetRequest.java new file mode 100644 index 0000000..a5ab9ba --- /dev/null +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpGetRequest.java @@ -0,0 +1,42 @@ +package ms.itsecteam.warpdrink.data.rest.http; + +import android.os.AsyncTask; +import android.util.Log; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +public class HttpGetRequest extends AsyncTask<Void, Void, String> { + String url; + public HttpGetRequest initTask(String url) { + this.url = "http://10.0.2.2:8080/warpdrink/rest/"; + this.url += url; + return this; + } + @Override + protected String doInBackground(Void... params) { + try { + HttpClient client = new DefaultHttpClient(); + HttpGet request = new HttpGet(this.url); + + HttpResponse response = client.execute(request); + BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); + + String line = ""; + String responsestr=""; + while ((line = rd.readLine()) != null) { + responsestr += line; + } + return responsestr; + } catch (Exception e) { + Log.e("MainActivity", e.getMessage(), e); + } + return null; + } + +} diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpPostRequest.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpPostRequest.java new file mode 100644 index 0000000..8150020 --- /dev/null +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpPostRequest.java @@ -0,0 +1,49 @@ +package ms.itsecteam.warpdrink.data.rest.http; + +import android.os.AsyncTask; +import android.util.Log; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.DefaultHttpClient; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.List; + +public class HttpPostRequest extends AsyncTask<Void, Void, String> { + String url; + List<NameValuePair> postParams; + public HttpPostRequest initTask(String url, List<NameValuePair> postParams) { + this.url = "http://10.0.2.2:8080/warpdrink/rest/"; + this.url += url; + this.postParams =postParams; + return this; + } + @Override + protected String doInBackground(Void... params) { + try { + HttpClient client = new DefaultHttpClient(); + HttpPost request = new HttpPost(this.url); + + request.setEntity(new UrlEncodedFormEntity(this.postParams, "UTF-8")); + + HttpResponse response = client.execute(request); + BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); + + String line = ""; + String responsestr=""; + while ((line = rd.readLine()) != null) { + responsestr += line; + } + return responsestr; + } catch (Exception e) { + Log.e("MainActivity", e.getMessage(), e); + } + return null; + } + +} diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpPutRequest.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpPutRequest.java new file mode 100644 index 0000000..b0dcd7b --- /dev/null +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/data/rest/http/HttpPutRequest.java @@ -0,0 +1,49 @@ +package ms.itsecteam.warpdrink.data.rest.http; + +import android.os.AsyncTask; +import android.util.Log; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.impl.client.DefaultHttpClient; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.List; + +public class HttpPutRequest extends AsyncTask<Void, Void, String> { + String url; + List<NameValuePair> postParams; + public HttpPutRequest initTask(String url, List<NameValuePair> postParams) { + this.url = "http://10.0.2.2:8080/warpdrink/rest/"; + this.url += url; + this.postParams =postParams; + return this; + } + @Override + protected String doInBackground(Void... params) { + try { + HttpClient client = new DefaultHttpClient(); + HttpPut request = new HttpPut(this.url); + + request.setEntity(new UrlEncodedFormEntity(this.postParams, "UTF-8")); + + HttpResponse response = client.execute(request); + BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); + + String line = ""; + String responsestr=""; + while ((line = rd.readLine()) != null) { + responsestr += line; + } + return responsestr; + } catch (Exception e) { + Log.e("MainActivity", e.getMessage(), e); + } + return null; + } + +} diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/ChargeCustomDialog.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/ChargeCustomDialog.java index b4fcc7f..08a3f49 100644 --- a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/ChargeCustomDialog.java +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/ChargeCustomDialog.java @@ -10,6 +10,7 @@ import android.widget.NumberPicker; import ms.itsecteam.warpdrink.MainActivity; import ms.itsecteam.warpdrink.R; import ms.itsecteam.warpdrink.data.objects.User; +import ms.itsecteam.warpdrink.data.rest.RestClient; public class ChargeCustomDialog extends Dialog implements View.OnClickListener { @@ -53,6 +54,7 @@ public class ChargeCustomDialog extends Dialog implements User u = this.c.getCurrentUser(); u.setCredit(u.getCredit()+amount); u.save(); + RestClient.getInstance().saveUserCredit(u); } this.c.refreshCreditTextView(); dismiss(); diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/ChargeDialog.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/ChargeDialog.java index 589a6f5..5436935 100644 --- a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/ChargeDialog.java +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/ChargeDialog.java @@ -9,6 +9,7 @@ import android.widget.Button; import ms.itsecteam.warpdrink.MainActivity; import ms.itsecteam.warpdrink.R; import ms.itsecteam.warpdrink.data.objects.User; +import ms.itsecteam.warpdrink.data.rest.RestClient; public class ChargeDialog extends Dialog implements android.view.View.OnClickListener { @@ -62,6 +63,7 @@ public class ChargeDialog extends Dialog implements User u = this.c.getCurrentUser(); u.setCredit(u.getCredit()+amount); u.save(); + RestClient.getInstance().saveUserCredit(u); } this.c.refreshCreditTextView(); dismiss(); diff --git a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/NewUserDialog.java b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/NewUserDialog.java index aaaf347..6f0751d 100644 --- a/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/NewUserDialog.java +++ b/WarpDrinkApp/app/src/main/java/ms/itsecteam/warpdrink/dialogs/NewUserDialog.java @@ -11,6 +11,7 @@ import android.widget.Toast; import ms.itsecteam.warpdrink.MainActivity; import ms.itsecteam.warpdrink.R; import ms.itsecteam.warpdrink.data.DataApi; +import ms.itsecteam.warpdrink.data.rest.RestClient; public class NewUserDialog extends Dialog implements View.OnClickListener { diff --git a/WarpDrinkApp/build.gradle b/WarpDrinkApp/build.gradle index 9405f3f..79381f1 100644 --- a/WarpDrinkApp/build.gradle +++ b/WarpDrinkApp/build.gradle @@ -1,5 +1,4 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. - buildscript { repositories { jcenter() @@ -11,9 +10,11 @@ buildscript { // in the individual module build.gradle files } } - allprojects { repositories { jcenter() } } + +dependencies { +} \ No newline at end of file -- GitLab