宣传一下黄老大的ET2项目

我曾经的supervisor黄老大开发了一个功能十分强大的Eclipse Toolkit,提供了一些Eclipse应用程序经常需要用到的组件,如高度可定制的表格控件等等,是对目前SWT/JFace/GEF的扩展和增强。

Here is the link: http://sourceforge.net/projects/eclipsetoolkit2/.
An old link is http://www.cs.umb.edu/~huangjun/.

I release all files under epl v1.0.

Sorry for bare documents and samples coz mid-term is coming! I will try my
best to make up.

I do believe there are many ways to impl such stuffs and I am not sure my
way is good enough. I am open to any comments. Thanks for your attention!”

file

用Jena获得本体的缺省名称空间

这个标题其实有点问题,因为本体/RDF本身并没有名称空间的概念,它们只关心绝对的URI;在Jena里一旦模型读进内存,就都是使用绝对URI标识资源的,而当使用xml格式存储的时候,才会引出这些xml中的概念。

最近遇到一个问题,在一个程序里要读取多个xml格式的本体文件(*.owl),它们之间有import关系,在读一个文件之前,我需要先确认该文件需要import的那些名称空间所对应的本体(此本体的缺省名称空间是import的值)是否存在,所以我必须知道每个.owl文件的缺省名称空间和import值(后者在这里暂不讨论),这样做的一个好处是不需要让Jena在找不到本地文件时去访问网络,造成延迟。

虽然Jena API没有提供直接得到它的方法,从一个.owl文件得到缺省名称空间的方法其实很简单,但com.hp.hpl.jena.shared.PrefixMapping接口有一个getNsPrefixURI()方法,利用它可以得到xml文档中每个prefix对应的名称空间。

什么是前缀(prefix)呢?prefix主要是为了简化xml的书写,例如下面的语句中,rdf就是prefix,这样在xml文档的其他地方就可以用"rdf:xxx"表示"http://www.w3.org/1999/02/22-rdf-syntax-ns#xxx"这一长串了。

xmlns:rdf="[http://www.w3.org/1999/02/22-rdf-syntax-ns](http://www.w3.org/1999/02/22-rdf-syntax-ns)#"

有了这个方法,我们就可以得到rdf、owl、xsd等前缀对应的名称空间,而缺省名称空间对应的前缀是空字符串(""),因此使用model.getNsPrefixURI(""),而OntModel对象是实现PrefixMapping接口的。

当然,要得到一个xml文件的缺省名称空间有很多方法,只是在一个面向本体而不是xml的应用程序里,使用本体这个层次的API可能更合适一些。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2005/03/16/119960.html

利用winrar自动备份重要资料(续,经验技巧)

以前帖子里说过用Winrar自动备份资料的方法,我现在平均每周备份两次,备份的内容包括日程(Rainlendar)、RSS频道(Rssowl)、Eclipse里的项目、常用IP设置、Outlook Express内容等等,压缩下来大约150M左右,其中主要是(带附件的)信件和项目文件占了大部分空间。

今天发现Eclipse里的一个CVS设置给搞错了,连接的是旧的CVS服务器,我在Eclipse里把服务器的地址改过来再进行Update操作,结果把我之后做的几处修改都覆盖了。还好我昨天晚上刚做了备份,这几天的工作没有白费。

类似这样的意外事件很难预料,事先做好充足的预防工作让我们有备无患,而付出的只是每周几分钟的时间,利当然远远大于弊。

关于Winrar备份我又总结了几条经验:首先可以设计两个备份任务,一个是全面备份,一个是快速备份,一些体积比较大又不是特别重要的不需要经常备份,平时每天进行快速备份,每周或每月全面备份一次就可以了;其次,在命令行里加上-ag参数可以让备份得到的压缩包文件名自动包含当前日期,从而不会覆盖掉以前的备份,该参数还可以指定日期格式,如YYYY-MM-DD等;另外,用-ms参数可以不对已经被压缩过的文件再次压缩,而是直接存放;最后,用-x命令可以排除一些我们不希望备份的文件,比如*.jar文件,一般都可以下载得到。我现在用的备份命令如下,其中backup-q.txt的内容是要备份文件的列表,得到的压缩包名像BAK20050223.rar这样:

"C:\Program Files\WinRAR\WinRAR.exe" a -agYYYYMMDD -ms -x*.jar -ep2 -ibck -t c:\backup\BAK.rar @c:\backup\backup-q.txt

这里要提醒一下,备份的文件最好定期转移到本地硬盘以外的存储地点,比如刻成光盘保存,还是不要过于相信硬盘了。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2005/02/23/108272.html

解决高分辨率看网页字体太小问题的一个方法

有些笔记本电脑或LCD显示器的最佳分辨率大于1024x768,例如SXGA+的1400x1050,我们一般会在Windows的显示选项里设置使用大字体,以便更容易阅读。但是IE浏览器缺省是使用96DPI分辨率来显示的,且不允许用户在选项里选择使用自定义的分辨率,所以看很多网页时字体会变得很小以至于影响阅读。

以前有一个办法是在IE选项的辅助功能里设置IE“不使用网页指定的字体大小”,然后就可以在查看菜单里选择自己想要的文字大小(较小、中、较大等等),但这只是文字的放大,会让那些格式比较复杂的页面变得极其混乱,比如新浪网。

我今天在网上找到一个相比起来更好些的方法,原文在MSDN上,其实只要在注册表里加一项就可以让IE使用我们设置的DPI了,这样的好处是页面会整体放大,不会对版式造成任何影响;问题有两个,一是因为图片被放大了所以能看出轻微的锯齿,二是更改设置后要重开IE才能看到效果。

我做了两个注册表片断,直接双击即可导入,其中一个是让IE使用自定义DPI,另一个是恢复为缺省设置(使用96 DPI),这里下载

有需要的朋友不妨试试,注意导入后一定要重开IE才能看到效果。

file
图1 1400x1050分辨率下96DPI的IE

file
图2 1400x1050分辨率下自定义为130DPI的IE

让URLConnection使用代理服务器

JDK的文档对使用代理服务器的介绍很少,据说JDK5.0好象增加了这方面的内容。其实要使用代理服务器很简单,只要在URL.openConnection()之前增加下面的代码即可:

Properties prop = System.getProperties(); 
prop.put("http.proxyHost", getProxyHost()); 
prop.put("http.proxyPort", "" + getProxyPort());

也就是给系统变量里增加了两个项,在执行程序时加上参数“-Dhttp.proxyHost=xxx”的效果也是一样的。

若代理服务器需要验证,则还要使用以下代码:

String authentication = getProxyUser() + ":" + getProxyPassword(); 
String encodedLogin = new sun.misc.BASE64Encoder().encodeBuffer(authentication.getBytes()); 
connection.setRequestProperty("Proxy-Authorization", "Basic " + encodedLogin);

也就是在Http头上增加了Proxy-Authorization信息。

更多属性:http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2005/01/11/90236.html

[Eclipse]PreferencePage的小问题花了大把时间

在Eclipse里可以用FieldEditorPreferencePage简化Preference page的创建,但在随机文档里只重点说了要实现createFieldEditors方法,我明明实现了它,但点Preference命令时却总是提示:

java.lang.InstantiationException: org.haree.mobject.ui.BasicPreferencePage
    at java.lang.Class.newInstance0(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:141)
    at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:124)
    at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:113)
    at org.eclipse.ui.internal.WorkbenchPlugin.createExtension(WorkbenchPlugin.java:189)
    at org.eclipse.ui.internal.dialogs.WorkbenchPreferenceNode.createPage(WorkbenchPreferenceNode.java:60)
    at org.eclipse.jface.preference.PreferenceDialog.showPage(PreferenceDialog.java:985)
    at org.eclipse.jface.preference.PreferenceDialog$8.selectionChanged(PreferenceDialog.java:529)
    at org.eclipse.jface.viewers.StructuredViewer$3.run(StructuredViewer.java:450)
    at org.eclipse.core.internal.runtime.InternalPlatform.run(InternalPlatform.java:616)
    at org.eclipse.core.runtime.Platform.run(Platform.java:747)
    at org.eclipse.jface.viewers.StructuredViewer.firePostSelectionChanged(StructuredViewer.java:448)
    at org.eclipse.jface.viewers.StructuredViewer.setSelection(StructuredViewer.java:1094)
    at org.eclipse.jface.preference.PreferenceDialog.selectSavedItem(PreferenceDialog.java:807)
    at org.eclipse.jface.preference.PreferenceDialog$3.run(PreferenceDialog.java:309)
    at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:69)
    at org.eclipse.jface.preference.PreferenceDialog.createContents(PreferenceDialog.java:305)
    at org.eclipse.jface.window.Window.create(Window.java:348)
    at org.eclipse.jface.dialogs.Dialog.create(Dialog.java:925)
    at org.eclipse.ui.internal.OpenPreferencesAction.run(OpenPreferencesAction.java:70)
    at org.eclipse.jface.action.Action.runWithEvent(Action.java:881)
    at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:915)
    at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:866)
    at org.eclipse.jface.action.ActionContributionItem$7.handleEvent(ActionContributionItem.java:785)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:82)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:796)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:2772)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2431)

找了一个多小时,才发现原来是要提供一个没有参数的构造方法才可以。想了一下,可能因为Eclipse最终是使用Class.newInstance()的方式来生成界面元素的,所以有这个要求。

算是一个经验吧,我觉得Eclipse的帮助再丰富些就好了,特别是应该提供更多的例子代码。

顺便推荐下面两篇文章(要是Eclipse帮助都这么详细该多好):

Mutatis mutandis - Using Preference Pages as Property Pages

Simplifying Preference Pages with Field Editors

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2005/01/11/90073.html

用正则表达式处理含中文字符串的问题

已经是第二次遇到同样的问题了,要匹配的字符串里含有中文,例如“<你好><Edward>”,我希望取出Edward的名字,所以正则表达式为“<[^>]><([^>])>”,匹配后只要取group(1)即可。在一台装有jdk1.4.2_06国际版的机器上,运行正常,但在装jdk1.4.2_01的机器上,则完全不能匹配。卸载原来的jdk,换成1.4.2_06版就没有问题了。

为什么会有这个区别呢,我试了增加各种参数例如-Duser.language=zh -Duser.region=cn -Dfile.encoding=GBK都没有用,难道我的程序要求用户机器上必须装最新的jdk1.4?但据我所知,还有很多机器上装的是jdk1.4.0呢,更别说jdk5.0了。

时间关系,这个问题暂时放在这里,欢迎提供解决方法。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2005/01/07/88414.html

在应用程序中利用Jena API处理OWL本体

接触Semantic Web的时间还不是很长,所以现在写的这方面内容算是笔记性质,很可能存在很多误解,欢迎指出或讨论:)

一般来说,我们在Protege这样的编辑器里构建了本体,就会想在应用程序里使用它,这就需要一些开发接口。用程序操作本体是很必要的,因为在很多情况下,我们要自动生成本体,靠人手通过Protege创建所有本体是不现实的。Jena是HP公司开发的这样一套API,似乎HP公司在本体这方面走得很靠前,其他大公司还在观望吗?

可以这样说,Jena对应用程序就像Protege对我们,我们使用Protege操作本体,应用程序则是使用Jena来做同样的工作,当然这些应用程序还是得由我们来编写。其实Protege本身也是在Jena的基础上开发的,你看如果Protege的console里报异常的话,多半会和Jena有关。最近出了一个Protege OWL API,相当于对Jena的包装,据说使用起来更方便,这个API就是Protege的OWL Plugin所使用的,相信作者经过OWL Plugin的开发以后,说这些话是有一定依据的。

题目是说用Jena处理OWL,其实Jena当然不只能处理OWL,就像Protege除了能处理OWL外还能处理RDF(S)一样。Jena最基本的使用是处理RDF(S),但毕竟OWL已经成为W3C的推荐标准,所以对它的支持也是大势所趋。

好了,现在来点实际的,怎样用Jena读我们用Protege创建的OWL本体呢,假设你有一个OWL本体文件(.owl),里面定义了动物类(http://www.zoo.com/ont/Animal,注意这并不是一个实际存在的URL,不要试图去访问它),并且它有一些实例,现在看如下代码:

OntModel m = ModelFactory.createOntologyModel();
File myFile = ...;
m.read(new FileInputStream(myFile), "");
ResIterator iter = m.listSubjectsWithProperty(RDF.type, m.getResource("http://www.zoo.com/ont/Animal"));
while (iter.hasNext()) {
    Resource animal = (Resource) iter.next();
    System.out.println(animal.getLocalName());
}

和操作RDF(S)不同,com.hp.hpl.jena.ontology.OntModel是专门处理本体(Ontology)的,它是com.hp.hpl.jena.rdf.model.Model的子接口,具有Model的全部功能,同时还有一些Model没有的功能,例如listClasses()、listObjectProperties(),因为只有在本体里才有“类”和“属性”的概念。

上面的代码很简单,从ModelFactory创建一个OntModel,从指定文件把模型读到内存里。再下面的代码是一个例子,作用是取出模型中所有Animal的实例(Individual,也叫个体),并打印它们的名称。要从OntModel里取实例,也可以用listIndividuals()方法,只不过你得在得到的实例中判断它们是不是Animal的实例,我觉得不如用上面这种简易查询的方式来得方便。

Jena里扩展了很多Iterator,比如ResIterator、StmtIterator和NodeIterator等等,刚开始用会觉得很别扭,好象还不如都用java标准的Iterator,不知道Jena的设计者是怎么考虑的。要熟练掌握还是得对整个Jena的API有全局掌握才好。

在循环里,我们得到的每个元素都是一个Resource,因为本体里的任何东西都是资源,不论你想得到Subject、Property还是Object,在Jena里实际得到的都是资源(Resource),在Jena里,Property是Resource的子接口,而Jena并没有Subject或Object接口。(注:在OWL本体中,Subject->Property->Object组成一个三元组,例如:张小刚->父亲->张大刚;或者:绵羊多利->rdf:type->动物,rdf:type是一个特殊的属性,表示前者是后者的实例)

暂时先写到这,关于在本体中引入其他本体和使用推理,下次继续。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2005/01/06/87598.html

利用winrar自动备份重要资料

每个人的电脑上都有很多有价值的资料,例如你写的论文、Outlook中的信件、IE收藏夹、FeedDemon中的rss链接等等,经常备份的重要性自不用多说,但怎样让备份变为轻松简单而不是繁重的劳动呢,我在网上查找了很多备份工具,发现它们要么很贵,要么存在各种缺陷(如不使用通用的压缩格式),后来发现其实只使用winrar就完全可以完成这个任务,而大部分人的电脑上都有这个压缩软件。

打开winrar的帮助主题,你会发现在winrar的命令行模式里可以指定很多参数,其格式为:

WinRAR  <command> -<switch1> -<switchN> <archive> <files> <@listfiles> <path_to_extract\>

利用winrar可以从列表文件中读取要压缩的文件/文件夹这个功能,我们可以创建一个列表文件如C:\backup.txt,在这个文件里写入需要备份的文件/文件夹路径,格式很简单,每个路径一行即可。然后创建一个快捷方式(或批处理文件),其命令为:

"C:\Program Files\WinRAR\WinRAR.exe" a C:\backup.rar @C:\backup.txt

要进行备份的时候只要执行这个命令即可,这样会在C:生成备份后的压缩文件,你最好把它转移到其他存储装置上。配合windows的计划任务,还可以进行定时自动备份。你还可以指定其他参数,例如加上-ibck可以让备份在后台执行,加上-t参数可以在压缩完成后验证等等,具体请参考winrar帮助主题。

这个方法的缺点是你必须自己找出那些需要备份的信息,有一些软件把信息存在注册表里不好备份,所以你可能需要在使用这种方式备份的同时手动备份注册表。不过很多专门用于备份的工具也是没有这个功能的。

Update:经验技巧

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2004/12/28/82975.html