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
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
}
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!
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");
}
}
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.
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