this is my first question here. do not judge strictly:) I'm parsing a file with the dim extension of the xml format, in fact, so I chose SAXparser. the problem is probably architectural or I don’t know how to call it correctly. in general, if you describe: there is a list of tags that I need to pull out and, in accordance with them, create objects, assign values to their fields, which the parser will pull out as strings from certain tags. in accordance with the tags I need, I have implemented classes with which I need to create objects in the startElement method, after that in endElement I need to assign the appropriate strings to this object. The crux of the problem is that I can't figure out how I can avoid a lot of code in the SaxParserHandler class, including a lot of if/else in the startElement and endElement methods. tried to use enum and factory pattern, but all in vain. example of my current code in SaxParserHandler:
public class SaxParserHandler extends DefaultHandler {
private Dataset_Id dataset_id = null;
private StringBuilder data = null;
private Dataset_Frame dataset_frame = null;
private String MetadataId = "Metadata_Id";
private String dataset_name_tag = "DATASET_NAME";
private String dataset_frame_tag = "Dataset_Frame";
private Vertex vertex = null;
private List<Vertex> vertices = null;
private String vertex_tag = "Vertex";
private String FRAME_LON = "FRAME_LON";
private String FRAME_LAT = "FRAME_LAT";
private String FRAME_X = "FRAME_X";
private String FRAME_Y = "FRAME_Y";
private String FRAME_ROW = "FRAME_ROW";
private String FRAME_COL = "FRAME_COL";
private Source_Information source_information = null;
private Scene_Source scene_source = null;
private String source_info_tag = "Source_Information";
private String source_id_tag = "SOURCE_ID";
private String scene_source_tag = "Scene_Source";
private String imaging_date_tag = "IMAGING_DATE";
private String imaging_time_tag = "IMAGING_TIME";
private String mission_tag = "MISSION";
private String mission_index_tag = "MISSION_INDEX";
private String instrument_tag = "INSTRUMENT";
private String satellite_incidence_angle_tag = "SATELLITE_INCIDENCE_ANGLE";
private String viewing_angle_tag = "VIEWING_ANGLE";
private String sun_azimuth_tag = "SUN_AZIMUTH";
private String sun_elevation_tag = "SUN_ELEVATION";
private String theoretical_resolution_tag = "THEORETICAL_RESOLUTION";
private Coordinate_Reference_System coordinate_reference_system = null;
private Horizontal_CS horizontal_cs = null;
private String Coordinate_Reference_System_Tag = "Coordinate_Reference_System";
private String Horizontal_CS_Tag = "Horizontal_CS";
private String HORIZONTAL_CS_CODE_TAG = "HORIZONTAL_CS_CODE";
private String HORIZONTAL_CS_TYPE_TAG = "HORIZONTAL_CS_TYPE";
private String HORIZONTAL_CS_NAME_TAG = "HORIZONTAL_CS_NAME";
private Production production = null;
private Production_Facility production_facility = null;
private String Production_Tag = "Production";
private String DATASET_PRODUCTION_DATE_TAG = "DATASET_PRODUCTION_DATE";
private String PRODUCT_TYPE_TAG = "PRODUCT_TYPE";
private String PRODUCT_INFO_TAG = "PRODUCT_INFO";
private String JOB_ID_TAG = "JOB_ID";
private String Production_Facility_Tag = "Production_Facility";
private String SOFTWARE_NAME_TAG = "SOFTWARE_NAME";
private String SOFTWARE_VERSION_TAG = "SOFTWARE_VERSION";
private String PROCESSING_CENTER_TAG = "PROCESSING_CENTER";
private Raster_Encoding raster_encoding = null;
private String Raster_Encoding_Tag = "Raster_Encoding";
private String DATA_TYPE_TAG = "DATA_TYPE";
private String NBITS_TAG = "NBITS";
private String BYTEORDER_TAG = "BYTEORDER";
private String BANDS_LAYOUT_TAG = "BANDS_LAYOUT";
private Data_Processing data_processing = null;
private String Data_Processing_Tag = "Data_Processing";
private String PROCESSING_LEVEL_TAG = "PROCESSING_LEVEL";
private String GEOMETRIC_PROCESSING_TAG = "GEOMETRIC_PROCESSING";
private String RADIOMETRIC_PROCESSING_TAG = "RADIOMETRIC_PROCESSING";
private Data_Access data_access = null;
private Data_File_List data_file_list = null;
private String Data_Access_Tag = "Data_Access";
private String DATA_FILE_FORMAT_TAG = "DATA_FILE_FORMAT";
private String DATA_FILE_ORGANISATION_TAG = "DATA_FILE_ORGANISATION";
private String Data_File_List_Tag = "Data_File_List";
private String DATA_FILE_PATH_TAG = "DATA_FILE_PATH";
private Image_Display image_display = null;
private Band_Display_Order band_display_order = null;
private String Image_Display_Tag = "Image_Display";
private String Band_Display_Order_Tag = "Band_Display_Order";
private String RED_CHANNEL_TAG = "RED_CHANNEL";
private String GREEN_CHANNEL_TAG = "GREEN_CHANNEL";
private String BLUE_CHANNEL_TAG = "BLUE_CHANNEL";
private Data_Strip data_strip = null;
private Data_Strip_Identification data_strip_identification = null;
private Time_Stamp time_stamp = null;
private Ephemeris ephemeris = null;
private String Data_Strip_Tag = "Data_Strip";
private String Data_Strip_Identification_Tag = "Data_Strip_Identification";
private String DATA_STRIP_ID_TAG = "DATA_STRIP_ID";
private String SEGMENT_ID_TAG = "SEGMENT_ID";
private String Time_Stamp_Tag = "Time_Stamp";
private String REFERENCE_BAND_TAG = "REFERENCE_BAND";
private String REFERENCE_TIME_TAG = "REFERENCE_TIME";
private String REFERENCE_LINE_TAG = "REFERENCE_LINE";
private String LINE_PERIOD_TAG = "LINE_PERIOD";
private String Ephemeris_Tag = "Ephemeris";
private String SATELLITE_ALTITUDE_TAG = "SATELLITE_ALTITUDE";
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase(dataset_name_tag))
dataset_id = new Dataset_Id();
else if (qName.equalsIgnoreCase(dataset_frame_tag)) {
dataset_frame = new Dataset_Frame();
} else if (qName.equals(vertex_tag)) {
vertex = new Vertex();
if (vertices == null)
vertices = new ArrayList<>();
} else if (qName.equalsIgnoreCase(source_info_tag)) {
source_information = new Source_Information();
} else if (qName.equals(scene_source_tag)) {
scene_source = new Scene_Source();
} else if (qName.equals(Coordinate_Reference_System_Tag)) {
coordinate_reference_system = new Coordinate_Reference_System();
} else if (qName.equals(Horizontal_CS_Tag)) {
horizontal_cs = new Horizontal_CS();
} else if (qName.equals(Production_Tag)) {
production = new Production();
} else if (qName.equals(Production_Facility_Tag)) {
production_facility = new Production_Facility();
} else if (qName.equals(Raster_Encoding_Tag)) {
raster_encoding = new Raster_Encoding();
} else if (qName.equals(Data_Processing_Tag)) {
data_processing = new Data_Processing();
} else if (qName.equals(Data_Access_Tag)) {
data_access = new Data_Access();
} else if (qName.equals(Data_File_List_Tag)) {
data_file_list = new Data_File_List();
}else if (qName.equals(Image_Display_Tag)) {
image_display = new Image_Display();
}else if (qName.equals(Band_Display_Order_Tag)) {
band_display_order = new Band_Display_Order();
}else if (qName.equals(Data_Strip_Tag)){
data_strip = new Data_Strip();
}else if (qName.equals(Data_Strip_Identification_Tag)) {
data_strip_identification = new Data_Strip_Identification();
}else if (qName.equals(Time_Stamp_Tag)) {
time_stamp = new Time_Stamp();
}else if (qName.equals(Ephemeris_Tag)) {
ephemeris = new Ephemeris();
}
data = new StringBuilder();
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals(dataset_name_tag)) {
dataset_id.setDataset_name(data.toString());
} else if (qName.equals(FRAME_LON)) {
vertex.setFRAME_LON(data.toString());
} else if (qName.equals(FRAME_LAT)) {
vertex.setFRAME_LAT(data.toString());
} else if (qName.equals(FRAME_X)) {
vertex.setFRAME_X(data.toString());
} else if (qName.equals(FRAME_Y)) {
vertex.setFRAME_Y(data.toString());
} else if (qName.equals(FRAME_ROW)) {
vertex.setFRAME_ROW(data.toString());
} else if (qName.equals(FRAME_COL)) {
vertex.setFRAME_COL(data.toString());
} else if (qName.equals(vertex_tag)) {
vertices.add(vertex);
} else if (qName.equals(dataset_frame_tag)) {
dataset_frame.setDataset_Frame(vertices);
} else if (qName.equals(source_id_tag)) {
source_information.setSource_id(data.toString());
} else if (qName.equals(imaging_date_tag)) {
scene_source.setIMAGING_DATE(data.toString());
} else if (qName.equals(imaging_time_tag)) {
scene_source.setIMAGING_TIME(data.toString());
} else if (qName.equals(mission_tag)) {
scene_source.setMISSION(data.toString());
} else if (qName.equals(mission_index_tag)) {
scene_source.setMISSION_INDEX(data.toString());
} else if (qName.equals(instrument_tag)) {
scene_source.setINSTRUMENT(data.toString());
} else if (qName.equals(satellite_incidence_angle_tag)) {
scene_source.setSATELLITE_INCIDENCE_ANGLE(data.toString());
} else if (qName.equals(viewing_angle_tag)) {
scene_source.setVIEWING_ANGLE(data.toString());
} else if (qName.equals(sun_azimuth_tag)) {
scene_source.setSUN_AZIMUTH(data.toString());
} else if (qName.equals(sun_elevation_tag)) {
scene_source.setSUN_ELEVATION(data.toString());
} else if (qName.equals(theoretical_resolution_tag)) {
scene_source.setTHEORETICAL_RESOLUTION(data.toString());
} else if (qName.equals(source_info_tag)) {
source_information.setScene_source(scene_source);
} else if (qName.equals(HORIZONTAL_CS_TYPE_TAG)) {
horizontal_cs.setHORIZONTAL_CS_TYPE(data.toString());
} else if (qName.equals(HORIZONTAL_CS_NAME_TAG)) {
horizontal_cs.setHORIZONTAL_CS_NAME(data.toString());
} else if (qName.equals(HORIZONTAL_CS_CODE_TAG)) {
horizontal_cs.setHORIZONTAL_CS_CODE(data.toString());
} else if (qName.equals(Horizontal_CS_Tag)) {
coordinate_reference_system.setHorizontal_cs(horizontal_cs);
} else if (qName.equals(DATASET_PRODUCTION_DATE_TAG)) {
production.setDATASET_PRODUCTION_DATE(data.toString());
} else if (qName.equals(PRODUCT_TYPE_TAG)) {
production.setPRODUCT_TYPE(data.toString());
} else if (qName.equals(PRODUCT_INFO_TAG)) {
production.setPRODUCT_INFO(data.toString());
} else if (qName.equals(JOB_ID_TAG)) {
production.setJOB_ID(data.toString());
} else if (qName.equals(SOFTWARE_NAME_TAG)) {
production_facility.setSOFTWARE_NAME(data.toString());
} else if (qName.equals(SOFTWARE_VERSION_TAG)) {
production_facility.setSOFTWARE_VERSION(data.toString());
} else if (qName.equals(PROCESSING_CENTER_TAG)) {
production_facility.setPROCESSING_CENTER(data.toString());
} else if (qName.equals(Production_Tag)) {
production.setProduction_facility(production_facility);
} else if (qName.equals(DATA_TYPE_TAG)) {
raster_encoding.setDATA_TYPE(data.toString());
} else if (qName.equals(NBITS_TAG)) {
raster_encoding.setNBITS(data.toString());
} else if (qName.equals(BYTEORDER_TAG)) {
raster_encoding.setBYTEORDER(data.toString());
} else if (qName.equals(BANDS_LAYOUT_TAG)) {
raster_encoding.setBANDS_LAYOUT(data.toString());
} else if (qName.equals(PROCESSING_LEVEL_TAG)) {
data_processing.setPROCESSING_LEVEL(data.toString());
} else if (qName.equals(GEOMETRIC_PROCESSING_TAG)) {
data_processing.setGEOMETRIC_PROCESSING(data.toString());
} else if (qName.equals(RADIOMETRIC_PROCESSING_TAG)) {
data_processing.setRADIOMETRIC_PROCESSING(data.toString());
} else if (qName.equals(DATA_FILE_FORMAT_TAG)) {
data_access.setDATA_FILE_FORMAT(data.toString());
} else if (qName.equals(DATA_FILE_ORGANISATION_TAG)) {
data_access.setDATA_FILE_ORGANISATION(data.toString());
} else if (qName.equals(DATA_FILE_PATH_TAG)) {
data_file_list.setDATA_FILE_PATH(data.toString());
} else if (qName.equals(Data_File_List_Tag)) {
data_access.setData_file_lists(data_file_list);
}else if (qName.equals(RED_CHANNEL_TAG)) {
band_display_order.setRED_CHANNEL(data.toString());
}else if (qName.equals(GREEN_CHANNEL_TAG)) {
band_display_order.setGREEN_CHANNEL(data.toString());
}else if (qName.equals(BLUE_CHANNEL_TAG)) {
band_display_order.setBLUE_CHANNEL(data.toString());
}else if (qName.equals(Band_Display_Order_Tag)) {
image_display.setBand_display_orders(band_display_order);
}else if (qName.equals(DATA_STRIP_ID_TAG)){
data_strip_identification.setDATA_STRIP_ID(data.toString());
}else if (qName.equals(SEGMENT_ID_TAG)) {
data_strip_identification.setSEGMENT_ID(data.toString());
}else if (qName.equals(Data_Strip_Identification_Tag)) {
data_strip.setData_strip_identification(data_strip_identification);
}else if (qName.equals(REFERENCE_BAND_TAG)) {
time_stamp.setREFERENCE_BAND(data.toString());
}else if (qName.equals(REFERENCE_TIME_TAG)){
time_stamp.setREFERENCE_TIME(data.toString());
}else if (qName.equals(REFERENCE_LINE_TAG)) {
time_stamp.setREFERENCE_LINE(data.toString());
}else if (qName.equals(LINE_PERIOD_TAG)) {
time_stamp.setLINE_PERIOD(data.toString());
}else if (qName.equals(Time_Stamp_Tag)) {
data_strip.setTime_stamp(time_stamp);
}else if (qName.equals(SATELLITE_ALTITUDE_TAG)) {
ephemeris.setSATELLITE_ALTITUDE(data.toString());
}else if (qName.equals(Ephemeris_Tag)) {
data_strip.setEphemerises(ephemeris);
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
data.append(new String(ch, start, length));
}
Root root = new Root();
public Root getRoot() {
root.setDataset_id(dataset_id);
root.setDataset_frame(dataset_frame);
root.setSource_information(source_information);
root.setCoordinate_reference_systems(coordinate_reference_system);
root.setProductions(production);
root.setRaster_encodings(raster_encoding);
root.setData_processings(data_processing);
root.setData_accesses(data_access);
root.setImage_displays(image_display);
root.setData_strips(data_strip);
return root;
}
}
part of dim file sample
<?xml version="1.0" encoding="ISO-8859-1"?>
<Dimap_Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Metadata_Id>
<METADATA_FORMAT version="1.1">DIMAP</METADATA_FORMAT>
</Metadata_Id>
<Dataset_Id>
<DATASET_NAME>KM000604MI_017_MUL_L1G</DATASET_NAME>
<DATASET_TN_PATH href="KM000604MI_017_MUL_L1G_tn.jpg"/>
<DATASET_QL_PATH href="KM000604MI_017_MUL_L1G_ql.jpg"/>
</Dataset_Id>
<Production>
<DATASET_PRODUCER_NAME/>
<DATASET_PRODUCTION_DATE>2015-09-28</DATASET_PRODUCTION_DATE>
<PRODUCT_TYPE/>
</Production>
<Dataset_Use>
<DATASET_CONTENT/>
</Dataset_Use>
<Data_Processing>
<GEOMETRIC_PROCESSING/>
<Processing_Parameter>
<PROC_PARAMETER_DESC>SOFTWARE</PROC_PARAMETER_DESC>
<PROC_PARAMETER_VALUE>Keystone 3.8.9.FINAL.</PROC_PARAMETER_VALUE>
</Processing_Parameter>
</Data_Processing>
<Coordinate_Reference_System>
<GEO_TABLES>EPSG</GEO_TABLES>
<Horizontal_CS>
<HORIZONTAL_CS_CODE>EPSG:32642</HORIZONTAL_CS_CODE>
<HORIZONTAL_CS_TYPE>PROJECTED</HORIZONTAL_CS_TYPE>
<HORIZONTAL_CS_NAME>WGS 84 / UTM zone 42N</HORIZONTAL_CS_NAME>
<Coordinate_Axis>
<AXIS1_NAME>Easting</AXIS1_NAME>
<AXIS2_NAME>Northing</AXIS2_NAME>
<AXIS1_ORIENTATION>EAST</AXIS1_ORIENTATION>
<AXIS2_ORIENTATION>NORTH</AXIS2_ORIENTATION>
</Coordinate_Axis>
<Projection>
<PROJECTION_NAME>UTM zone 42N</PROJECTION_NAME>
<PROJECTION_CODE>EPSG:16042</PROJECTION_CODE>
<Projection_CT_Method>
<PROJECTION_CT_NAME>Transverse Mercator</PROJECTION_CT_NAME>
<PROJECTION_CT_CODE>EPSG:9807</PROJECTION_CT_CODE>
<Projection_Parameters>
<Projection_Parameter>
<PROJECTION_PARAMETER_NAME>Latitude_of_natural_origin</PROJECTION_PARAMETER_NAME>
<PROJECTION_PARAMETER_VALUE unit="DEG">0.0</PROJECTION_PARAMETER_VALUE>
</Projection_Parameter>
<Projection_Parameter>
<PROJECTION_PARAMETER_NAME>Longitude_of_natural_origin</PROJECTION_PARAMETER_NAME>
<PROJECTION_PARAMETER_VALUE unit="DEG">69.0</PROJECTION_PARAMETER_VALUE>
</Projection_Parameter>
<Projection_Parameter>
<PROJECTION_PARAMETER_NAME>Scale_factor_at_natural_origin</PROJECTION_PARAMETER_NAME>
<PROJECTION_PARAMETER_VALUE>0.9996</PROJECTION_PARAMETER_VALUE>
</Projection_Parameter>
<Projection_Parameter>
<PROJECTION_PARAMETER_NAME>False_easting</PROJECTION_PARAMETER_NAME>
<PROJECTION_PARAMETER_VALUE unit="M">500000.0</PROJECTION_PARAMETER_VALUE>
</Projection_Parameter>
<Projection_Parameter>
<PROJECTION_PARAMETER_NAME>False_northing</PROJECTION_PARAMETER_NAME>
<PROJECTION_PARAMETER_VALUE unit="M">0.0</PROJECTION_PARAMETER_VALUE>
</Projection_Parameter>
</Projection_Parameters>
</Projection_CT_Method>
</Projection>
<Geographic_CS>
<GEOGRAPHIC_CS_NAME>WGS 84</GEOGRAPHIC_CS_NAME>
<GEOGRAPHIC_CS_CODE>EPSG:4326</GEOGRAPHIC_CS_CODE>
<Horizontal_Datum>
<HORIZONTAL_DATUM_NAME>World Geodetic System 1984</HORIZONTAL_DATUM_NAME>
<HORIZONTAL_DATUM_CODE>EPSG:6326</HORIZONTAL_DATUM_CODE>
<Ellipsoid>
<ELLIPSOID_NAME>WGS 84</ELLIPSOID_NAME>
<ELLIPSOID_CODE>EPSG:7030</ELLIPSOID_CODE>
<Ellipsoid_Parameters>
<ELLIPSOID_MAJOR_AXIS unit="M">6378137.0</ELLIPSOID_MAJOR_AXIS>
<ELLIPSOID_MINOR_AXIS unit="M">6356752.314245</ELLIPSOID_MINOR_AXIS>
</Ellipsoid_Parameters>
</Ellipsoid>
<Prime_Meridian>
<PRIME_MERIDIAN_NAME>Greenwich</PRIME_MERIDIAN_NAME>
<PRIME_MERIDIAN_CODE>EPSG:8901</PRIME_MERIDIAN_CODE>
<PRIME_MERIDIAN_OFFSET unit="DEG">0.0</PRIME_MERIDIAN_OFFSET>
</Prime_Meridian>
</Horizontal_Datum>
</Geographic_CS>
</Horizontal_CS>
</Coordinate_Reference_System>
If you are open to use third party libraries, you might give Jsoup a try. Jsoup is actually a HTML-parser but is also able to parse XML. It provides IMHO an intuitive and simple selector syntax and API which you can use to get the elements you are interested in.
I am not realy sure what you are trying to achieve and didn't find all the tags from your code in the sample xml you provided. But to give you a simple starting point on how to use Jsoup, please see below snippet where I fetch the
Production DATASET_PRODUCTION_DATE and the Projection_Parameters from the sample xml:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.parser.Parser;
import org.jsoup.select.Elements;
public class Example2 {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(new File("path to your xml file"));
Document doc = Jsoup.parse(in, "UTF-8", "", Parser.xmlParser());
String productionDate = doc.selectFirst("Production DATASET_PRODUCTION_DATE").text();
System.out.println("PRODUCTION_DATE: " + productionDate);
Elements projection_Parameters = doc.select("Projection_Parameter");
projection_Parameters.forEach(param -> {
String name = param.selectFirst("PROJECTION_PARAMETER_NAME").text();
String value = param.selectFirst("PROJECTION_PARAMETER_VALUE").text();
System.out.printf("NAME: %s, VALUE: %s %n", name, value);
});
}
}
output:
PRODUCTION_DATE: 2015-09-28
NAME: Latitude_of_natural_origin, VALUE: 0.0
NAME: Longitude_of_natural_origin, VALUE: 69.0
NAME: Scale_factor_at_natural_origin, VALUE: 0.9996
NAME: False_easting, VALUE: 500000.0
NAME: False_northing, VALUE: 0.0
Instead of printing to console you could of course create directly your POJOs. If interested get Jsoup from Maven central
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>
Related
I am trying to save a txt file into the Downloads folder in my first abndroid app.
public class DisplaySettingsActivity extends AppCompatActivity implements View.OnClickListener {
private H300sVoipSettings settings;
Button saveIntoFile;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_settings);
this.settings = (H300sVoipSettings) getIntent().getSerializableExtra("H300sVoipSettings");
this.saveIntoFile = (Button)findViewById(R.id.save);
this.saveIntoFile.setOnClickListener(this);
}
private String saveFile(){
Log.d("Η300s","Saving");
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)) {
Log.e("H300s","Unable to detect external storage");
return null;
}
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyMMdd");
File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
file = new File( file.getAbsolutePath(),"voip_h300s_"+pattern.format(LocalDate.now())+".txt");
Log.d("H300s",file.toString());
try {
Log.d("H300s","Saving");
this.settings.save(file);
Log.d("H300s","Saved");
Log.d("H300s",file.getAbsolutePath());
return file.getAbsolutePath();
} catch (Exception e) {
Log.e("H300s",e.toString());
Log.e("H300s",Log.getStackTraceString(e));
return null;
}
}
}
But this piece of code in my function:
this.settings.save(file);
Fails to be saved due to lack of permissions. As the following log shows:
2021-04-24 14:48:18.498 8208-8208/com.example.vodafone_fu_h300s E/H300s: java.io.IOException: Permission denied
2021-04-24 14:48:18.499 8208-8208/com.example.vodafone_fu_h300s E/H300s: java.io.IOException: Permission denied
at java.io.UnixFileSystem.createFileExclusively0(Native Method)
at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:281)
at java.io.File.createNewFile(File.java:1008)
at pc_magas.vodafone_fu_h300s.screens.DisplaySettingsActivity.saveFile(DisplaySettingsActivity.java:97)
at pc_magas.vodafone_fu_h300s.screens.DisplaySettingsActivity.onClick(DisplaySettingsActivity.java:120)
at android.view.View.performClick(View.java:6597)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25906)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
What I want to do is to save a txt file into Downloads Folder and make it accessible to the user via file manager. The class H300sVoipSettings has the following:
public class H300sVoipSettings implements Serializable
{
private String username = null;
private String password = null;
private String primary_registar = null;
private String primary_registar_port = null;
private String secondary_registar = null;
private String secondary_registar_port = null;
private String primary_proxy = null;
private String primary_proxy_port = null;
private String secondary_proxy = null;
private String secondary_proxy_port = null;
private String sip_domain = null;
private String sip_number = null;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPrimary_registar() {
return primary_registar;
}
public void setPrimary_registar(String primary_registar) {
this.primary_registar = primary_registar;
}
public String getPrimary_registar_port() {
return primary_registar_port;
}
public void setPrimary_registar_port(String primary_registar_port) {
this.primary_registar_port = primary_registar_port;
}
public String getSecondary_registar() {
if(secondary_registar == null || secondary_registar.trim().equals("")){
return null;
}
return secondary_registar;
}
public void setSecondary_registar(String secondary_registar) {
this.secondary_registar = secondary_registar;
}
public String getSecondary_registar_port() {
return secondary_registar_port;
}
public void setSecondary_registar_port(String secondary_registar_port) {
this.secondary_registar_port = secondary_registar_port;
}
public String getPrimary_proxy() {
return primary_proxy;
}
public void setPrimary_proxy(String primary_proxy) {
this.primary_proxy = primary_proxy;
}
public String getPrimary_proxy_port() {
return primary_proxy_port;
}
public void setPrimary_proxy_port(String primary_proxy_port) {
this.primary_proxy_port = primary_proxy_port;
}
public String getSecondary_proxy() {
return secondary_proxy;
}
public void setSecondary_proxy(String secondary_proxy) {
this.secondary_proxy = secondary_proxy;
}
public String getSecondary_proxy_port() {
return secondary_proxy_port;
}
public void setSecondary_proxy_port(String secondary_proxy_port) {
this.secondary_proxy_port = secondary_proxy_port;
}
public String getSip_domain() {
return sip_domain;
}
public void setSip_domain(String sip_domain) {
this.sip_domain = sip_domain;
}
public String getSip_number() {
return sip_number;
}
public void setSip_number(String sip_number) {
this.sip_number = sip_number;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public static H300sVoipSettings createFromJson(String jsonString) throws IllegalArgumentException, JSONException {
if(jsonString == null || jsonString.trim().equals("")){
throw new IllegalArgumentException("JsonString Should not be empty");
}
JSONArray settingsJson = new JSONArray(jsonString);
H300sVoipSettings settings = new H300sVoipSettings();
for (int i = 0; i < settingsJson.length(); i++) {
JSONObject item = settingsJson.getJSONObject(i);
if(item.getString("type").equals("provider")){
settings.setPrimary_registar(item.getString("primary_registrar"));
settings.setPrimary_registar_port(item.getString("primary_registrar_port"));
settings.setPrimary_proxy(item.getString("primary_proxy"));
settings.setPrimary_proxy_port(item.getString("primary_proxy_port"));
settings.setSip_domain(item.getString("sip_domain"));
String secondary_proxy = item.getString("secondary_proxy");
if(secondary_proxy != null && !secondary_proxy.trim().equals("")){
settings.setSecondary_proxy(secondary_proxy.trim());
}
settings.setSecondary_proxy_port(item.getString("secondary_proxy_port"));
settings.setSecondary_registar(item.getString("secondary_registrar"));
settings.setSecondary_registar_port(item.getString("secondary_registrar_port"));
} else if(item.getString("type").equals("number")){
settings.setSip_number(item.getString("sip_number"));
settings.setUsername(item.getString("username"));
settings.setPassword(item.getString("password"));
}
}
return settings;
}
public boolean equals(H300sVoipSettings other){
boolean truth = other.getPassword().equals(this.getPassword()) &&
other.getUsername().equals(this.getUsername()) &&
other.getSip_number().equals(this.getSip_number()) &&
other.getSip_domain().equals(this.getSip_domain()) &&
other.getPrimary_proxy().equals(this.getPrimary_proxy()) &&
other.getPrimary_proxy_port().equals(this.getPrimary_proxy_port()) &&
other.getPrimary_registar().equals(this.getPrimary_registar()) &&
other.getPrimary_registar_port().equals(this.getPrimary_registar_port()) &&
other.getSecondary_proxy_port().equals(this.getSecondary_proxy_port()) &&
other.getSecondary_registar_port().equals(this.getSecondary_registar_port());
truth = truth && ((other.getSecondary_proxy() == null && this.getSecondary_proxy() == null) || (other.getSecondary_proxy().equals(this.getSecondary_proxy())));
truth = truth &&
(
(other.getSecondary_registar() == null && this.getSecondary_registar() == null) ||
(
other.getSecondary_registar().equals(this.getSecondary_registar())
)
);
return truth;
}
public String toString()
{
StringBuilder txt = new StringBuilder();
txt.append("Phone Number: ");
txt.append(this.getSip_number());
txt.append("\n");
txt.append("Username: ");
txt.append(this.getUsername());
txt.append("\n");
txt.append("Password: ");
txt.append(this.getPassword());
txt.append("\n");
txt.append("Sip Domain: ");
txt.append(this.getSip_domain());
txt.append("\n");
txt.append("Primary proxy: ");
txt.append(this.getPrimary_proxy());
txt.append(" Port: ");
txt.append(this.getPrimary_proxy_port());
txt.append("\n");
txt.append("Secondary proxy: ");
String secondary_proxy = this.getSecondary_proxy();
secondary_proxy = (secondary_proxy == null || !secondary_proxy.trim().equals(""))?"N/A":secondary_proxy;
txt.append(secondary_proxy);
txt.append(" Port: ");
String secondaryProxyPort = this.getSecondary_proxy_port();
secondaryProxyPort=(secondaryProxyPort == null || !secondaryProxyPort.trim().equals(""))?"N/A":secondaryProxyPort;
txt.append(secondaryProxyPort);
txt.append("\n");
txt.append("Primary Registar: ");
String primaryRegistar = this.getPrimary_registar();
txt.append(primaryRegistar);
txt.append(" Port: ");
String primaryRegistarPort = this.getPrimary_registar_port();
txt.append(primaryRegistarPort);
txt.append("\n");
txt.append("Secondary Registar: ");
String secondary_registar = this.getSecondary_registar();
secondary_registar = (secondary_registar == null || !secondary_registar.trim().equals(""))?"N/A":secondary_registar;
txt.append(secondary_registar);
txt.append(" Port: ");
String secondaryRegistarPort = this.getSecondary_registar();
secondaryRegistarPort=(secondaryRegistarPort == null || !secondaryRegistarPort.trim().equals(""))?"N/A":secondaryRegistarPort;
txt.append(secondaryRegistarPort);
txt.append("\n");
return txt.toString();
}
public void save(File file) throws IOException {
PrintWriter out = new PrintWriter(new FileWriter(file));
out.println("********");
out.print("Exported Date: ");
out.println(new Date().toString());
out.println("********");
out.print(this.toString());
out.close();
}
}
And is used for data serialization. The application has the following in Android Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Furthermore I have looked upon these answers whith no result whatsoever:
https://stackoverflow.com/a/62748149/4706711
So do you have any idea how I can access the donwloads folder?
Despite having the permissions:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
You should also prompt the user to accept these requests as well. In order to achieve this the onCLick function should be:
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.d("H300s","Permission Accepted");
saveFile();
} else {
requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE );
}
}
Where the requestPermissionLauncher is initialized into the onCreate like this:
requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
Log.d("H300s","Permissions Callback");
if (isGranted) {
Log.d("H300s","Permission Accepted 2");
saveFile();
} else {
permissionSaveDenied();
}
});
Furthermore, ensure that at build.gradle you should place the following:
implementation 'androidx.activity:activity-ktx:1.2.0'
implementation 'androidx.fragment:fragment:1.3.0'
In order for the ActivityResultContracts to work.
Bonus Tip
You can skip declaring the need for this permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Because application gonna request the user to provide it nevertheless.
I have a workbook with two sheets:
Sheet1
Sheet2
And there is a sequence on Sheet2 at the range of A1 to A5:
aa
bb
cc
dd
ee
And in Sheet1, the cell A1 is validated by the sequence in Sheet2.
Excel screenshot
However, sheet.getDataValidations() returns an empty list for this case.
Did I miss something?
public static void main(String[] args) throws Exception {
String filePath = "/Users/fujiexiang/ExcelWorkbook.xlsx";
Workbook workbook = WorkbookFactory.create(new FileInputStream(filePath));
Sheet sheet = workbook.getSheetAt(0);
System.out.println("" + dataValidations + " " + dataValidations.size());
}
"[] 0" was printed out.
Apache POI bases on Office Open XML published for Excel 2007. And Excel 2007 had not supported data validation list constraint coming directly from another worksheet. There had must be created a named range for the data validation list constraint. Now current Excel versions support data validation list constraint coming directly from another worksheet but of course not backwards compatible. That's why apache poi also cannot read those constraints as it only reads CTDataValidations which are from Office Open XML published for Excel 2007.
In the XML the difference looks like so in /xl/worksheets/sheet1.xml:
Excel 2007:
<dataValidation type="list" allowBlank="1" showInputMessage="1" showErrorMessage="1" sqref="A1">
<formula1>Sheet2_A1_A5</formula1>
</dataValidation>
There "Sheet2_A1_A5" is a named range in the workbook that points to Sheet2!A1:A5.
Excel 365:
<x14:dataValidation type="list" allowBlank="1" showInputMessage="1" showErrorMessage="1">
<x14:formula1>
<xm:f>Sheet2!A1:A5</xm:f>
</x14:formula1>
<xm:sqref>A1</xm:sqref>
</x14:dataValidation>
There "Sheet2!A1:A5" is a direct reference to the other worksheet.
As you see, the new x14:dataValidation is in a separate name space. This is not covered by apache poi until now.
What one could do is using low level XML parsing methods to get the new XSSFX14DataValidations additional to the XSSFDataValidations. The following example shows a working draft for how to do this.
import java.io.FileInputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlCursor;
import javax.xml.namespace.QName;
class ReadExcelDataValidaton {
static java.util.List<XmlObject> getX14DataValidations(XSSFSheet sheet) {
java.util.List<XmlObject> x14DataValidations = new java.util.ArrayList<XmlObject>();
XmlCursor cursor = sheet.getCTWorksheet().newCursor();
cursor.selectPath(
"declare namespace x14='http://schemas.microsoft.com/office/spreadsheetml/2009/9/main' .//x14:dataValidation");
while(cursor.hasNextSelection()) {
cursor.toNextSelection();
XmlObject obj = cursor.getObject();
x14DataValidations.add(obj);
}
return x14DataValidations;
}
static void addXSSFX14DataValidations(XSSFSheet sheet, java.util.List<DataValidation> dataValidations) {
java.util.List<XmlObject> x14DataValidations = getX14DataValidations(sheet);
for (XmlObject x14DataValidation : x14DataValidations) {
XSSFX14DataValidation xssfX14DataValidation = new XSSFX14DataValidation(x14DataValidation);
dataValidations.add(xssfX14DataValidation);
}
}
static java.util.List<DataValidation> getDataValidations(Sheet sheet) {
#SuppressWarnings("unchecked")
java.util.List<DataValidation> dataValidations = (java.util.List<DataValidation>)sheet.getDataValidations();
if (sheet instanceof XSSFSheet) {
addXSSFX14DataValidations((XSSFSheet)sheet, dataValidations);
}
return dataValidations;
}
public static void main(String[] args) throws Exception {
Workbook workbook = WorkbookFactory.create(new FileInputStream("./Excel.xlsx"));
Sheet sheet = workbook.getSheetAt(0);
java.util.List<DataValidation> dataValidations = getDataValidations(sheet);
for (DataValidation dataValidation : dataValidations) {
System.out.println(dataValidation);
System.out.println(dataValidation.getValidationConstraint().getFormula1());
}
workbook.close();
}
}
class XSSFX14DataValidation implements DataValidation {
private DataValidationConstraint validationConstraint;
private int errorStyle;
private boolean emptyCellAllowed;
private boolean suppressDropDownArrow;
private boolean showPromptBox;
private boolean showErrorBox;
private String promptBoxTitle;
private String promptBoxText;
private String errorBoxTitle;
private String errorBoxText;
private CellRangeAddressList regions;
public XSSFX14DataValidation(XmlObject x14DataValidation) {
String type = "";
XmlObject typeAttribute = x14DataValidation.selectAttribute(new QName("type"));
if (typeAttribute != null) type = typeAttribute.newCursor().getTextValue();
Integer validationType = DataValidationConstraint.ValidationType.ANY;
if ("CUSTOM".equalsIgnoreCase(type)) {
validationType = DataValidationConstraint.ValidationType.FORMULA;
} else if ("DATE".equalsIgnoreCase(type)) {
validationType = DataValidationConstraint.ValidationType.DATE;
} else if ("DECIMAL".equalsIgnoreCase(type)) {
validationType = DataValidationConstraint.ValidationType.DECIMAL;
} else if ("LIST".equalsIgnoreCase(type)) {
validationType = DataValidationConstraint.ValidationType.LIST;
} else if ("NONE".equalsIgnoreCase(type)) {
validationType = DataValidationConstraint.ValidationType.ANY;
} else if ("TEXT_LENGTH".equalsIgnoreCase(type)) {
validationType = DataValidationConstraint.ValidationType.TEXT_LENGTH;
} else if ("TIME".equalsIgnoreCase(type)) {
validationType = DataValidationConstraint.ValidationType.TIME;
} else if ("WHOLE".equalsIgnoreCase(type)) {
validationType = DataValidationConstraint.ValidationType.INTEGER;
}
String operator = "";
XmlObject operatorAttribute = x14DataValidation.selectAttribute(new QName("operator"));
if (operatorAttribute != null) operator = operatorAttribute.newCursor().getTextValue();
Integer operatorType = DataValidationConstraint.OperatorType.IGNORED;
if ("BETWEEN".equalsIgnoreCase(operator)) {
operatorType = DataValidationConstraint.OperatorType.BETWEEN;
} else if ("NOT_BETWEEN".equalsIgnoreCase(operator)) {
operatorType = DataValidationConstraint.OperatorType.NOT_BETWEEN;
} else if ("EQUAL".equalsIgnoreCase(operator)) {
operatorType = DataValidationConstraint.OperatorType.EQUAL;
} else if ("NOT_EQUAL".equalsIgnoreCase(operator)) {
operatorType = DataValidationConstraint.OperatorType.NOT_EQUAL;
} else if ("GREATER_THAN".equalsIgnoreCase(operator)) {
operatorType = DataValidationConstraint.OperatorType.GREATER_THAN;
} else if ("GREATER_OR_EQUAL".equalsIgnoreCase(operator)) {
operatorType = DataValidationConstraint.OperatorType.GREATER_OR_EQUAL;
} else if ("LESS_THAN".equalsIgnoreCase(operator)) {
operatorType = DataValidationConstraint.OperatorType.LESS_THAN;
} else if ("LESS_OR_EQUAL".equalsIgnoreCase(operator)) {
operatorType = DataValidationConstraint.OperatorType.LESS_OR_EQUAL;
}
String formula1 = null;
XmlObject[] xmlObjects = x14DataValidation.selectChildren(
new QName("http://schemas.microsoft.com/office/spreadsheetml/2009/9/main", "formula1"));
if (xmlObjects.length > 0) {
XmlObject formula1Element = xmlObjects[0];
formula1 = formula1Element.newCursor().getTextValue();
}
String formula2 = null;
xmlObjects = x14DataValidation.selectChildren(
new QName("http://schemas.microsoft.com/office/spreadsheetml/2009/9/main", "formula2"));
if (xmlObjects.length > 0) {
XmlObject formula2Element = xmlObjects[0];
formula2 = formula2Element.newCursor().getTextValue();
}
this.validationConstraint = new XSSFDataValidationConstraint(validationType, operatorType, formula1, formula2);
this.regions = new CellRangeAddressList();
String sqref = "";
xmlObjects = x14DataValidation.selectChildren(
new QName("http://schemas.microsoft.com/office/excel/2006/main", "sqref"));
if (xmlObjects.length > 0) {
XmlObject sqrefElement = xmlObjects[0];
sqref = sqrefElement.newCursor().getTextValue();
}
String [] refs = sqref.split(" ");
for (String ref : refs) {
CellRangeAddress address = CellRangeAddress.valueOf(ref);
this.regions.addCellRangeAddress(address);
}
String allowBlank = "";
XmlObject allowBlankAttribute = x14DataValidation.selectAttribute(new QName("allowBlank"));
if (allowBlankAttribute != null) allowBlank = allowBlankAttribute.newCursor().getTextValue();
this.emptyCellAllowed = ("1".equals(allowBlank) || "TRUE".equalsIgnoreCase(allowBlank));
String showInputMessage = "";
XmlObject showInputMessageAttribute = x14DataValidation.selectAttribute(new QName("showInputMessage"));
if (showInputMessageAttribute != null) showInputMessage = showInputMessageAttribute.newCursor().getTextValue();
this.showPromptBox = ("1".equals(showInputMessage) || "TRUE".equalsIgnoreCase(showInputMessage));
String showErrorMessage = "";
XmlObject showErrorMessageAttribute = x14DataValidation.selectAttribute(new QName("showErrorMessage"));
if (showErrorMessageAttribute != null) showErrorMessage = showErrorMessageAttribute.newCursor().getTextValue();
this.showErrorBox = ("1".equals(showErrorMessage) || "TRUE".equalsIgnoreCase(showErrorMessage));
//TODO: complete
}
public DataValidationConstraint getValidationConstraint() {
return this.validationConstraint;
}
public void setErrorStyle(int errorStyle) {
this.errorStyle = errorStyle;
}
public int getErrorStyle() {
return this.errorStyle;
}
public void setEmptyCellAllowed(boolean allowed) {
this.emptyCellAllowed = allowed;
}
public boolean getEmptyCellAllowed() {
return this.emptyCellAllowed;
}
public void setSuppressDropDownArrow(boolean suppress) {
this.suppressDropDownArrow = suppress;
}
public boolean getSuppressDropDownArrow() {
return this.suppressDropDownArrow;
}
public void setShowPromptBox(boolean show) {
this.showPromptBox = show;
}
public boolean getShowPromptBox() {
return this.showPromptBox;
}
public void setShowErrorBox(boolean show) {
this.showErrorBox = show;
}
public boolean getShowErrorBox() {
return this.showErrorBox;
}
public void createPromptBox(String title, String text) {
this.promptBoxTitle = title;
this.promptBoxText = text;
}
public String getPromptBoxTitle() {
return this.promptBoxTitle;
}
public String getPromptBoxText() {
return this.promptBoxText;
}
public void createErrorBox(String title, String text) {
this.errorBoxTitle = title;
this.errorBoxText = text;
}
public String getErrorBoxTitle() {
return this.errorBoxTitle;
}
public String getErrorBoxText() {
return this.errorBoxText;
}
public CellRangeAddressList getRegions() {
return this.regions;
}
}
<MyWorld>
<MyWorldId>SGSNPackage2</MyWorldId>
<MyNation>
<state>GROWING</state>
</MyNation>
<state>HAPPY</state>
</MyWorld>
My Parser class :
import java.io.IOException;
import java.io.StringReader;
import java.util.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
public class MyParser extends DefaultHandler {
private static final String EMPTY_VALUE = "";
private final StringBuilder characters = new StringBuilder();
private boolean read;
private boolean elementFound;
private boolean elementPropertyFound;
private boolean elementIdFound;
private boolean elementWithIdFound;
private boolean elementProperty;
private boolean elementPropertyIsList;
private List<String> properties;
private final Set<String> propertyAlreadyExist = new HashSet<String>();
private String elementType;
private List<String> primaryKeyAttributes;
private String elementIdValue;
private String elementIdName;
private Map<String, Object> elementPropertiesMap;
Map<String, Object> complexMapAttribute = new HashMap<>();
public void setAttributes(final List<String> attributes) {
this.properties = attributes;
}
public void setFdnType(final String fdnType) {
this.elementType = fdnType;
}
public void setPrimaryKeyAttributes(final List<String> primaryKeyAttributes) {
this.primaryKeyAttributes = primaryKeyAttributes;
}
public void setKeyValue(final String keyValue) {
this.elementIdValue = keyValue;
}
#Override
public void startElement(final String uri, final String localName, final String qName, final Attributes attribute) throws SAXException {
if (qName.equalsIgnoreCase(elementType)) {
if (!elementWithIdFound) {
elementFound = true;
} else {
elementWithIdFound = false;
}
} else if (primaryKeyAttributes.contains(qName) && elementFound) {
elementIdFound = true;
read = true;
} else if (properties.contains(qName) && elementWithIdFound) {
if (propertyAlreadyExist.contains(qName)) {
elementPropertyIsList = true;
}
propertyAlreadyExist.add(qName);
elementIdName = qName;
elementPropertyFound = true;
read();
read = true;
elementProperty = false;
} else if(elementFound && elementWithIdFound && elementPropertyFound){
elementProperty = true;
read();
read = true;
}
}
#SuppressWarnings("unchecked")
#Override
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
final String text;
if (primaryKeyAttributes.contains(qName) || properties.contains(qName)) {
if (elementFound && elementWithIdFound && elementPropertyFound) {
text = readBuffer();
if (elementIdName != null) {
if(elementPropertyIsList) {
if(elementProperty){
if(null != elementPropertiesMap.get(elementIdName) && elementPropertiesMap.get(elementIdName)!= EMPTY_VALUE){
final List<Map<String,Object>> listOfComplexAttribute = new ArrayList<>();
if(elementPropertiesMap.get(elementIdName) instanceof List){
listOfComplexAttribute.addAll((List<Map<String, Object>>) elementPropertiesMap.get(elementIdName));
}else{
listOfComplexAttribute.add((Map<String, Object>) elementPropertiesMap.get(elementIdName));
}
listOfComplexAttribute.add(new HashMap<String, Object>(complexMapAttribute));
elementPropertiesMap.put(elementIdName, new ArrayList<Map<String, Object>>(listOfComplexAttribute));
}else{
elementPropertiesMap.put(elementIdName, new HashMap<String, Object>(complexMapAttribute));
}
complexMapAttribute.clear();
}else{
final List<Object> attributeValueList = new ArrayList<>();
if(null != elementPropertiesMap.get(elementIdName) && elementPropertiesMap.get(elementIdName)!= EMPTY_VALUE){
if(elementPropertiesMap.get(elementIdName) instanceof List){
attributeValueList.addAll((List<Object>) elementPropertiesMap.get(elementIdName));
}else{
attributeValueList.add(elementPropertiesMap.get(elementIdName));
}
attributeValueList.add(text);
elementPropertiesMap.put(elementIdName, new ArrayList<Object>(attributeValueList));
}else{
elementPropertiesMap.put(elementIdName,text);
}
}
} else {
if (elementProperty) {
elementPropertiesMap.put(elementIdName,new HashMap<String, Object>(complexMapAttribute));
complexMapAttribute.clear();
} else {
elementPropertiesMap.put(elementIdName,text);
}
}
elementIdName = null;
elementPropertyFound =false;
}
} else {
if (elementIdFound) {
if (readBuffer().equalsIgnoreCase(elementIdValue)) {
elementWithIdFound = true;
} else {
elementIdFound = false;
elementWithIdFound = false;
elementFound = false;
elementIdName = null;
}
}
}
}else if (elementFound && elementWithIdFound && elementPropertyFound && elementProperty){
text = readBuffer();
complexMapAttribute.put(qName, text);
}
}
#Override
public void characters(final char[] ch, final int start, final int length) throws SAXException {
if (read) {
characters.append(new String(ch, start, length));
}
}
public void parseData(final String data) {
elementPropertiesMap = new HashMap<>();
for (String attributeName : properties) {
elementPropertiesMap.put(attributeName, EMPTY_VALUE);
}
final SAXParserFactory parserFactor = SAXParserFactory.newInstance();
try {
final SAXParser parser = parserFactor.newSAXParser();
parser.parse(new InputSource(new StringReader(data)), this);
} catch (ParserConfigurationException | SAXException | IOException e) {
throw new RuntimeException((String) e.getMessage());
}
}
private void read() {
read = true;
characters.setLength(0);
}
private String readBuffer() {
final String chars = characters.toString();
characters.setLength(0);
read = false;
return chars;
}
}
I have above XML and I want to read the state of MyWorld. My SAX parser returns me the value of state as {GROWING. HAPPY} as attribures/element can occurs more than one so I handled accordingly.
What I want, I should get only "HAPPY" when I try to find state while parsing it ?
How I can achieve it ?
Thnaks a million for yur help!!
It is necessary to attach a 0313 XEP (0.2)
http://xmpp.org/extensions/attic/xep-0313-0.2.html#sect-idp616432
in to SMACK/ASMACK.
I create PacketExtension for this.
public class Archive313 implements PacketExtension {
static final public String NAMESPACE = "urn:xmpp:mam:tmp";
static final public String ELEMENT = "result";
private String Id;
private String Queryid;
private String Stamp;
private String To;
private String From;
private String Type;
private String Body;
public Archive313(String id, String queryid, String stamp, String to, String from, String type, String body) {
Id = id;
Queryid = queryid;
Stamp = stamp;
To = to;
From = from;
Type = type;
Body = body;
}
#Override
public String getElementName() {
return ELEMENT;
}
#Override
public String getNamespace() {
return NAMESPACE;
}
#Override
public String toXML() {
return "<" + ELEMENT + " xmlns='" + NAMESPACE + "' queryid='" + Queryid + "' id='" + Id + "'>" +
"<forwarded xmlns='urn:xmpp:forward:0'>" +
"<delay xmlns='urn:xmpp:delay' stamp='" + Stamp + "'/><message to='"
+ To + "' from='" + From + "' type='" + Type + "'><body>" + Body + "</body></message></forwarded></result>";
}
public static class Archive313Provider implements PacketExtensionProvider {
#Override
public PacketExtension parseExtension(XmlPullParser xmlPullParser) throws Exception {
String tag_name = "";
String id = "";
String queryid = "";
String stamp = "";
String to = "";
String from = "";
String type = "";
String body = "";
while (xmlPullParser.getEventType() != XmlPullParser.END_DOCUMENT) {
switch (xmlPullParser.getEventType()) {
case XmlPullParser.START_TAG:
tag_name = xmlPullParser.getName();
for (int i = 0; i < xmlPullParser.getAttributeCount(); i++) {
if (tag_name != null && tag_name.equals("result")) {
if (xmlPullParser.getAttributeName(i).equals("queryid")) {
queryid = xmlPullParser.getAttributeValue(i);
}
if (xmlPullParser.getAttributeName(i).equals("id")) {
id = xmlPullParser.getAttributeValue(i);
}
}
if (tag_name != null && tag_name.equals("delay")) {
if (xmlPullParser.getAttributeName(i).equals("stamp")) {
stamp = xmlPullParser.getAttributeValue(i);
}
}
if (tag_name != null && tag_name.equals("message") && xmlPullParser.getAttributeCount() > 2) {
if (xmlPullParser.getAttributeName(i).equals("to")) {
to = xmlPullParser.getAttributeValue(i);
}
if (xmlPullParser.getAttributeName(i).equals("from")) {
from = xmlPullParser.getAttributeValue(i);
}
if (xmlPullParser.getAttributeName(i).equals("type")) {
type = xmlPullParser.getAttributeValue(i);
}
}
}
break;
case XmlPullParser.END_TAG:
tag_name = xmlPullParser.getName();
break;
case XmlPullParser.TEXT:
if ("body".equals(tag_name)) {
body = xmlPullParser.getText();
}
break;
default:
break;
}
xmlPullParser.next();
}
return new Archive313(id,queryid,stamp,to,from,type,body);
}
}
}
ProviderManager pm = ProviderManager.getInstance();
pm.addExtensionProvider("result", "urn:xmpp:mam:tmp", new Archive313.Archive313Provider());
mXMPPConnection.addPacketListener(archiveListener, new PacketExtensionFilter("result", "urn:xmpp:mam:tmp"));
private PacketListener archiveListener = new PacketListener() {
#Override
public void processPacket(Packet packet) {
Log.d("archiveListener", packet.toXML());
}
};
In this implementation I do not give any Packet to archiveListener.
If i set filter:
PacketFilter filter = new PacketFilter() {
#Override
public boolean accept(Packet packet) {
if (packet.toXML().contains("urn:xmpp:mam:tmp")) {
return true;
}
return false;
}
};
I got packages but they are not full.
Need to be:
<message id='aeb213' to='juliet#capulet.lit/chamber'>
<result xmlns='urn:xmpp:mam:tmp' queryid='f27' id='28482-98726-73623'>
<forwarded xmlns='urn:xmpp:forward:0'>
<delay xmlns='urn:xmpp:delay' stamp='2010-07-10T23:08:25Z'/>
<message to='juliet#capulet.lit/balcony'
from='romeo#montague.lit/orchard'
type='chat'>
<body>Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.</body>
</message>
</forwarded>
</result>
</message>
I got:
<message id='aeb213' to='juliet#capulet.lit/chamber'>
<result xmlns='urn:xmpp:mam:tmp' queryid='f27' id='28482-98726-73623'>
</result>
</message>
In SMACK Logs I got full message.
It looks like your code
ProviderManager pm = ProviderManager.getInstance();
pm.addExtensionProvider("result", "urn:xmpp:mam:tmp", new Archive313.Archive313Provider());
never calls. Check this. Commonly, this code must be placed in static block of main class which working with xmpp lib.
To add any extension you have to do three things.
Create a custom extension class extending Extension/ExtensionElement.
Create an extension provider extending ExtensionProvider.
Add custom extension provider to provider manager.
Note : Extension provider will parse your extension from packet (XML) as per your requirement (onParse() method of provider). Every custom extension have to parsed manually and need to add custom provider to provider manager.
When I have the program print out System.out.println(_spaces.get("classroom").toStringLong()); it spits back "classroom: a large lecture hall with a door that goes null to sidewalk." Why does it say a door that goes to null? I think I have to fix my _buildPortals method, but I'm not sure how.
public class ConfigLoader
{
private Ini _ini;
private HashMap<String, Space> _spaces = new HashMap<String, Space>();
private HashMap<String, Portal> _portals = new HashMap<String, Portal>();
private HashMap<String, Agent> _agents = new HashMap<String, Agent>();
public ConfigLoader(File iniFile)
{
_ini = new Ini(iniFile);
}
public Agent buildAll()
{
_buildSpaces();
_buildPortals();
_buildExits();
_buildDestinations();
System.out.println(_spaces.get("classroom").toStringLong());
_buildAgents();
//return _selectStartAgent();
return null;
}
private void _buildSpaces()
{
for(String spaceName : _ini.keys("spaces"))
{
String description = _ini.get("spaces", spaceName);
String image = _ini.get("images", "images");
Space spaceInstance = new Space(spaceName, description, null, image);
_spaces.put(spaceName, spaceInstance);
}
}
private void _buildPortals()
{
for(String portalName : _ini.keys("portals"))
{
String description = _ini.get("portal", portalName);
Portal portalInstance = new Portal(portalName, description, null);
_portals.put(portalName, portalInstance);
}
}
private void _buildExits()
{
for(String spaceName : _ini.keys("exits"))
{
String spaceExit = _ini.get("exits", spaceName);
Space space = _spaces.get(spaceName);
Portal exit = _portals.get(spaceExit);
space.setPortal(exit);
}
}
private void _buildDestinations()
{
for(String portalName : _ini.keys("destinations"))
{
String destination = _ini.get("destinations", portalName);
Space dest = _spaces.get(destination);
Portal portal = _portals.get(portalName);
if(dest == null)
{
System.out.println("Error");
System.exit(1);
}
else
{
portal.setDestination(dest);
}
}
}
private void _buildAgents()
{
for(String agentName : _ini.keys("agents"))
{
String agent = _ini.get("agents", agentName);
Space space = _spaces.get(agent);
if(space == null)
{
System.out.println("Error");
System.exit(1);
}
else
{
Agent a = new Agent(space, agentName);
_agents.put(agentName, a);
}
}
}
private Agent _selectStartAgent()
{
for(String agentName : _ini.keys("start"))
{
String agent = _ini.get("start", agentName);
Agent agentInstance = _agents.get(agent);
if(agent == null)
{
System.out.println("Error");
System.exit(1);
}
else
{
return agentInstance;
}
}
return null;
}
}
Following the other patterns in your code, maybe..
String description = _ini.get("portal", portalName);
needs to be
String description = _ini.get("portals", portalName);
If so, it's usually a good idea to extract something like this to a string constant.
private static final String PORTALS = "portals";
and use that in multiple places.
Your buildSpaces method's second line is wrong. You're getting the image associated with a certain space but you have two strings in your get call and that's not right.