How to read the WebMaster field with Rome - java

I am trying to use ROME to parse an RSS feed like this:
url = new URL("http://www.rssboard.org/files/sample-rss-2.xml");
XmlReader reader = new XmlReader(url);
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(reader);
System.out.println(feed.getAuthor());
However, I cannot find a method to get the "WebMaster" field or any other customized field.
I have read about the custom modules in Rome from here, but I couldn't figure out how to use it. I create a similar SamplleModule, SampleModuleImpl, and SampleModule Parser for webMaster field, but I don't know how to use it!
This the classes that I have implemented:
SamplleModule:
public interface SampleModule extends Module {
public static final String URI =
"http://www.rssboard.org/files/sample-rss-2.xml";
public String getWebMaster();
public void setWebMaster(String webMaster);
}
SampleModuleImpl:
public class SampleModuleImpl extends ModuleImpl implements SampleModule {
private static final long serialVersionUID = 1L;
private String _webMaster;
protected SampleModuleImpl() {
super(SampleModule.class, SampleModule.URI);
}
#Override
public void copyFrom(Object obj) {
SampleModule sm = (SampleModule) obj;
setWebMaster(sm.getWebMaster());
}
#Override
public Class getInterface() {
return SampleModule.class;
}
#Override
public String getWebMaster() {
return _webMaster;
}
#Override
public void setWebMaster(String webMaster) {
_webMaster = webMaster;
}
}
and SampleModuleParser:
public class SampleModuleParser implements ModuleParser {
private static final Namespace SAMPLE_NS = Namespace.getNamespace("sample",
SampleModule.URI);
#Override
public String getNamespaceUri() {
return SampleModule.URI;
}
#Override
public Module parse(Element dcRoot) {
boolean foundSomething = false;
SampleModule fm = new SampleModuleImpl();
Element e = dcRoot.getChild("webMaster");
if (e != null) {
foundSomething = true;
fm.setWebMaster(e.getText());
}
return (foundSomething) ? fm : null;
}
}
I have also added these module to rome.properties.
I just don't know how to use them in my reader method.
Any idea folks?

take a look here for an example of how do to this with the MRSS module:
http://ideas-and-code.blogspot.com/2009/07/media-rss-plugin-for-rome-howto.html
Basically you take a SyndEntry object and using the namespace for your module you get an instance of your module object from the entry if one exists, so in your case:
SampleModule myModule = (SampleModule)e.getModule( SampleModule.URI );
And then you can use it. I use groovy with rome for my parser and do things like this:
def mediaModule = entry.getModule("http://search.yahoo.com/mrss/")
if(mediaModule) {
mediaModule.getMediaGroups().each { group ->
group.contents.each { content ->
if(content.type != null && content.type.startsWith("image")) {
log.info "got an image"
String imgUrl = content.getReference().toString()
post.images.add(new MediaContent(type:'image',url:imgUrl))
}
}
}
}
HTH

Related

A way of accessing Windows MMDevice API from Java?

I would like to use the MMDevice API from my Java app. What are my options?
I tried to use JNA. Looks like I can't use JNA Typelib parsing because there no types for this API (Is there a COM type library for Windows Core Audio). As suggested, I need to provide my own declarations of the API.
So I also tried both JNA examples with manual declarations but they give "Interface not supported HRESULT=80004002" error:
public class MMDeviceAPITest {
public static void test1() {
try {
Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
var obj = new Test1.MMDeviceEnumerator(); // exception E_NOINTERFACE (HRESULT: 80004002)
// ...
} finally {
Ole32.INSTANCE.CoUninitialize();
}
}
public static void test2() {
try {
Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
var factory = new Factory();
var obj = factory.createObject(Test2.MMDeviceEnumerator.class); // exception E_NOINTERFACE (HRESULT: 80004002)
var in = obj.queryInterface(Test2.IMMDeviceEnumerator.class);
// ...
} finally {
Ole32.INSTANCE.CoUninitialize();
}
}
}
interface Test1 {
class MMDeviceEnumerator extends COMLateBindingObject {
public MMDeviceEnumerator() {
super(new Guid.CLSID("bcde0395-e52f-467c-8e3d-c4579291692e"), true);
}
}
}
interface Test2 {
#ComObject(clsId = "bcde0395-e52f-467c-8e3d-c4579291692e")
interface MMDeviceEnumerator extends IUnknown {} // doesn't extend IUnknown in C sources, probably it's the problem...
#ComInterface(iid = "a95664d2-9614-4f35-a746-de8db63617e6")
interface IMMDeviceEnumerator extends IUnknown {}
}
Any ideas how I could access this API from Java? Can I somehow create working declarations for JNA? Or use another framework maybe?
My last idea is to create/find a micro native app/library that wraps the needed COM calls, so I could call this app/library easily (via subprocesses or simple JNA declarations). I'm new to COM world, but it sounds working for me...
The docs you linked show how to create using CoCreateInstance:
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
hr = CoCreateInstance(
CLSID_MMDeviceEnumerator, NULL,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
(void**)&pEnumerator);
This should get you somewhere close with JNA.
class MMDeviceEnumerator extends Unknown {
public static final CLSID CLSID_MMDeviceEnumerator = new CLSID("bcde0395-e52f-467c-8e3d-c4579291692e");
public static final GUID IID_IMMDeviceEnumerator = new GUID("a95664d2-9614-4f35-a746-de8db63617e6");
public MMDeviceEnumerator(Pointer p) {
super(p);
}
public static MMDeviceEnumerator create() {
PointerByReference pEnumerator = new PointerByReference();
HRESULT hres = Ole32.INSTANCE.CoCreateInstance(
CLSID_MMDeviceEnumerator, null,
WTypes.CLSCTX_ALL, IID_IMMDeviceEnumerator,
pEnumerator);
if (COMUtils.FAILED(hres)) {
return null;
}
return new MMDeviceEnumerator(pEnumerator.getValue());
}
// map functions as needed
}
I used the implementation of IWbemContext in JNA as a template above. You can consult that class for example COM function mappings.
For some reason I can't suggest edits to the answer of Daniel Widdis. The answer worked for me, many thanks! Just wanted to show how to map one method as an example:
class MMDeviceEnumerator extends Unknown {
public static final CLSID CLSID_MMDeviceEnumerator = new CLSID("bcde0395-e52f-467c-8e3d-c4579291692e");
public static final GUID IID_IMMDeviceEnumerator = new GUID("a95664d2-9614-4f35-a746-de8db63617e6");
public MMDeviceEnumerator(Pointer p) {
super(p);
}
public static MMDeviceEnumerator create() {
PointerByReference pEnumerator = new PointerByReference();
HRESULT hres = Ole32.INSTANCE.CoCreateInstance(
CLSID_MMDeviceEnumerator, null,
WTypes.CLSCTX_ALL, IID_IMMDeviceEnumerator, pEnumerator);
if (COMUtils.FAILED(hres)) {
return null;
}
return new MMDeviceEnumerator(pEnumerator.getValue());
}
public static final int EDataFlow_eRender = 0;
public static final int EDataFlow_eCapture = 1;
public static final int EDataFlow_eAll = 2;
public static final int EDataFlow_enum_count = 3;
public static final int DEVICE_STATE_ACTIVE = 0x1;
public static final int DEVICE_STATE_DISABLED = 0x2;
public static final int DEVICE_STATE_NOTPRESENT = 0x4;
public static final int DEVICE_STATE_UNPLUGGED = 0x8;
public static final int DEVICE_STATEMASK_ALL = 0xF;
public void EnumAudioEndpoints(int dataFlow, int dwStateMask, PointerByReference ppDevices) {
WinNT.HRESULT res = (WinNT.HRESULT) _invokeNativeObject(
3, // `EnumAudioEndpoints` is the 3rd method of `IMMDeviceEnumeratorVtbl` in `mmdeviceapi.h`
new Object[] { getPointer(), dataFlow, new WinDef.DWORD(dwStateMask), ppDevices},
WinNT.HRESULT.class
);
COMUtils.checkRC(res);
}
// map other functions as needed
}

How to deserialize JSON with private constructor and interfaces as Builder?

I've searched the internet for something to similar to what I'm doing, but haven't found anything. I'm using interfaces in Java 8 to create a Builder pattern, like so:
public class UrlImmutable {
public final String parentUrl;
public final Double parentUrlSentiment;
public final Set<String> childUrls;
public final boolean isParentVendorUrl;
public final Map<TagClassification, Set<String>> parentUrlArticleTags;
private UrlImmutable(String parentUrl, Double parentUrlSentiment, Set<String> childUrls, boolean isParentVendorUrl,
Map<TagClassification, Set<String>> parentUrlArticleTags ) {
super();
this.parentUrl = parentUrl;
this.parentUrlSentiment = parentUrlSentiment;
this.childUrls = childUrls;
this.isParentVendorUrl = isParentVendorUrl;
this.parentUrlArticleTags = parentUrlArticleTags;
}
/** Our Interfaces for the Builder **/
public interface ParentUrlBuilder {
ParentUrlSentimentBuilder parentUrl(String parentUrl);
}
public interface ParentUrlSentimentBuilder {
ChildUrlBuilder parentUrlSentiment(Double parentUrlSentiment);
}
public interface ChildUrlBuilder {
IsVendorUrlBuilder childUrls(Set<String> childUrls);
}
public interface IsVendorUrlBuilder {
ParentUrlArticleTagsBuilder isParentVendorUrl(boolean isParentVendorUrl);
}
public interface ParentUrlArticleTagsBuilder {
UrlImmutable parentUrlArticleTags(Map<TagClassification,Set<String>> parentUrlArticleTags);
}
public static ParentUrlBuilder discoveredUrl() {
return parentUrl -> parentUrlSentiment -> childUrls -> isParentVendorUrl -> parentUrlArticleTags ->
new UrlImmutable(parentUrl, parentUrlSentiment, childUrls, isParentVendorUrl, parentUrlArticleTags);
}
}
And to construct this object, we do this:
UrlImmutable url =
UrlImmutable()
.parentUrl("http://www.google.com")
.parentUrlSentiment(10.5)
.childUrls(childUrls)
.isParentVendorUrl(true)
.parentUrlArticleTags(parentUrlArticleTags);
I can't seem to find the right combination of annotations for this. Any help much appreciated!

how to use path variable in californium CoAP server?

Similar with Restful syntax in Jersey or other framework, I could fetch the variable in the Restful uri path like that:
#Path("/users/{username}")
public class UserResource {
#GET
#Produces("text/xml")
public String getUser(#PathParam("username") String userName) {
...
}
}
but in californium, the syntax is different, I try these codes but it is not correct:
class usersextends CoapResource {
public users() {
super("users/{username}");
}
#Override
public void handleGET(CoapExchange exchange) {
exchange.respond("The username is "+ ???????);
}
}
How could I use the same function as first piece of code did? Another thing is where I can find official document introduce the API? I just saw the source code and try to find the solution now.
Create your own MessageDeliverer and change findResource method:
public class MyMessageDeliverer implements MessageDeliverer {
private final Resource root;
public MyMessageDeliverer(Resource root) {
this.root = root;
}
/* You can use implementation of methods from ServerMessageDeliverer */
#Override
public void deliverRequest(Exchange exchange) {
}
#Override
public void deliverResponse(Exchange exchange, Response response) {
}
/* method returns last known Resource instead of null*/
private Resource findResource(List<String> list) {
LinkedList<String> path = new LinkedList<String>(list);
Resource current = root;
Resource last = null;
while (!path.isEmpty() && current != null) {
last = current;
String name = path.removeFirst();
current = current.getChild(name);
}
if (current == null) {
return last;
}
return current;
}
}
Use your MessageDeliverer:
server = new CoapServer();
server.setMessageDeliverer(new MyMessageDeliverer(server.getRoot()));
Add your Resource to server:
server.add(new Users());
Request /users/{username} will be delivered to your Users resource. Fetch the variable from request URI:
public class Users extends CoapResource {
public Users() {
super("users");
}
public void handleGet(CoapExchange exchange) {
List<String> uri = exchange.getRequestOptions().getUriPath();
uri.remove("users");
String username = uri.remove(0);
//for query params:
Map<String, String> params = new HashMap<String, String>();
for (String p : exchange.getRequestOptions().getUriQuery()) {
String[] parts = p.split("=");
params.put(parts[0], parts[1]);
}
String param = params.get("param");
}
}

How to create custom events in Java

Even after some time trying to read and understand the topics already posted here, I am still confused on how to create events in Java.
Assuming that I have this class in C#:
public class HighlightsObjectHandler {
// Constants
private const String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Handlers
public event EventHandler HighlightsJsonChanged;
public event EventHandler HighlightsContentChanging;
public event EventHandler HighlightsContentChanged;
// Variables
private String
_json;
// Properties
public String HighlightsJson {
get {
return _json;
}
set {
if (value != _json && value != null) {
_json = value;
OnHighlightsJsonChanged( EventArgs.Empty );
ParseJson();
}
}
}
public Boolean HighlightsUpdating { get; private set; }
public List<HighlightObject> Highlights { get; private set; }
// Methods
private void ParseJson() {
JsonObject
jsonObject;
if (JsonObject.TryParse( HighlightsJson, out jsonObject )) {
OnHighlightsContentChanging( EventArgs.Empty );
// Json parsing and other stuff...
// ... it shouldn't matter for this question.
OnHighlightsContentChanged( EventArgs.Empty );
}
}
// Events
internal void OnHighlightsJsonChanged( EventArgs eventArgs ) {
if (HighlightsJsonChanged != null) {
HighlightsJsonChanged( this, eventArgs );
}
}
internal void OnHighlightsContentChanging( EventArgs eventArgs ) {
HighlightsUpdating = true;
if (HighlightsContentChanging != null) {
HighlightsContentChanging( this, eventArgs );
}
}
internal void OnHighlightsContentChanged( EventArgs eventArgs ) {
HighlightsUpdating = false;
if (HighlightsContentChanged != null) {
HighlightsContentChanged( this, eventArgs );
}
}
// Constructors
public HighlightsObjectHandler() {
Highlights = new List<HighlightObject>();
}
}
How would I make a copy of this in Java?
I somewhat understand that I need to create an interface that would hold the 3 EventHandlers that I have in this code. Then, I would have to implement that interface in the class. Let's assume that the class would have the exact same name and the result would be something like this:
public class HighlightsObjectHandler implements SomeListener { ... }
But, from what I see from tutorials and forums, they would fire, for instance, the HighlightsContentChanging directly instead of calling the OnHighlightsContentChanging ( where I would like to set a variable - HighlightsUpdating - to a value and then calling the listeners associated with the event ).
And there is where I'm losing my mind. How would I make this happen? In the Windows Phone app, that variable would help me whenever a page that had this content in it to set the page as loading or to display a message if the page has nothing to show.
UPDATE:
I've managed to create the code I as able to, or had acknowledge to. I'll leave here the code so far:
package com.example.nlsonmartins.myapplication.Highlights;
import java.util.ArrayList;
import org.json.*;
public class HighlightsObjectHandler {
// Constants
private final String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Enumerators
// Handlers
// Variables
private String
_json;
private Boolean
_updating;
private ArrayList<HighlightObject>
_highlights;
// Properties
public String HighlightsJson() {
return _json;
}
public void HighlightsJson(String highlightsJson) {
// Validate the json. This cannot be null nor equal to the present one ( to prevent firing events on the same data )
if(highlightsJson != _json && highlightsJson != null) {
_json = highlightsJson;
// Fire the Java equivalent of C# 'OnHighlightsJsonChanged( EventArgs.Empty );'
ParseJson();
}
}
public Boolean HighlightsUpdating() {
return _updating;
}
private void HighlightsUpdating(Boolean isUpdating) {
_updating = isUpdating;
}
public ArrayList<HighlightObject> Highlights() {
return _highlights;
}
// Methods
private void ParseJson() {
try {
JSONObject
jsonObject = new JSONObject(HighlightsJson());
// Fire the Java equivalent of C# 'OnHighlightsContentsChanging( EventArgs.Empty );'
// Parse the JSON object
// Fire the Java equivalent of C# 'OnHighlightsContentsChanged( EventArgs.Empty );'
} catch (JSONException exception) {
}
}
// Events
/* Create the event handler for 'OnHighlightsJsonChanged' */
/* Create the event handler for 'OnHighlightsContentsChanging' and call the 'HighlightsUpdating(true);' method */
/* Create the event handler for 'OnHighlightsContentsChanged' and call the 'HighlightsUpdating(false);' method */
// Constructors
public HighlightsObjectHandler() {
_highlights = new ArrayList<HighlightObject>();
}
}
I don't have an equivalent for the 'JsonObject' type, but other than that I think the following may work for you, using your own custom EventHandler functional interface, custom EventArgs class, and generic 'Event' helper class:
import java.util.*;
public class HighlightsObjectHandler
{
// Constants
private static final String JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Handlers
public Event<CustomEventHandler> HighlightsJsonChanged = new Event<CustomEventHandler>();
public Event<CustomEventHandler> HighlightsContentChanging = new Event<CustomEventHandler>();
public Event<CustomEventHandler> HighlightsContentChanged = new Event<CustomEventHandler>();
// Variables
private String _json;
// Properties
public final String getHighlightsJson()
{
return _json;
}
public final void setHighlightsJson(String value)
{
if (!_json.equals(value) && value != null)
{
_json = value;
OnHighlightsJsonChanged(CustomEventArgs.Empty);
ParseJson();
}
}
private boolean HighlightsUpdating;
public final boolean getHighlightsUpdating()
{
return HighlightsUpdating;
}
private void setHighlightsUpdating(boolean value)
{
HighlightsUpdating = value;
}
private ArrayList<HighlightObject> Highlights;
public final ArrayList<HighlightObject> getHighlights()
{
return Highlights;
}
private void setHighlights(ArrayList<HighlightObject> value)
{
Highlights = value;
}
// Methods
private void ParseJson()
{
//todo: no equivalent to 'JsonObject':
JsonObject jsonObject = null;
//todo: no equivalent to 'out' parameter:
if (JsonObject.TryParse(HighlightsJson, jsonObject))
{
OnHighlightsContentChanging(CustomEventArgs.Empty);
// Json parsing and other stuff...
// ... it shouldn't matter for this question.
OnHighlightsContentChanged(CustomEventArgs.Empty);
}
}
// Events
public final void OnHighlightsJsonChanged(CustomEventArgs eventArgs)
{
if (HighlightsJsonChanged != null)
{
for (CustomEventHandler listener : HighlightsJsonChanged.listeners())
{
listener.invoke(this, eventArgs);
}
}
}
public final void OnHighlightsContentChanging(CustomEventArgs eventArgs)
{
setHighlightsUpdating(true);
if (HighlightsContentChanging != null)
{
for (CustomEventHandler listener : HighlightsContentChanging.listeners())
{
listener.invoke(this, eventArgs);
}
}
}
public final void OnHighlightsContentChanged(CustomEventArgs eventArgs)
{
setHighlightsUpdating(false);
if (HighlightsContentChanged != null)
{
for (CustomEventHandler listener : HighlightsContentChanged.listeners())
{
listener.invoke(this, eventArgs);
}
}
}
// Constructors
public HighlightsObjectHandler()
{
setHighlights(new ArrayList<HighlightObject>());
}
}
#FunctionalInterface
public interface CustomEventHandler
{
void invoke(object sender, CustomEventArgs e);
}
public class CustomEventArgs
{
public static readonly CustomEventArgs Empty;
public CustomEventArgs()
{
}
}
//this is produced as a helper class by C# to Java Converter:
public final class Event<T>
{
private java.util.Map<String, T> namedListeners = new java.util.HashMap<String, T>();
public void addListener(String methodName, T namedEventHandlerMethod)
{
if (!namedListeners.containsKey(methodName))
namedListeners.put(methodName, namedEventHandlerMethod);
}
public void removeListener(String methodName)
{
if (namedListeners.containsKey(methodName))
namedListeners.remove(methodName);
}
private java.util.List<T> anonymousListeners = new java.util.ArrayList<T>();
public void addListener(T unnamedEventHandlerMethod)
{
anonymousListeners.add(unnamedEventHandlerMethod);
}
public java.util.List<T> listeners()
{
java.util.List<T> allListeners = new java.util.ArrayList<T>();
allListeners.addAll(namedListeners.values());
allListeners.addAll(anonymousListeners);
return allListeners;
}
}
import java.util.*;
interface HelloListener
{ void someoneSaidHello();}
NOTE
I'm going to have this StackOverflow answer as a base for what I'm going to explain in this answer.
Okay, so, for what I could read and understand, it isn't that much different building C#-like events in Java ( or, in another point of view, it isn't that hard from someone who develops in C# to build events in Java ).
First, from my perspective, I'd like to point that the way I build the events in Java are almost a copy-paste from C# ( maybe it's the correct way to do it, maybe it isn't ).
Second, I'm going to - hopefully - put this in a way people might understand ( based on tutorials I saw here on StackOverflow and other sites ):
The events on C# are wrapped in a method that is set as internal - usually the OnSomethingChanging or OnSomethingChanged - whereas the Java events are not. Imagine this method in Java:
List<HelloListener> listeners = new ArrayList<HelloListener>();
public void sayHello() {
System.out.println("Hello!!");
// Notify everybody that may be interested.
for (HelloListener hl : listeners)
hl.someoneSaidHello();
}
Now, to make it more C# like, I would to make it like this:
public event EventHandler HelloListener;
public void SayHello() {
Console.WriteLine("Hello!!");
// Notify everybody that may be interested.
if(HelloListener != null) {
HelloListener(this, EventArgs.Empty);
}
}
Basically I was expecting to have to make an OnHelloListener method, then trigger the events on that very method but, on the majority of examples and tutorials that I saw, they would do something like I wrote above. That was what was messing my head really badly ( and probably others too if they come from C# to Java ).
In conclusion
If I was to translate the HighlightsObjectHandler class from C# to Java - and keeping the C# soul in it - I would end with something like this:
public class HighlightsObjectHandler {
// Constants
private final String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Enumerators
// Handlers
private List<HighlightsListener>
_highlightsListeners = new ArrayList<HighlightsListener>();
// Variables
private String
_json;
private Boolean
_updating;
private List<HighlightObject>
_highlights;
// Properties
public String HighlightsJson() {
return _json;
}
public void HighlightsJson(String highlightsJson) {
// Validate the json. This cannot be null nor equal to the present one ( to prevent firing events on the same data )
if (!highlightsJson.equals(_json) && highlightsJson != null) {
_json = highlightsJson;
OnHighlightsJsonChanged();
ParseJson();
}
}
public Boolean HighlightsUpdating() {
return _updating;
}
private void HighlightsUpdating(Boolean isUpdating) {
_updating = isUpdating;
}
public List<HighlightObject> Highlights() {
return _highlights;
}
// Methods
private void ParseJson() {
if (HighlightsUpdating()) {
return;
}
try {
OnHighlightsContentsChanging();
// Parse the JSON object
OnHighlightsContentsChanged();
} catch (JSONException exception) {
}
}
// Events
private void OnHighlightsJsonChanged() {
for(HighlightsListener highlightsListener : _highlightsListeners) {
highlightsListener.HighlightsJsonChanged();
}
}
private void OnHighlightsContentsChanging() {
HighlightsUpdating(true);
for(HighlightsListener highlightsListener : _highlightsListeners) {
highlightsListener.HighlightsContentChanging();
}
}
private void OnHighlightsContentsChanged() {
HighlightsUpdating(false);
for(HighlightsListener highlightsListener : _highlightsListeners) {
highlightsListener.HighlightsContentChanged();
}
}
// Constructors
public HighlightsObjectHandler() {
_highlights = new List<HighlightObject>();
}
}
Once again, my problem was basically me expecting to have to create the OnSomethingChanged methods that would trigger the events and not the code directly placed on the methods when I want them to be triggered.
You could say that I was an app that was crashing when you typed this while expecting you to type that.
Java to C#
WARNING If you're easily confused or you're still trying to understand this, I recommend you to not read this part of the answer. This is just an for fun and curiosity block that I found somewhat funny and interesting...
So, let's say that my problem was the opposite that is now, I had a Java class with events and would like to translate it to C#. From what I know to this point I would end with something like this in C#:
public class HighlightsObjectHandler {
// Constants
private const String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Enumerators
// Handlers
public event EventHandler HighlightsJsonChanged;
public event EventHandler HighlightsContentChanging;
public event EventHandler HighlightsContentChanged;
// Variables
private String
_json;
// Properties
public String HighlightsJson {
get {
return _json;
}
set {
if (value != _json && value != null) {
_json = value;
if (HighlightsJsonChanged != null) {
HighlightsJsonChanged( this, eventArgs );
}
ParseJson();
}
}
}
public Boolean HighlightsUpdating { get; private set; }
public List<HighlightObject> Highlights { get; private set; }
// Methods
private void ParseJson() {
JsonObject
jsonObject;
if (JsonObject.TryParse( HighlightsJson, out jsonObject )) {
HighlightsUpdating = true;
if (HighlightsContentChanging != null) {
HighlightsContentChanging( this, eventArgs );
}
// Json parsing
HighlightsUpdating = false;
if (HighlightsContentChanged != null) {
HighlightsContentChanged( this, eventArgs );
}
}
}
// Events
// Constructors
public HighlightsObjectHandler() {
Highlights = new List<HighlightObject>();
}
}
Note how instead the OnHighlightsJsonChanged and the other internal methods are removed and, instead of having the code I had on the methods they are instead where I called the methods.
P.S.: I will mark this answer as the answer to the this question on the next Monday so I can see others answers and select one of them if they fit more as a final answer.

Tika - Is it possible to get the id attribute of a div tag?

Is it possible to filter what tika parses by the id attribute of div tags in the html?
I am trying to filter out divs with the id "header" because all the pages i am parsing have the same header and I only need the unique data.
I have already triggered the ContentHandler.StartElement for the div tags:
class MyHtmlMapper extends DefaultHtmlMapper {
public String mapSafeElement(String name) {
if ("DIV".equals(name)) {
return "div";
}
return super.mapSafeElement(name);
}
}
And I create the parser with the following:
InputStream urlInput = new URL(url).openStream();
Parser parser = new AutoDetectParser();
Metadata metadata = new Metadata();
ContentHandler handler = new BodyContentHandler();
ParseContext context = new ParseContext();
context.set(HtmlMapper.class, new MyHtmlMapper());
So I am assuming I have to override the BodyContentHandler.startElement() and BodyContentHandler.endElement() methods in the data handler (Something like the following):
class MyContnentHandler extends BodyContentHandler{
public void startElement(String uri, String name, String element, Attributes atri) {
...
super.startElement(...)
}
public void endElement(...)
... //Similar to above
}
}
I've been working on this for a little while and I'm just not terribly familiar with tika. If anyone has any suggestions or solutions they'd be greatly apprecieated!
I later learned that I could make the attributes (i.e. id and class) show up in startElement by overriding the mapSafeAttribute method in the MyHtmlMapper class as follows:
class MyHtmlMapper extends DefaultHtmlMapper {
public String mapSafeElement(String name) {
if ("DIV".equals(name)) {
return "div";
}
return super.mapSafeElement(name);
}
public String mapSafeAttribute(String eleName, String attrName) {
HashSet<String> safeAttrs = new HashSet<String>();
safeAttrs.add("id");
safeAttrs.add("class");
if (safeAttrs.contains(attrName) && eleName.equals("div")) {
return attrName;
} else {
return super.mapSafeAttribute(eleName, attrName);
}
}
}
But I still cannot figure out how to stop the parser from parsing up the things in-between the start and end tag of the with a given attribute property.
Let me know if I've left out any information that would be useful.
class MyHtmlMapper extends DefaultHtmlMapper {
public public boolean isDiscardElement(String name) {
//put here not wanted attributes
HashSet<String> discardAttrs = new HashSet<String>();
if (discardAttrs.contains(name) && eleName.equals("div")) {
return true;
}
return false;
}
)
http://tika.apache.org/1.2/api/index.html?org/apache/tika/parser/html/HtmlParser.html

Categories

Resources