Spring mvc, making a menu data object - java

I'm really a newbie to JAVA, spring mvc.
And my understanding for "code" is so poor that I can't even think of how I'm going to get through with upcoming errors.
So this question will sound like " Do this for me!". ( It will do, actually )
Anyway, I'm trying to make a two-depth menu. Its structure looks like this below.
TopMenu
::: menuNo
::: menuName
::: memberType
::: url
::: sort
::: subMenus
::: menuNo
::: menuName
::: memberType
::: url
::: sort
TopMenu2
::: menuNo2
::: menuName2
::: memberType2
::: url2
.
.
.
.
So I made a bean class for this.
public class MenuInfoBean {
private String menuNo;
private String menuName;
private String memberType;
private String url;
private int sort;
List<MenuInfoBean> subMenus;
public MenuInfoBean() {
}
public String getMenuNo() {
return menuNo;
}
public void setMenuNo(String menuNo) {
this.menuNo = menuNo;
}
public String getMenuName() {
return menuName;
}
public void setMenuName(String menuName) {
this.menuName = menuName;
}
public String getMemberType() {
return memberType;
}
public void setMemberType(String memberType) {
this.memberType = memberType;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getSort() {
return sort;
}
public void setSort(int sort) {
this.sort = sort;
}
public List<MenuInfoBean> getSubMenus() {
return subMenus;
}
public void setSubMenus(MenuInfoBean subMenus) {
subMenus.menuName = subMenus.menuName;
subMenus.memberType = subMenus.memberType;
subMenus.url = subMenus.url;
subMenus.sort = subMenus.sort;
}
}
Which database will be used is not decided yet, so I'm temporarily using properties for menu data.
#TopMenu List
topmenu = M1000,M9000
#SubMenu List
M1000.submenu =
M9000.submenu = M9001,M9002,M9003,M9004
#TopMenu Info
#M1000 APPLICATION
M1000.menuName=APPLICATION
M1000.url=
M1000.memberType=00,10
M1000.sort=1
#M9000 ADMIN
M9000.menuName=ADMIN
M9000.url=/SYS01/memberList.mon
M9000.memberType=00,10
M9000.sort=1
#SubMenu Info
#M9000 ADMIN's
M9001.menuName=Member mgmt
M9001.url=/SYS01/memberList.mon
M9001.memberType=00,10
M9001.sort=1
M9002.menuName=menu2
M9002.url=/SYS01/memberList.mon
M9002.memberType=00,10
M9002.sort=1
M9003.menuName=menu3
M9003.url=/SYS01/memberList.mon
M9003.memberType=00,10
M9003.sort=1
M9004.menuName=menu4
M9004.url=/SYS01/memberList.mon
M9004.memberType=00,10
M9004.sort=1
And here I fetch the data and try to put them into a List.
public class MenuManager {
public List<MenuInfoBean> getMenus(String permissionCode) {
LabelProperties msgResource = LabelProperties.getInstance();
MenuInfoBean menuInfo = new MenuInfoBean();
List<MenuInfoBean> menuList = new ArrayList<MenuInfoBean>();
String topMenu = msgResource.getProperty("topmenu");
String[] topMenuItems = topMenu.split(",");
for (int i = 0; topMenuItems.length > i; i++ ) {
String subMenuName = msgResource.getProperty(topMenuItems[i] + ".submenu");
if ( subMenuName.isEmpty() == false ) {
menuInfo.setMenuName(msgResource.getProperty(subMenuName + ".menuName"));
menuInfo.setMemberType(msgResource.getProperty(subMenuName + ".memberType"));
menuInfo.setUrl(msgResource.getProperty(subMenuName + ".url"));
menuInfo.setSort(Integer.parseInt(msgResource.getProperty(subMenuName + ".sort")));
menuInfo.setSubMenus(menuInfo);
} else {
menuInfo.setMenuName("");
menuInfo.setSubMenus(menuInfo);
}
menuInfo.setMenuNo("");
menuInfo.setMenuName(msgResource.getProperty(topMenuItems[i] + ".menuName"));
menuInfo.setMemberType(msgResource.getProperty(topMenuItems[i] + ".memberType"));
menuInfo.setUrl(msgResource.getProperty(topMenuItems[i] + ".url"));
menuInfo.setSort(Integer.parseInt(msgResource.getProperty(topMenuItems[i] + ".sort")));
menuList.add(menuInfo);
}
return menuList;
}
}
getProperty method works great. It gets the properties value correctly.
But as you may noticed, there's some null data is being made.
to ignore this NullPointerException, I made
List<MenuInfoBean> menuList = new ArrayList<MenuInfoBean>();
So the exception has been successfully avoided. But another error comes up which isn't important in this post....
Anyway, while trying to solve the new error, I looked into the menuInfo data and found out something wrong was going on.
The subMenus was holding the topMenu's data!
Here's the question, How can I make this menu with MenuInfoBean like the structure I mentioned on the top of this post?
And why subMenus data was holding topMenu's properties?
I set subMenus data first, and topMenu data later! why this happens?

First of all I am updating the domain object by adding a additional method add(Meun)
import java.util.ArrayList;
import java.util.List;
public class MenuInfoBean
{
private String menuNo;
private String menuName;
private String memberType;
private String url;
private int sort;
List<MenuInfoBean> subMenus;
public MenuInfoBean()
{
}
public String getMenuNo()
{
return menuNo;
}
public void setMenuNo(String menuNo)
{
this.menuNo = menuNo;
}
public String getMenuName()
{
return menuName;
}
public void setMenuName(String menuName)
{
this.menuName = menuName;
}
public String getMemberType()
{
return memberType;
}
public void setMemberType(String memberType)
{
this.memberType = memberType;
}
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
public int getSort()
{
return sort;
}
public void setSort(int sort)
{
this.sort = sort;
}
public List<MenuInfoBean> getSubMenus()
{
return subMenus;
}
// This is new method added to the bean
public void addSubMenuItem(MenuInfoBean menuInfoBean)
{
if (subMenus == null)
subMenus = new ArrayList<MenuInfoBean>();
subMenus.add(menuInfoBean);
}
}
Here is the class that generate the menu and return (look at the get menu method):
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang.StringUtils;
public class MenuExtractionComponent
{
public List<MenuInfoBean> getMenus(String permissionCode)
{
LabelProperties msgResource = LabelProperties.getInstance();
List<MenuInfoBean> menuList = new ArrayList<MenuInfoBean>();
String topMenu = msgResource.getProperty("topmenu");
List<String> topMenuItems = new ArrayList<String>();
// Checking is top menu empty
if (StringUtils.isNotBlank(topMenu))
{
topMenuItems.addAll(Arrays.asList(topMenu.split(",")));
}
for (String topMenuItem : topMenuItems)
{
// Setting top menu details
MenuInfoBean menuInfo = new MenuInfoBean();
menuInfo.setMenuNo("");
menuInfo.setMenuName(msgResource.getProperty(topMenuItem + ".menuName"));
menuInfo.setMemberType(msgResource.getProperty(topMenuItem + ".memberType"));
menuInfo.setUrl(msgResource.getProperty(topMenuItem + ".url"));
menuInfo.setSort(Integer.parseInt(msgResource.getProperty(topMenuItem + ".sort")));
String subMenu = msgResource.getProperty(topMenuItem + ".submenu");
List<String> subMenuItems = new ArrayList<String>();
// Checking is sub menu empty
if (StringUtils.isNotBlank(subMenu))
{
subMenuItems.addAll(Arrays.asList(subMenu.split(",")));
}
for (String subMenuItem : subMenuItems)
{
MenuInfoBean subMenuInfo = new MenuInfoBean();
subMenuInfo.setMenuName(msgResource.getProperty(subMenuItem + ".menuName"));
subMenuInfo.setMemberType(msgResource.getProperty(subMenuItem + ".memberType"));
subMenuInfo.setUrl(msgResource.getProperty(subMenuItem + ".url"));
subMenuInfo.setSort(Integer.parseInt(msgResource.getProperty(subMenuItem + ".sort")));
menuInfo.addSubMenuItem(subMenuInfo);
}
menuList.add(menuInfo);
}
return menuList;
}
}

Related

How to pass the global variable from one Test class to another test class and select that value in a dropdown in selenium?

I have this class ( DoctorRegistrationTest.java ) and having the global variable doctorCode , doctorFirstName , doctorFamilyName )
#BeforeMethod(groups = {"BVT", "Regression"})
public void loadRmsPage() {
loadRmsProfile();
softAssert = new SoftAssert();
doctorRegistrationPage = new DoctorRegistrationPage(webDriver);
}
#Epic("RMS - Create Doctor")
#Feature("RMS - Create Doctor functionality")
#Story("AUT-688")
#Severity(SeverityLevel.BLOCKER)
#Test(description = "Positive : Doctor Creation ", groups = {"BVT", "Regression"})
public void createDoctorTestMethod() {
do {
doctorCode = String.valueOf(generateRandomNumber(1000, 9999));
} while (false && doctorRegistrationPage.verifyCreatedDoctor(doctorCode));
setDoctorRegistrationInformation();
createDoctor();
}
public void createDoctor() {
doctorRegistrationPage.loadDoctorRegistrationPage();
doctorRegistrationPage.fillDoctorNameInformation(doctorCode, doctorFirstName, doctorFamilyName, doctorFirstNameInArabic, doctorFamilyNameInArabic);
doctorRegistrationPage.fillDoctorGeneralInformation(dateOfBirth, joinDate, identityNo, expiryDate, gender, doctorTitle, employmentType, identityType);
doctorRegistrationPage.fillDoctorContactInformation(mobileNumber, companyEmail);
doctorRegistrationPage.fillDoctorOtherInformation(doctorInformationEnglish, doctorInformationArabic);
doctorRegistrationPage.fillDoctorTiming(followUpDays, slotDurationMinutes);
doctorRegistrationPage.fillDoctorHospitalsAndClinics(hospital, clinics);
doctorRegistrationPage.fillDoctorDefaultProcedure(defaultProcedur, consultationProcedure);
boolean result = doctorRegistrationPage.verifyCreatedDoctor(doctorCode);
LOG.info("Return value of verifyCreatedDoctor method " + result);
softAssert.assertTrue(result, "TEST FAILED - CREATED DOCTOR NOT LISTING IN THE GRID");
softAssert.assertAll();
doctorRegistrationPage.logOutUser();
}
public void setDoctorRegistrationInformation() {
readPropertiesFile();
setNames();
setNumberValues();
setDate();
}
public void setNames() {
doctorFirstName = "AUT DN " + getRandomStringName(4);
doctorFamilyName = "AUT DFN " + getRandomStringName(4);
companyEmail = getRandomStringName(5) + "#aut.com";
doctorInformationEnglish = getRandomStringName(6);
}
public String getRandomStringName(int randomStringLength) {
return RandomStringUtils.randomAlphabetic(randomStringLength).toLowerCase();
}
public int generateRandomNumber(int low, int high) {
return (new Random()).nextInt(high - low) + low;
}
}
I have another class ( DoctorScheduleTest.java ) and needs to pass doctorCode , doctorFirstName , doctorFamilyName from (DoctorRegistrationTest.java ) to doctorSchedulePage.selectDoctorDropdown(doctor); method, instead of hardcoding the detail. Must pass the value like this (" doctorCode: doctorFirstName doctorFamilyName )
private String doctor =" 8938: AUT DN gvgl AUT DFN wnrn ";
#BeforeMethod(groups = {"BVT", "Regression"})
public void loadRmsPage()
{
loadRmsProfile();
softAssert = new SoftAssert();
doctorSchedulePage = new DoctorSchedulePage(webDriver);
}
#Epic("RMS")
#Feature("RMS - Create Doctor Schedule functionality")
#Story("AUT-835")
#Severity(SeverityLevel.BLOCKER)
#Test(description = "Positive : Doctor Schedule Creation", groups = {"BVT", "Regression"})
public void doctorScheduleCreationTestMethod()
{
setTemplateName();
createInitialSchedule();
setSchedule();
saveTemplate();
setTemplate();
setDateRange();
generateSchedule();
}
public void createInitialSchedule()
{
doctorSchedulePage.loadDoctorScheduleDashboard();
doctorSchedulePage.selectHospitalDropDown(hospital);
doctorSchedulePage.selectClinicDropDown(clinic);
doctorSchedulePage.selectDoctorDropdown(doctor);
doctorSchedulePage.fillTemplate(scheduleTemplateName);
}
public void setSchedule()
{
doctorSchedulePage.sundaySchedule(startHourTime,startMinuteTime,startSchedule,endHourTime,endMinuteTime,endSchedule);
doctorSchedulePage.mondaySchedule(startHourTime,startMinuteTime,startSchedule,endHourTime,endMinuteTime,endSchedule);
doctorSchedulePage.tuesdaySchedule(startHourTime,startMinuteTime,startSchedule,endHourTime,endMinuteTime,endSchedule);
doctorSchedulePage.wednesdaySchedule(startHourTime,startMinuteTime,startSchedule,endHourTime,endMinuteTime,endSchedule);
doctorSchedulePage.thursdaySchedule(startHourTime,startMinuteTime,startSchedule,endHourTime,endMinuteTime,endSchedule);
doctorSchedulePage.fridaySchedule(startHourTime,startMinuteTime,startSchedule,endHourTime,endMinuteTime,endSchedule);
doctorSchedulePage.saturdaySchedule(startHourTime,startMinuteTime,startSchedule,endHourTime,endMinuteTime,endSchedule);
}
public void saveTemplate()
{
doctorSchedulePage.saveTemplate();
}
public void setTemplate()
{
doctorSchedulePage.selectTemplateDropdown(scheduleTemplateName);
}
public void setDateRange()
{
doctorSchedulePage.selectScheduleDate(scheduleStartDate,scheduleEndDate);
}
public void generateSchedule()
{
doctorSchedulePage.generateSchedule();
}
public int generateRandomNumber(int low, int high)
{
return (new Random()).nextInt(high - low) + low;
}
public void setTemplateName()
{
scheduleTemplateName = "Template " + getRandomStringName(3);
}
public String getRandomStringName(int randomStringLength)
{
return RandomStringUtils.randomAlphabetic(randomStringLength).toLowerCase();
}
}
DoctorSchedulePage.java ( selectDoctorDropdown method )
public void selectDoctorDropdown(String doctorcode)
{
selectValueFromDropDown(doctorDropdown, doctorcode);
}
BasePage.java (selectValueFromDropDown method )
protected void selectValueFromDropDown(WebElement element, String value) {
if (value != null && !value.isEmpty()) {
waitForElementToPresent(element);
Select dropdown = new Select(element);
LOG.info("Selected "+value);
dropdown.selectByVisibleText(value);
}
}
First of all, your question indicates, that you have an issue with passing a test data into tests. That should be addressed in the first place.
Since that is another topic (and a much bigger one) I would recommend a workaround, using a separate class, with a doctor's data.
public static class Doctor{
public static String FirstName;
public static String FamilyName;
Initialize the data in the setup and use is whenever you need.
As I said before, that is not the best solution, as testing data should be kept outside of the tests, but might be helpful for now.

I need Freemarker documentation for data model when using #recurse with trees other than XML

I am trying to process a tree structure in Freemarker and would like use the #recurse, #visit directives but I can't find any good documentation on how to set up the data model. The only examples I can see are those that create a data model for an XML structure. I don't need it to be so detailed. My tree is very simple.
In trying to test the functionality I need, I built a unit test but when I run it I get
FreeMarker template error:
For "." left-hand operand: Expected a hash, but this has evaluated to a node
Here is the source code:
public class FreemarkerXmlTests {
static class Element implements TemplateNodeModel {
private final String name;
private final String text;
private Element parent;
private final List<Element> elements = new ArrayList<>();
public Element(String name) {
this(name, null);
}
public Element(String name, String text) {
this.name = name;
this.text = text;
}
public void add(Element element) {
element.parent = this;
this.elements.add(element);
}
public List<Element> getElements() {
return this.elements;
}
public String getName() {
return this.name;
}
public String getText() {
return this.text;
}
public String getTitle() {
return this.name;
}
public TemplateModel get(String key) {
return null;
}
#Override
public TemplateNodeModel getParentNode() throws TemplateModelException {
return this.parent;
}
#Override
public TemplateSequenceModel getChildNodes() throws TemplateModelException {
// TODO Auto-generated method stub
return new SimpleSequence(this.elements, cfg.getObjectWrapper());
}
#Override
public String getNodeName() throws TemplateModelException {
return this.name;
}
#Override
public String getNodeType() throws TemplateModelException {
return this.name;
}
#Override
public String getNodeNamespace() throws TemplateModelException {
return null;
}
}
private static Configuration cfg;
private static final String myTestTemplate = "<#recurse doc>\r\n" +
"\r\n" +
"<#macro book>\r\n" +
" Book element with title ${.node.title} \r\n" +
" <#recurse>\r\n" +
" End book\r\n" +
"</#macro>\r\n" +
"\r\n" +
"<#macro title>\r\n" +
" Title element\r\n" +
"</#macro>\r\n" +
"\r\n" +
"<#macro chapter>\r\n" +
" Chapter element with title: ${.node.title}\r\n" +
"</#macro>";
#BeforeClass
public static void classInit() throws IOException {
StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
stringTemplateLoader.putTemplate("myTestTemplate", myTestTemplate);
cfg = new Configuration(Configuration.VERSION_2_3_29);
cfg.setTemplateLoader(stringTemplateLoader);
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
cfg.setLogTemplateExceptions(false);
cfg.setWrapUncheckedExceptions(true);
cfg.setFallbackOnNullLoopVariable(false);
}
#Test
public void basicXmlTest() throws TemplateException, IOException {
Element doc = new Element("doc");
Element book = new Element("book");
book.add(new Element("title", "Test Book"));
doc.add(book);
Element chapter1 = new Element("chapter");
chapter1.add(new Element("title", "Ch1"));
chapter1.add(new Element("para", "p1.1"));
chapter1.add(new Element("para", "p1.2"));
chapter1.add(new Element("para", "p1.3"));
book.add(chapter1);
Element chapter2 = new Element("chapter");
chapter2.add(new Element("title", "Ch2"));
chapter2.add(new Element("para", "p2.1"));
chapter2.add(new Element("para", "p2.2"));
chapter2.add(new Element("para", "p2.3"));
book.add(chapter2);
Map<String, Object> root = new HashMap<>();
// Put string "user" into the root
root.put("doc", doc);
Template temp = cfg.getTemplate("myTestTemplate");
Writer out = new OutputStreamWriter(System.out);
temp.process(root, out);
}
Any ideas?
Take a look at the freemarker.template.TemplateNodeModel interface. Your objects have to implement that, or they have to be wrapped (via the ObjectWrapper) into a TemplateModel the implements that. Then #recurse/#visit/?parent/?children/etc. will work with them.
Here's an example of implementing TemplateNodeModel for traversing JSON: https://github.com/freemarker/fmpp/blob/master/src/main/java/fmpp/models/JSONNode.java
Some templates where above is used:
https://github.com/freemarker/fmpp/tree/master/src/test/resources/tests/dl_json/src
As of the . operator, for that you need to implement TemplateHashModel (or its sub-interfaces, like TemplateHashModelEx2).
With the help of the examples posted by ddekany, I added the following:
implements TemplateHashModel to the Element class
static class Element implements TemplateNodeModel, TemplateHashModel {
a method to the Element class and the unit test worked:
#Override
public TemplateModel get(String key) throws TemplateModelException {
switch (key) {
case "title":
case "name":
return cfg.getObjectWrapper().wrap(this.name);
default:
throw new TemplateModelException("unknown hash get: " + key);
}
}

How to show coordinates-markers on Android App with Google Maps from XML file

I have an xml file with some places in it and their coordinates. I want to show those places on my android app on Google Maps as markers. I have already load the maps.
How could I do this? Any help would be so much appreciated, even if someone could explain it theoritically, as it seems I cant grasp its concept. Can someone help?
example of xml file(placesp.xml):
<placesp>
<placep>
<place_id>1</place_id>
<name>Place1</name>
<description>Place description 1</description>
<coordinates>;40.430224;21.559570</coordinates>
</placep>
<placep>
<place_id>2</place_id>
<name>Place2</name>
<description>Place description 2</description>
<coordinates>;40.423324;21.062439</coordinates>
</placep>
<placep>
<place_id>3</place_id>
<name>Place3</name>
<description>Place description 3</description>
<coordinates>;40.266952;21.238220</coordinates>
</placep>
</placesp>
Maybe you could use a HashMap to save the data.
You just create a new class like this:
public class Coordinates {
public static final HashMap<String, LatLng> COORDINATES = new HashMap<String, LatLng>();
static {
// Place1
COORDINATES.put("Place1", new LatLng(40.430224;21.559570));
}
}
You can access the data stored by the hashmap like this:
locationLatLng = new LatLng(Coordinates.COORDINATES.get("Place1").latitude,Coordinates.COORDINATES.get("Place1").longitude);
And then using this line in the class where you loaded the map to add the markers:
map.addMarker(new MarkerOptions().position(locationLatLng));
I am not really sure how to access data from the xml file, but in theory the logic is the same. You have to get a LatLng coordinate to tell the addMarker method where to put the marker, and thats actually it. I hope I could help you with this.
First you need to create a model class to hold the information for each place. I provide you a sample bellow: Place.class
public class Place {
private int placeId;
private String placeName;
private String placeDescription;
private double placeLongitude;
private double placeLatitude;
public Place() {
super();
}
public int getPlaceId() {
return placeId;
}
public void setPlaceId(final int placeId) {
this.placeId = placeId;
}
public String getPlaceName() {
return placeName;
}
public void setPlaceName(final String placeName) {
this.placeName = placeName;
}
public String getPlaceDescription() {
return placeDescription;
}
public void setPlaceDescription(final String placeDescription) {
this.placeDescription = placeDescription;
}
public double getPlaceLongitude() {
return placeLongitude;
}
public void setPlaceLongitude(final double placeLongitude) {
this.placeLongitude = placeLongitude;
}
public double getPlaceLatitude() {
return placeLatitude;
}
public void setPlaceLatitude(final double placeLatitude) {
this.placeLatitude = placeLatitude;
}
}
Next you will need a XML parser class to retrieve XML data to Place type list. You can use the following sample: PlaceXmlParser.class
public class PlaceXmlParser {
private static final String TAG = PlaceXmlParser.class.getSimpleName();
private static final String PLACE_ID = "place_id";
private static final String PLACE_NAME = "name";
private static final String PLACE_DESCRIPTION = "description";
private static final String PLACE_COORDINATES = "coordinates";
public PlaceXmlParser() {
super();
}
public List<Place> parsePlacesXml(final InputStream xmlStream) {
Place place = null;
final List<Place> placeList = new ArrayList<>();
try {
final XmlPullParserFactory xmlFactoryObject = XmlPullParserFactory.newInstance();
final XmlPullParser parser = xmlFactoryObject.newPullParser();
parser.setInput(xmlStream, null);
int event = parser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
if (event == XmlPullParser.START_TAG) {
final String name = parser.getName();
switch (name) {
case PLACE_ID:
place = new Place();
setPlaceId(parser, place);
break;
case PLACE_NAME:
setPlaceName(parser, place);
break;
case PLACE_DESCRIPTION:
setPlaceDescription(parser, place);
break;
case PLACE_COORDINATES:
setPlaceLatLong(parser, place);
placeList.add(place);
break;
}
}
event = parser.next();
}
} catch (final XmlPullParserException e) {
Log.e(TAG, e.toString());
} catch (final IOException e) {
Log.e(TAG, e.toString());
}
return placeList;
}
private boolean areValidArgs(final XmlPullParser parser, final Place place) {
return null != parser && null != place;
}
private void setPlaceId(final XmlPullParser parser, final Place place) {
if (areValidArgs(parser, place)) {
final String placeId = getTagValue(parser);
place.setPlaceId(Integer.parseInt(placeId));
}
}
private void setPlaceName(final XmlPullParser parser, final Place place) {
if (areValidArgs(parser, place)) {
final String placeName = getTagValue(parser);
place.setPlaceName(placeName);
}
}
private void setPlaceDescription(final XmlPullParser parser, final Place place) {
if (areValidArgs(parser, place)) {
final String placeDescription = getTagValue(parser);
place.setPlaceDescription(placeDescription);
}
}
private void setPlaceLatLong(final XmlPullParser parser, final Place place) {
if (areValidArgs(parser, place)) {
final String[] latLong = getTagValue(parser).split(";");
if (3 == latLong.length) {
place.setPlaceLatitude(Double.parseDouble(latLong[1]));
place.setPlaceLongitude(Double.parseDouble(latLong[2]));
}
}
}
private String getTagValue(final XmlPullParser parser) {
String result = "";
try {
if (parser.next() == XmlPullParser.TEXT) {
result = parser.getText();
parser.nextTag();
}
} catch (final XmlPullParserException e) {
Log.e(TAG, e.toString());
} catch (final IOException e) {
Log.e(TAG, e.toString());
}
return result;
}
}
Finally, in you Google Map's activity, implement OnMapReadyCallback interface, override onMapReady method and add place markers to Google Map: MapActivity.class
public class MapActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private List<Place> placeList;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
this.placeList = getPlaceList();
}
#Override
public void onMapReady(final GoogleMap googleMap) {
this.mMap = googleMap;
addPlaceListMarkersToGoogleMap();
}
private void addPlaceListMarkersToGoogleMap() {
for (final Place place : this.placeList) {
final LatLong latLong = new LatLong(place.getPlaceLatitude(), place.getPlaceLongitude());
this.mMap.addMarker(new MarkerOptions().position(latLong).title(place.getPlaceName()));
}
}
private List<Place> getPlaceList() {
final String xmlString = "<placesp>" +
"<placep>" +
" <place_id>1</place_id>" +
" <name>Place1</name>" +
" <description>Place description 1</description>" +
" <coordinates>;40.430224;21.559570</coordinates>" +
"</placep>" +
"<placep>" +
" <place_id>2</place_id>" +
" <name>Place2</name>" +
" <description>Place description 2</description>" +
" <coordinates>;40.423324;21.062439</coordinates>" +
"</placep>" +
"<placep>" +
" <place_id>3</place_id>" +
" <name>Place3</name>" +
" <description>Place description 3</description>" +
" <coordinates>;40.266952;21.238220</coordinates>" +
"</placep>" +
"</placesp>";
final InputStream xmlStream = getXmlStream(xmlString);
final PlaceXmlParser parser = new PlaceXmlParser();
return parser.parsePlacesXml(xmlStream);
}
private InputStream getXmlStream(final String xmlString) {
InputStream xmlStream = null;
try {
xmlStream = new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
} catch (final UnsupportedEncodingException e) {
e.printStackTrace();
}
return xmlStream;
}
}
Provided code works well for given XML sample, be aware of possible exceptions and handle it. Hope this help!

How do I combine two separate parsed jsonObjects into a single arraylist?

I would like to combine two separate parsed jsonObjects into a single arraylist, then display the results as Strings?
I would like to store summaryJsonObject & segment in storylineData. When I step through the code using the debugger summaryJsonObject & segment both hold the raw json. The raw json data also shows in the logcat but storylineData remains null & unavailable throughout.
Here is the parsing code.
public class StorylineData {
private static String date;
private ArrayList<SummaryData> summary;
private ArrayList<SegmentData> segments;
private String caloriesIdle;
private String lastUpdate;
public String getDate() {
return date;
}
public ArrayList<SummaryData> getSummary() {
return summary;
}
public ArrayList<SegmentData> getSegments() {
return segments;
}
public String getCaloriesIdle() {
return caloriesIdle;
}
public String getLastUpdate() {
return lastUpdate;
}
public void setDate(String date) {
this.date = date;
}
public void setSummary(ArrayList<SummaryData> summary) {
this.summary = summary;
}
public void setSegments(ArrayList<SegmentData> segments) {
this.segments = segments;
}
public void setCaloriesIdle(String caloriesIdle) {
this.caloriesIdle = caloriesIdle;
}
public void setLastUpdate(String lastUpdate) {
this.lastUpdate = lastUpdate;
}
public static StorylineData parse(JSONObject jsonObject) {
if (jsonObject != null) {
StorylineData storylineData = new StorylineData();
storylineData.date = jsonObject.optString("date");
storylineData.caloriesIdle = jsonObject.optString("caloriesIdle");
storylineData.lastUpdate = jsonObject.optString("lastUpdate");
storylineData.summary = new ArrayList<SummaryData>();
storylineData.segments = new ArrayList<SegmentData>();
JSONArray summariesJsonArray= jsonObject.optJSONArray("summary");
if (summariesJsonArray != null) {
for (int i = 0; i < summariesJsonArray.length(); i++) {
JSONObject summaryJsonObject = summariesJsonArray.optJSONObject(i);
if (summaryJsonObject != null) {
storylineData.summary.add(SummaryData.parse(summaryJsonObject));
Log.d("storylineHandler", summaryJsonObject.toString());
}
}
}
JSONArray segmentsJsonArray = jsonObject.optJSONArray("segments");
if (segmentsJsonArray != null) {
for (int i = 0; i < segmentsJsonArray.length(); i++) {
JSONObject segment = segmentsJsonArray.optJSONObject(i);
if (segment != null) {
storylineData.segments.add(SegmentData.parse(segment));
Log.d("storylineHandler", segment.toString());
}
}
}
return storylineData;
}
return null;
}
}
The MainActivity looks like this:
MainActivity
public class MainActivity extends FragmentActivity implements OnClickListener{
..other variables here..
List<StorylineData> storylineData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...other ui elements here...
mEditTextResponse = (TextView) findViewById(R.id.editResponse);
storylineData = new StorylineData();
MovesAPI.init(this, CLIENT_ID, CLIENT_SECRET, CLIENT_SCOPES.....
#Override
public void onClick(View v) {
toggleProgress(true);
switch (mSpinnerAPI.getSelectedItemPosition()) {
... other cases here...
break;
...other cases here...
case 4: // Get Summary Day
MovesAPI.getSummary_SingleDay(summaryHandler, "20150418", null);//Date changed to "20150117"
break;
Other cases here..
case 10: // Get Storyline Day
MovesAPI.getStoryline_SingleDay(storylineHandler, "20150418", null, false);//Date changed to "20150418"
break;
...Other cases here..
}
}
... Other MovesHandlers here...
private JSONObject summaryJsonObject;
private List<StorylineData> storylineList;
private JSONObject summariesJsonArray;
private MovesHandler<ArrayList<StorylineData>> storylineHandler = new MovesHandler<ArrayList<StorylineData>>() {
#Override
public void onSuccess(ArrayList<StorylineData> result) {
toggleProgress(false);
storylineList = (List<StorylineData>) StorylineData.parse(summaryJsonObject);
updateResponse( + storylineData.toString() + "\n" //displays true to layout view
result.add(StorylineData.parse(summariesJsonArray))+ "\n"
+Log.d("call result", result.toString()) + "\n" //displays 60 in layout view & com.protogeo.moves.demos.apps.storyline.StorylineData#52824f88, null]
+ Log.d("Log.d storylineHandler", storylineHandler.toString()) + "\n" ); //returns 78 in layout view & com.protogeo.moves.demos.apps.Mainactivity#234234 to log cat
onFailure code here..
}
};
public void toggleProgress(final boolean isProgrressing) {
togglePregress code here..
}
public void updateResponse(final String message) {
runOnUiThread(new Runnable() {
public List<StorylineData> storylineList;
#Override
public void run() {
mEditTextResponse.setText(message);
if (storylineData!= null) {
for (StorylineData storylineData : storylineList) {
mEditTextResponse.append(("storylineData" + storylineData.toString()));
}
}
}
});
}
}
HttpClass
public static void getDailyStorylineList(final MovesHandler<JSONArray> handler,
final String specificSummary,
final String from,
final String to,
final String pastDays,
final String updatedSince,
final boolean needTrackPoints) {
new Thread(new Runnable() {
#Override
public void run() {
try {
/* Refresh access token if only AuthData.MOVES_REFRESHBEFORE days are there to expire current token */
AuthData.refreshAccessTokenIfNeeded();
/* Exchange the authorization code we obtained after login to get access token */
HashMap<String, String> nameValuePairs = new HashMap<String, String>();
nameValuePairs.put("access_token", AuthData.getAuthData().getAccessToken());
// if (specificSummary != null && specificSummary.length() > 0) nameValuePairs.put("specificSummary", specificSummary);//att
if (from != null && from.length() > 0) nameValuePairs.put("from", from);
if (to != null && to.length() > 0) nameValuePairs.put("to", to);
if (pastDays != null && pastDays.length() > 0) nameValuePairs.put("pastDays", pastDays);
if (updatedSince != null && updatedSince.length() > 0) nameValuePairs.put("updatedSince", updatedSince);
if (needTrackPoints) nameValuePairs.put("trackPoints", "true");
URL url = new URL(MovesAPI.API_BASE + MovesAPI.API_PATH_STORYLINE + (specificSummary != null ? specificSummary : "") + "?" + Utilities.encodeUrl(nameValuePairs));
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoInput(true);
urlConnection.connect();
if (urlConnection.getResponseCode() != 200) {
/* All other HTTP errors from Moves will fall here */
handler.onFailure(getErrorStatus(Utilities.readStream(urlConnection.getErrorStream()), urlConnection.getResponseCode()), "Server not responded with success ("+ urlConnection.getResponseCode() +")");
return;
}
String response = Utilities.readStream(urlConnection.getInputStream());
Object object = new JSONTokener(response).nextValue();
if (object instanceof JSONArray) {
JSONArray jsonArray = (JSONArray) object;
ArrayList<StorylineData> storylineData = new ArrayList<StorylineData>();
if (jsonArray != null) {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject storylineJsonObject = jsonArray.optJSONObject(i);
if (storylineJsonObject != null) {
storylineData.add(StorylineData.parse(storylineJsonObject));
}
}
}
handler.onSuccess(storylineData);
} else {
handler.onFailure(MovesStatus.INVALID_RESPONSE, "Expected a JSONArray from server, but failed");
}
} catch (Exception ex) {
ex.printStackTrace();
handler.onFailure(MovesStatus.UNEXPECTED_ERROR, "An unexpected error occured, please check logcat");
}
}
}).start();
}
MovesHandler
public interface MovesHandler<T> {//T stands for generic type
/**
* Implement this method to get success notifications along with the result
* #param result : Result of the operation completed with this handler
*/
public void onSuccess(ProfileData result);
/**
* Implement this method to get failure notifications along with the {#link MovesStatus} code and a brief message
* #param status : Status code of the failure
* #param message : A brief message about the reason behind failure
*/
public void onFailure(MovesStatus status, String message);
}
If you wanted to have one ArrayList to store both SummaryData and SegmentData, you could just created an ArrayList of Objects, ArrayList<Object>. This would be the more general solution.
The alternative would be having SummaryData and SegmentData inherit the same class or implement the same interface.
Using an extended class, you could have:
class Data {
}
class SegmentData extends Data {
}
class SummaryData extends Data {
}
You could then have an ArrayList that would be able to add both SegmentData and SummaryData objects.
If you wanted to show each item as a String you would need to loop through the list and call the toString() function of each item
ArrayList<Data> dataList;
for (Data d : dataList) {
Log.d("data", d.toString())
}
Just make sure to overwrite the toString() function in SegmentData and SummaryData
EDIT: Showing how to print JsonArray
If you wanted to just print for JsonArrays, you could:
public class StorylineData {
private static String date;
private JSONArray summary;
private JSONArray segments;
private String caloriesIdle;
private String lastUpdate;
public String getDate() {
return date;
}
public JSONArray getSummary() {
return summary;
}
public JSONArray getSegments() {
return segments;
}
public String getCaloriesIdle() {
return caloriesIdle;
}
public String getLastUpdate() {
return lastUpdate;
}
public void setDate(String date) {
this.date = date;
}
public void setSummary(JSONArray summary) {
this.summary = summary;
}
public void setSegments(JSONArray segments) {
this.segments = segments;
}
public void setCaloriesIdle(String caloriesIdle) {
this.caloriesIdle = caloriesIdle;
}
public void setLastUpdate(String lastUpdate) {
this.lastUpdate = lastUpdate;
}
public static StorylineData parse(JSONObject jsonObject) {
if (jsonObject != null) {
StorylineData storylineData = new StorylineData();
storylineData.date = jsonObject.optString("date");
storylineData.caloriesIdle = jsonObject.optString("caloriesIdle");
storylineData.lastUpdate = jsonObject.optString("lastUpdate");
storylineData.summary = jsonObject.optJSONArray("summary");
storylineData.segments = jsonObject.optJSONArray("segments");
return storylineData;
}
return null;
}
#Override
public String toString() {
JSONArray combined = new JSONArray(summary);
combined.put(segment);
return combined.toString();
}
}
In your MainActivity
private StorylineData storylineData;
private MovesHandler<JSONArray> storylineHandler = new MovesHandler<JSONArray>() {
#Override
public void onSuccess(JSONArray result) {
toggleProgress(false);
storylineData = StorylineData.parse(summaryJsonObject);
updateResponse(storylineData.toString()) //displays true to layout view
result.add(storylineData.getSummary());
Log.d("call result", result.toString());
Log.d("Log.d storylineHandler", storylineHandler.toString());
}
};

Java warning and error (read object)

My goal: save one ArrayList to a .dat file, after read this file and in the end print this array.
To save the ArrayList, "equipas" is one ArrayList< Equipa>, I use this function:
saveMyFile("Equipas.dat", (Object) equipas);
To read:
public static ArrayList<Equipa> readMyFile(String s){
ArrayList<Equipa> novo = new ArrayList<Equipa>();
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(s));
novo = (ArrayList<Equipa>) ois.readObject();
ois.close();
}
catch(IOException er) { System.out.println(er.getMessage()); }
catch(ClassNotFoundException er) { System.out.println(er.getMessage()); }
return novo;}
In this read function, I have one Compilation Warning: "…uses unchecked or unsafe operations. Recompile with - Xlint:unchecked for details."
To save:
public static void saveMyFile(String s, Object o)
{
try {
ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(s));
oos.writeObject(o);
oos.flush();
oos.close();
}
catch(IOException e) { System.out.println(e.getMessage()); }
}
Finally, I want to print the ArrayList's info:
ArrayList<Equipa> cena = new ArrayList<Equipa>();
cena=(ArrayList<Equipa>) readMyFile("Equipas.dat");
for(Equipa e:cena)
e.toString();
Error when I try to run:
" writing aborted; java.io.NotSerializableException: Equipa"
Equipa havs the Serializable:
import java.util.*;
import java.io.*;
public class Equipa implements Serializable
{
private String nome;
private Carro carro;
private ArrayList<Piloto> pilotos;
private double tempoDecorrido;
private int pontos;
private boolean desistiu;
private int voltaDesistencia;
private Piloto piloto;
/**
* Constructor for objects of class Equipa
*/
public Equipa()
{
this.nome = "NA";
this.carro = null;
this.pilotos = new ArrayList<Piloto>();
this.tempoDecorrido = 0;
this.pontos = 0;
this.desistiu = false;
this.voltaDesistencia = 0;
this.piloto = null;
}
public Equipa(String nome, Carro carro, ArrayList<Piloto> pilotos)
{
this.nome = nome;
this.carro = carro;
//this.pilotos = new ArrayList<Piloto>(pilotos);
this.pilotos = pilotos;
this.tempoDecorrido = 0;
this.pontos = 0;
this.desistiu = false;
this.voltaDesistencia = 0;
//this.piloto = pilotos.get(0);
}
public Equipa (Equipa e)
{
this.nome = e.getNome();
this.carro = e.getCarro();
this.pilotos = e.getPilotos();
this.tempoDecorrido = e.getTempoDecorrido();
this.pontos = e.getPontos();
this.desistiu = e.getDesistiu();
this.voltaDesistencia = e.getVoltaDesistencia();
//this.piloto = e.getPiloto();
}
/** Getters */
public String getNome()
{
return this.nome;
}
public Carro getCarro()
{
return this.carro;
}
public ArrayList<Piloto> getPilotos()
{
return new ArrayList<Piloto>(this.pilotos);
}
public double getTempoDecorrido()
{
return this.tempoDecorrido;
}
public int getPontos()
{
return this.pontos;
}
public boolean getDesistiu()
{
return this.desistiu;
}
public int getVoltaDesistencia()
{
return this.voltaDesistencia;
}
public Piloto getPiloto()
{
return this.piloto;
}
/** Setters */
public void setNome(String nome)
{
this.nome = nome;
}
public void setCarro(Carro carro)
{
this.carro = carro;
}
public void setPilotos(ArrayList<Piloto> pilotos)
{
this.pilotos = new ArrayList<Piloto>(pilotos);
}
public void setTempoDecorrido(double tempoDecorrido)
{
this.tempoDecorrido = tempoDecorrido;
}
public void setPontos(int pontos)
{
this.pontos = pontos;
}
public void setDesistiu(boolean desistiu)
{
this.desistiu = desistiu;
}
public void setVoltaDesistencia(int voltaDesistencia)
{
this.voltaDesistencia = voltaDesistencia;
}
public void setPiloto(Piloto piloto)
{
this.piloto = piloto;
}
/** Outros Métodos */
public Equipa clone()
{
return new Equipa(this);
}
public boolean equals(Equipa e)
{
if(this.nome == e.getNome())
return true;
else
return false;
}
public String getStringPilotos()
{
String s = new String();
for(Piloto p: this.pilotos)
s = (s + ", " + p.getNome());
return s;
}
public String toString()
{
return new String("Nome da equipa: " + nome + "; Categoria do carro: " + carro.getClass().getName() + "; Marca e modelo: " + carro.getMarca() + " " + carro.getModelo() + "; Pilotos: " + getStringPilotos())+"\n";
}
Implementing Serializable means that serialization is permitted, but not necessarily that it is possible. For it to work, everything referenced by Equipa must also be either primitive or Serializable (and so on, recursively). Is this the case?
Warning in the read function is the result of generics in java. You won't be able to suppress it, unless you use #SuppressWarnings("unchecked") to ignore it.
If you are sure you are reading an ArrayList<Equipa>, you can ignore it without any problem.
With the Equipa code, I can try to point to the Serializable problem: make sure that Carro and Piloto classes are also Serializables. You can add the code of theses classes if you are not sure.
The only type-safer way would be do a custom serialization, using writeObject(OutputStream) and readObjectInputStream say on a class ArrayListOfEquipa maybe using Equipa[] (ArrayList.toArray()).
Not really attractive, if the warning would be the only reason.

Categories