Hi I am completely new in XML in Java.In my recent project I need to create validation rules in XML,but the the problem is that different user group may have different rule
For example
<root>
<user-group type="sale">
<parameter-name ="loginName">
<max-length>10</max-length>
<min-length>4</min-length>
</parameter-name>
<parameter-name ="password">
<max-length>10</max-length>
<min-length>4</min-length>
</parameter-name>
</user-group>
<user-group type="clerk">
<parameter-name ="loginName">
<max-length>16</max-length>
<min-length>4</min-length>
</parameter-name>
<parameter-name ="password">
<max-length>12</max-length>
<min-length>8</min-length>
</parameter-name>
</user-group>`
</root>
So how to write a Java stuff to implements the above rule.
Thanks in advance.
Read the XML using one of the known XML parsers. Refer
XML Parsing for Java
As you read through the XML, you can create a data structure to store the rules. This is explained below.
Loop through each of the "user-group" XML nodes in your Java program, create a map implementation, you can use a HashMap, with key - "clerk" value will be a POJO bean defining a "rule"
For example here is your "Rules" class -
public class Rules {
private String ruleName;
private int maxLength;
private int minLength;
public String getRuleName() {
return ruleName;
}
public void setRuleName(String ruleName) {
this.ruleName = ruleName;
}
public int getMinLength() {
return minLength;
}
public void setMinLength(int minLength) {
this.minLength = minLength;
}
public void setMaxLength(int maxLength) {
this.maxLength = maxLength;
}
public int getMaxLength() {
return maxLength;
}
}
Now you can use this HashMap anywhere in your program, to implement the rules. Seems like you would need to implement rules on the UI. In that case, I would recommend using established frameworks like Struts, Spring or an equivalent framework.
Hope this gives you a headstart ;)
The simple answer: use XML schemas with define namespaces. This way each user-group type can define what the structure of that node is. Setting this as an attribute is not really the most effective way to do this. I can elaborate later tonight on how to use XSD with namespaces so that you could create a document with "different" user-group nodes, specified in different namespaces, that each entity could validate and use without any problems. I don't have time to show an example, but I found this: Creating an XML document using namespaces in Java
The most simplistic explanation I can come up with is the definition of "table". For a furniture store, a "table" entity has maybe a round or square surface with most likely 4 legs, etc. But a "table" could mean something completely different for some other group. Using your XML as an example, it would be something like this:
<root>
<sale:user-group xmlns:sale="SOME_URL">
<some structure and rules>
</sale:user-group>
<clerk:user-group xmlns:clerk="SOME_OTHER_URL">
<different structure and rules>
</clerk:user-group>
</root>
The link I provided should answer your question. If not, I will come back tonight and show you a simple XSD that might fit your case.
Related
I want to implement a network protocol. To obtain a maintainable design I am looking for fitting patterns.
The protocol is based on XML and should be read with java. To simplify the discussion here I assume the example grammar:
<User>
<GroupList>
<Group>group1</Group>
<Group>group2</Group>
</GroupList>
</User>
Short question:
What is a good design pattern to parse such thing?
Long version:
I have found this and this question where different patterns (mostly state pattern) are proposed.
My actual (but lacking) solution is the folowing:
I create for each possible entry in the XML a class to contain the data and a parser. Thus I have User, User.Parser, ... as classes.
Further there is a ParserSelector that has a Map<String,AbstractParser> in which all possible subentries get registered.
For each parser a ParserSelector gets instantiated and set up.
For example the ParserSelector of the GroupList.Parser has one entry: The mapping from the string "Group" to an instance of Group.Parser.
If I did not use the ParserSleector class, I would have to write this block of code into every single parser.
The problem is now how to get the read data to the superobjects.
The Group.Parser would create a Group object with content group1.
This object must now be registered in the GroupList object.
I have read of using Visitor or Observer patterns but do not understand how they might fit here.
I give some pseudo code below to see the problem.
You see, that I have to check via instanceof for the type as statically there is the type information not available.
I thought this should be possible to solve using polymorphism in java in a cleaner (more maintainable) way.
I always face then the problem that java does only do dynamic binding on overriding.
Thus I cannot add a parameter to the XMLParser.parse(...) method to allow of "remote updating" as in a visitor/observer like approach.
Side remark: The real grammar is "deep" that is, it is such that there are quite many XML entries (here only three: User, GroupList and Group) while most of them might contain only very few different subentries (User and GroupList may only contain one subentry here, while Group itself contains only text).
Here comes some lines of pseude java code to explain the problem:
class User extends AbstractObject {
static class Parser implements XMLParser {
ParserSelector ps = ...; // Initialize with GroupList.Parser
void parse(XMLStreamReader xsr){
XMLParser p = ps.getParser(...); // The corresponding parser.
// We know only that it is XMLParser statically.
p.parse(...);
if(p instanceof GroupList.Parser){
// Set the group list in the User class
}
}
}
}
class GroupList extends AbstractObject{...}
class Group extends AbstractObject{...}
class ParserSelector{
Map<String,XMLParser> = new Map<>();
void registerParser(...){...} // Registers a possible parser for subentries
XMLParser getParser(String elementName){
return map.get(elementName); // Returns the parser registered with the given name
}
}
interface XMLParser {
void parse(XMLStreamReader xsr);
}
abstract class AbstractObject{}
To finish this question:
I ended up with JAXB. In fact I was not aware of the fact that it allows to easily create a XML Schema from java source code (using annotations).
Thus I just have to write the code with classical java objects which are used for transfer. Then the API handles the conversion to and from XML quite well.
I need to import a text file, with values separated by pipes ( | ), into a database using Java and Hibernate. The text file is generated elsewhere, and has the following layout:
example-file.txt
|0150|A|B|C|
|0150|X|Y|Z|
|0190|1|2|
|0200|9|8|7|H|F|E|
Each line corresponds to a record.
The first value (i.e 0150, 0190, 0200) is the type of info it holds (to which table it should be stored).
The rest are the values to be stored in that table.
So far, I've been able to read the lines, find to which Object the record corresponds to - using a Factory pattern - separating the values into a String[] array and calling a method createInstance(String[] fields) to create the object and store it into the database - using a Template pattern:
ImportServiceInterface
public interface ImportServiceInterface {
public void createInstance(String[] fields);
}
AbstractImportService
public abstract class AbstractImportService implements ImportServiceInterface {
public static ImportServiceInterface getImportService(String line) {
// returns the correct subclass
}
public void import() {
createInstance(splitFields());
}
public String[] splitFields(String line) {
// splits the line
}
}
So I have 3 separate services, each implementing their own version of createInstance(String[] fields):
ImportExampleTypeService
public ImportExampleTypeService implements AbstractImportService {
public void createInstance(String[] fields) {
ExampleModel myExample = new myExampleModel(); // mapped with Hibernate
// find which object members corresponds to the fields
// call the DAO to store the object
}
}
My problem is that the user will be able to specify his own layout: to which fields the values correspond to, size and position.
I thought about creating a table to store the layouts, then matching the names of the attributes using Reflection.
But I must be missing something, perhaps there's an easier way to do this?
SuperCSV supports custom delimiters and population of java objects via reflection, so I think it would do most of your work for you in this case.
Furthermore, it supports the concept of a header row as the first line in the file which then defines which fields those columns are mapped to in the java object, or you can just customize the column mappings manually.
Thank you #increment1 and #Templar for your answers!
The requirements have changed. The system has to be able to import both the above format (which will not be user-defined) and a user-defined, CSV-like, flat file, with a single type of record per file. It makes my life easier. I have been looking at different flat-file parsing libraries, and I'm posting it here in case anyone stumbles upon the same problem:
jflat: simple to use, extensible and customizable framework. Probably the best choice for most.
BeanIO: a flat-file marshaller/unmarshaller that uses xml files to figure out how to parse the file. Supports many formats, more than one type of record per file etc.
FFP: Flat File Parsing. Also supports absolute and relative definitions, using POJOs instead of xml files. I would have chosen this one, but it seems to be dead?
Flatworm: very similar to BeanIO. It appears it has inspired BeanIO, and there is not much activity on Flatworm either...
I have chosen BeanIO, because its flexibility suits my project better. So here's what I am going to do:
1) Keep my design, implementing my createInstance() method as needed;
2) Use a different implementation using BeanIO for the user-defined files;
3) Use a Facade to call the parser I need:
FacadeInterface
public interface ImportFacadeInterface {
public void importFile();
}
ImportDefaultLayoutFacadeImpl
public class ImportDefaultLayoutFacadeImpl implements ImportFacadeInterface {
public void importFile() {
// use the ImportServiceInterface
}
}
ImportUserDefinedLayoutFacadeImpl
public class ImportUserDefinedLayoutFacadeImpl implements ImportFacadeInterface {
public void importFile() {
// use BeanIO
}
}
My approch to store the possible record structures would be a Map with |0150| as Key and |A|B|C| as Value. This could be an approch to parse a line.
String line = ...;
String structure = map.get(line.substring(1, 4));
// Now you have the line structure and can parse it into your own format.
I was to save some configuration values. :)
These values are might be defined in a xml file and might be of the types String, boolean, String[], ...
or others. These values might be defined in a xml file.
Is there a best practise way to save these values, together with their tagname in the xml file and a default value.
I want to clean up some ultra bad legacy code, where things look like this:
public static final String VIEWCOOKIE_MAXLENGTH_VALUENAME = "view_cookie_max_length";
public static final int VIEWCOOKIE_MAXLENGTH_DEFAULT = 512;
public static int viewCookie_maxLength = VIEWCOOKIE_MAXLENGTH_DEFAULT;
Integer temInt = basic.getTimedBaseIntegerValue(basic.c_adclear_section, null,
CookieValues.VIEWCOOKIE_MAXLENGTH_VALUENAME,
CookieValues.VIEWCOOKIE_MAXLENGTH_DEFAULT, currentTime);
if (firstLoad || basic.checkParamChanged(0,CookieValues.VIEWCOOKIE_MAXLENGTH_VALUENAME,
CookieValues.viewCookie_maxLength, temInt))
CookieValues.viewCookie_maxLength = temInt;
those lines for all values, and methods for all the different type.
Is there a better way like this:
public class Value<T> {
String valueName;
final T defaultValue;
T value;
Method method;
...
}
but I don't know if this is the best way and also I'm a little bit worried, because I don't want to slow down the server, due to all the Wrapppers. This problem is hard to search so I'm sorry if this has already been asked somewhere.
This might answer your question: What is the best way to convert a java object to xml with open source apis
Basically you have to use a Marshaller (something that converts an object to text and back), and there are tons of those for Java.
I want to write my own locator to access the elements. WebDriver’s API offers currently eight locators allowing to retrieve elements by id, name attribute, tag name, complete or partial link text, XPath, class name, and css selector. However those default locators not enough for me now because I have to access the elements through a new attribute. Let me give an xample so that you can understand what I really want here.
Example:
Choose your username:
Now I want to write a code so that I can access the username button using the myLocator locator like:
*driver.findElement(By.myLocator("username")).*
It would be very helpful if anybody can give us some good idea how could I rewrite the BY class to add my own locator.
Thank you in advance for your help.
using c#
using OpenQA.Selenium;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class ImageBy : By
{
public ImageBy(string imageByString)
{
FindElementMethod = (ISearchContext context) =>
{
IWebElement mockElement = context.FindElement(By.XPath("//img[#src='" + imageByString + "']"));
return mockElement;
};
FindElementsMethod = (ISearchContext context) =>
{
ReadOnlyCollection<IWebElement> mockElements = context.FindElements(By.XPath("//img[#src='" + imageByString + "']"));
return mockElements;
};
}
}
and the usage would be as follows
[FindsBy(How = How.Custom, Using = #"/path/to/img", CustomFinderType = typeof(ImageBy) )]
private IWebElement MenuStartButton = null;
Using Java
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebElement;
public class ByImageSrc extends By
{
private final String imageByString;
public ByImageSrc(String imageByString)
{
this.imageByString = imageByString;
}
#Override
public List<WebElement> findElements(SearchContext context)
{
List<WebElement> mockElements = context.findElements(By.xpath("//img[#src='" + imageByString + "']"));
return mockElements;
}
}
usage :
WebElement element = driver.findElement(new ByImageSrc("/path/to/image"));
You would need to subclass the By class and provide an implementation for findElement and findElements methods, since this is where the 'meat' of the actual element finding occurs.
You should then be able to use it with the normal driver.FindElement then.
I know this doesn't really answer your question, but why not just use Xpath?
It seems like it would be a lot of extra work to build out a new locator instead of just crawling the DOM.
For example: driver.findElement(By.Xpath("//div[#username='YourUsername']")
I could give a better example with some more detail about the attribute and page you're working with.
Much like Michiel answered I feel you can achieve what you want with what Selenium has already provided. If it is a maintenance overhead you are wanting to avoid due to developers altering ids and element names you can create a separate file that keeps track of the elements you need to locate.
//EG. (not Java I know :))
string usernameXPath = "//div[#username='YourUsername']";
Then if there is a change you can maintain this. You could even go a step further and implement a class for each 'other type' of element and just put an XPath around it in the constructor. XPath is very flexible as it offers functions such as 'contains' and 'parent::div'. Maybe look at the W3schools page for some more XPath reading.
EDIT: Also worth noting is that the C# bindings latest release says the following:
.Net: Introduces the Updating the CustomFinderType property to the
.NET FindsByAttribute. This allows use of custom By subclasses in
the PageFactory. The custom finder must be a subclass of By, and
it must expose a public constructor that takes a string argument.
Hopefull this is in the next Java release for you too :)
You can do something like this:
private final String myLocator = "//*[contains(#id,'username') and contains (#type,'text') and contains (text(),'exactly what I want')]";
So you can write up the locator however you wish, depending on the attributes that what you're mapping has, no need to have 5 rows for a click or select.
Also, you can use a wildcard in that locator and just replace whatever you want to use as a parameter with "%s", like this:
private final String myLocator = "//*[contains(#id,'%s') and contains (#type,'text') and contains (text(),'exactly what I want')]";
Then have a dynamic element created from that like:
private WebElement usernameSelectElement(String text) {
return driver.findElement(By.xpath(String.format(myLocator, text)));
}
And the usage would be something like:
public void clickMyElement(text){
usernameSelectElement(text).click();
}
For the example that you had, it's just overly complicated in my view.
We are designing a system for processing XML messages.
The processing Java class needs to split out various attributes and values from a largish XML and pass these as parameters to individual handler classes for varied operations.
We have thought of following options:
A)
Pass the entire XML to each handler and let it extract the relevant bits - but feel this might be inefficient to pass the XML around each time
B)
Convert the XML into a DTO or set of smaller DTOs and pass each DTO to relevant handler
C)
Cut the XML into snippets and pass these to each handler method
We're not happy with each of these, so any suggestions which way to go?
Example XML
<IdAction>supplied</IdAction>
<RegId>true</RegId>
<DeRegId>false</DeRegId>
<SaveMessage>false</SaveMessage>
<ServiceName>abcRequest</ServiceName>
<timeToPerform>3600</timeToPerform>
<timeToReceipt/>
<SendToBES>true</SendToBES>
<BESQueueName>com.abc.gateway.JMSQueue.forAddRequest</BESQueueName>
<BESTransform/>
<BESJMSProperties>
<property>
<propName>stateCode</propName>
<propValue>OK</propValue>
</property>
<property>
<propName>stateResponse</propName>
<propValue>OK</propValue>
</property>
</BESJMSProperties>
This contains 4 blocks processed by 4 handlers one does
<IdAction>supplied</IdAction>
<RegId>true</RegId>
<DeRegId>false</DeRegId>
another does
<timeToPerform>3600</timeToPerform>
<timeToReceipt/>
next does
<SendToBES>true</SendToBES>
<BESQueueName>com.abc.gateway.JMSQueue.forAddRequest</BESQueueName>
<BESTransform/>
<BESJMSProperties>
<property>
<propName>stateCode</propName>
<propValue>OK</propValue>
</property>
<property>
<propName>stateResponse</propName>
<propValue>OK</propValue>
</property>
</BESJMSProperties>
and so on
B sounds like the best option to me. A is most inefficient, and C would presumably need one pass to parse it and pick out the fragments, then a 2nd pass to properly handle them?
Use SAX to parse out minimal DTO sets for transmission to dedicated handler classes.
Good question, btw. Good to think about these things in advance, and get 2nd, 3rd, 4th opinions :-)
I don't think you need any special design considerations in terms of memory usage or performance so I would go with the solution that involved the least amount of coding and that would be to use a JAXB marshaller to parse your xml into DTOs and then going with your plan B. Perhaps it is harder to set up than StAX but it saves you from writing any XML parsing.
http://jaxb.java.net/
if you are using Spring is very easy to set up a bean for org.springframework.oxm.jaxb.Jaxb2Marshaller
http://static.springsource.org/spring-ws/site/reference/html/oxm.html (8.5.2)
Tried?
http://simple.sourceforge.net/
Personally i would create a datamodel for the xml and pass the datamodel around. Take a look at the tutorials. With a custom datamodel you can map only the data you want into the model and for the handler classes you can pass along child nodes or a subset of the xml data model instead of the entire thing.
If you have an xml with the following structure
<book>
<title>XML</title>
<author>
<firstname>John</firstname>
<lastname>Doe</lastname>
</author>
<isbn>123541356eas</isbn>
</book>
Then you would have a datamodel something like this:
[ Book ] [ Author ]
--------------- ------------------
|String title | |String firstname|
|String isbn | |String lastname |
|Author author| ------->|----------------|
---------------
Where Book has a reference to Author.
And then you could pass along the Author object to your handler method.
You could use StAX for this use case. Each processBlock operation will act on the XMLStreamReader advancing its state, then subsequent processBlock operations can do their bit:
package forum7011558;
import java.io.FileReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
public class Demo {
public static void main(String[] args) throws Exception {
Demo demo = new Demo();
FileReader xml = new FileReader("src/forum7011558/input.xml");
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
demo.processBlock1(xsr);
demo.processBlock2(xsr);
demo.processBlock3(xsr);
demo.processBlock4(xsr);
}
private void processBlock1(XMLStreamReader xsr) {
// PROCESS BLOCK 1
}
private void processBlock2(XMLStreamReader xsr) {
// PROCESS BLOCK 2
}
private void processBlock3(XMLStreamReader xsr) {
// PROCESS BLOCK 3
}
private void processBlock4(XMLStreamReader xsr) {
// PROCESS BLOCK 4
}
}