alartin's profileWindows Live 共享空间PhotosBlogListsMore Tools Help

Blog


    26 October

    IkeWiki: 协同知识管理的语义Wiki (3)

    4 IkeWiki
    A number of semantic wiki systems are currently under
    development.7 In the following, we introduce one such system
    called IkeWiki. Like “wiki”, the name is derived from
    Hawaiian and can be translated as “fast knowledge”.


    4.1 Design Principles
    Although now also considered in different settings,
    IkeWiki has originally been developed as a prototype tool
    to support knowledge workers in collaboratively formalising
    knowledge [4]. IkeWiki’s design principles are influenced
    by this idea, but equally hold in other areas:


    Easy to Use, Interactive Interface. As domain experts
    are usually non-technical people, ease of use is of big
    importance. Therefore, IkeWikis interface resembles as
    closely as possible theWikipedia interface which people are
    familiar with. Also, IkeWiki offers an interactive WYSIWYG
    editor (using AJAX technology to communicate with
    the server backend) in addition to the traditional structured
    text editor, as WYSIWYG editors generally have a better
    acceptance among non-technical users. The WYSIWYG
    editor also supports interactive typing of links and
    resources.
    At the same time, IkeWiki offers all the normal editing
    interfaces (supporting Wikipedia-style structured text) for
    more experienced users.


    Compatibility with Wikipedia/MediaWiki. A significant
    amount of “informal” knowledge is available in
    Wikipedia. To reuse this knowledge, IkeWiki supports the

    Wikipedia syntax. This allows users to import existing content
    from Wikipedia into IkeWiki (e.g. via simple copy and
    paste) and begin with semantic annotations straight away.

    能够和其他应用程序交换数据,例如本体编辑器,语义Web服务,其他Wiki等。
    Compatibility with Semantic Web standards. To be
    able to exchange data with other applications (e.g. ontology
    editors, Semantic Web services, other wikis), IkeWiki
    is purely based on existing Semantic Web standards like
    RDF and OWL. Note that other knowledge representation
    formats like conceptual graphs are conceivable but not investigated
    at this point.

    即刻开发和发布语义注释
    Immediate Exploitation of Semantic Annotations. An
    important motivating aspect of wiki systems is that content
    is immediately available to the public when a user clicks on
    “save”. Similarly, IkeWiki allows immediate exploitation
    of semantic annotations for enhanced editing, presentation,
    navigation, and searching, even if the knowledge base is not
    yet fully formalised.

    支持不同级别的经验
    Support for Different Levels of Experience. IkeWiki is
    designed as a tool for collaborative knowledge engineering.
    In such a process, it is common that non-technical
    domain experts work together with experienced knowledge
    engineers. Therefore, IkeWiki supports all levels of experience.
    This means that certain advanced functionalities can
    be hidden from novice users but are available to experienced
    users.

    支持不同级别的正式化
    Support for Different Levels of Formalisation. Different
    application areas need different levels of formalisation
    [4], and as Jim Hendler said:8 “a little semantics goes a long
    way”. One of the goals of IkeWiki is thus to support formalisation
    of knowledge all the way from informal texts to
    formal ontologies. Also, this means that parts of the knowledge
    base might be more formalised than others, and that
    formal knowledge is in constant evolution.

    支持推理,目前只支持OWL-RDFS推理
    Support for Reasoning. Unlike most other semantic
    wikis, IkeWiki supports reasoning on the knowledge base.
    We consider reasoning important as it allows to derive
    knowledge that is not explicit in the data and is thus the
    true power of Semantic Web technology. At the moment,
    IkeWiki supports only OWL-RDFS reasoning, but an extension
    with a user-accessible rule engine is planned.

    4.2 Architecture

     

    IkeWiki is implemented as a Java web application using
    a layered architecture shown in Figure 1. Data is stored in a

    Postgres database. When a resource is requested, the XML
    page content and related RDF data are retrieved and combined
    in the RenderingPipeline into an enriched XML representation.
    This XML representation is then either offered
    as interchange format for otherWeb services or transformed
    into HTML for presentation in the user’s browser. The individual
    layers are described in more detail in the following:

    页面内容的存储,支持版本和重建,使用WIF格式
    Page Store. The page store component serves to store and
    retrieve page content from the database. It also supports versioning
    and restoring of previous revisions. Page content
    is represented in structured text as well as an XML format
    we call WIF (wiki interchange format). Basic WIF merely
    describes the page content and structure, but allows to add
    custom, application specific information in separate namespaces.
    We have proposed WIF as a format for interchange
    of page content between arbitrary wiki systems.

    RDF存储,知识库通过Jena的RDF框架展示。IkeWiki使用内存模型来保证系统的响应度。内存模型常常和数据库模型同步。部分RDF存储是一个SPARQL引擎,允许查询知识库。


    RDF Store. The knowledge base is represented using the
    Jena RDF framework.9 IkeWiki uses an in-memory model
    to ensure responsiveness of the system. The in-memory
    model is frequently synchronised with a database model for
    persistent storage. Part of the RDF store is a SPARQL engine
    that allows for searching of the knowledge base.

    绘制管道将页面内容和语义注释结合起来,输出是WIF文档,包含相关的语义注释(例如连接类型,上下文适配),文档是RXR格式的。文档由很多Wiklet组成,每个Wiklet向WIF文档添加特定的信息片段。Wiklet可以根据权限来设置用户是否可以访问,从而控制不同用户的视图。


    Rendering Pipeline. The Rendering Pipeline combines
    page content with semantic annotations. Its output is a WIF
    document enriched by relevant semantic annotations (e.g.
    link types, context adaptation) in RXR format [2]. The
    “pipeline” consists of small steps we call “wiklets”. Each
    wiklet adds a specific piece of information to the WIF document.
    Wiklets can be enabled and disabled and associated
    with permissions so that only selected users can see
    the added information.

     

    Transformation, Servlet. The transformation layer applies
    XSLT transformations to the enriched WIF format to
    generate XHTML, SVG, and/or WIF output. The IkeWiki
    servlet then serves this output to the user’s browser.

    4.3 Interface 界面
    IkeWiki uses a purely browser-based interface (cf. Figure
    2). The current implementation only supports the
    Mozilla browser family due to its standards compliance and
    free availability.

    例子:生物学越桔(Bilberry)的页面。

    Page View. A sample page view is shown in Figure 2.
    In the figure, you can see a sample article (copied from
    Wikipedia) about the “Bilberry”.

    页面的类型信息在标题下方:Types:  skoes:Concept - rdfs:Resource

    Type information is shown below the page title (1).

    语义相关的页面在页面右侧单独的引用框(Reference Box)内显示。

     Links to (semantically) related pages are displayed in a separate “references box” on
    the right hand side (2).

    分类框显示生物学分类:越桔的科学分类,纲:双子叶(Magnoliopsida), 科:杜鹃花科(Ericaceae),属: 越桔属(Vaccinium)。注意:这是根据知识库中已经存在的语义注释自动生成的(例如,越桔 具有属 越桔属),这个分类显示了上下文适配功能。

    The taxonomy box (3) showing the biological classification of the described plant is automatically
    generated from existing semantic annotations (i.e. Bilberry
    hasGenus Vaccinium) and is an example for context
    adaptation.

    最后我们可以用AJAX技术表现交互的连接注释功能。

    Finally, (4) shows interactive typing of links using
    AJAX technology.

    内容编辑器有两种选择:传统的Wiki文本输入和所见即所得的编辑器
    Content Editor. The content editor is available in two
    flavours: as a traditional structured text editor and as a
    WYSIWYG editor. The structured text editor is aimed at
    expert users that are familiar with other wiki systems, and
    allows to directly copy content fromWikipedia. The WYSIWYG
    editor is aimed at novice users creating new content.
    The WYSIWYG editor interacts with the server backend:
    links are automatically recognised and verified, and semantic
    annotations can be done directly in the editor (as also
    shown in Figure 2, (4)).

    语义注释编辑器。语义注释分为三个编辑器:元数据编辑器允许输入和这个页面相关的文本元数据(就像Dublin Core元数据或者RDF Comment类似)。类型编辑器允许将系统中一个或者多个类型和这个页面相关联。连接编辑器允许通过类型信息注释出去(outgoing)和进入(incoming)的连接。在编辑器中,可以获得的注释是由基于页面和连接类型的推理器决定的。例如,一个从莫扎特页面到安魂曲页面的连接被注释为”是...的创作者“,系统自动将”创作者“这个类型和莫扎特页面相关联。用户无法直接删除这个类型。
    Semantic Annotations Editor. Semantic annotations are
    separated into three editors: the metadata editor allows to
    fill in textual metadata related to a page (like Dublin Core
    metadata or RDF comments). The type editor allows to associate
    one or more of the types available in the system with
    a page. The link editor allows to annotate outgoing and incoming
    links with type information. In the editors, available
    annotations are determined by the reasoner based on the
    page and link types; for example, if a link from “Mozart”
    to “Die Zauberfl¨ote” is annotated by “composerOf”, the
    system will automatically associate the type “Composer”
    with the page describing “Mozart”, and this type cannot be
    deleted directly by the user.

    image

    IkeWiki: 协同知识管理的语义Wiki (4)

    语义Wiki使用的场景

    5 Semantic Wiki Usage Scenarios
    A wide range of application scenarios for semantic wikis
    are conceivable. In the following, we briefly present three
    areas that might benefit from semantic wikis,

    ontology engineering, 本体工程
    knowledge management, 知识管理

    and educational environments. 教育环境

    在本体工程中,领域专家和知识工程师一起工作,创建正式的本体论。语义Wiki能够很好的支持这个过程

    本体工程
    Ontology Engineering. In ontology engineering, domain
    experts and knowledge engineers work together to create a
    formal ontology. Semantic wikis can support this process
    very well:
    • non-technical domain experts are offered an easy way to enter their knowledge;非技术的领域专家能够容易的输入他们的知识
    • domain experts and knowledge engineers can collaboratively work on the ontology, each bringing their personal expertise; and 领域专家可以和知识工程师在本体论构建上协同工作,每个人都带来自己的专业

    • the knowledge can be formalised in an evolutionary process, beginning with informal texts. 知识可以在不断演变的过程中从不正式的文本变为正式化

    可以考虑一个历史学家想要创建一个关于莫扎特的语义门户。他开始就通过编辑器向语义Wiki中添加文本,图片,甚至语音内容,他也可以在内容间描述一些简单的关系。同时,他的语义网技术不太足够了,于是他叫来一个知识工程师。知识工程师不太清楚主题,可以先弄一些简单的关系,然后将它们正式化为一个本体,同时,这个历史学家可以继续向系统添加更多的内容。
    As an example, consider a historian who wants to create a
    semantic portal about Mozart. He begins filling the semantic
    wiki with texts, images, and maybe even audio content
    he has available via an easy to use editor. He can also describe
    simple relations between content. At some point, his
    experience in Semantic Web technologies does no longer
    suffice, so he brings in a knowledge engineer. The knowledge
    engineer – without in-depth knowledge of the topic
    – can take the simple relations and further formalise them
    e.g. to form an ontology. At the same time, the historian can
    continue filling the system with more content.

    知识管理
    Knowledge Management. In our knowledge-based
    economy, knowledge management is becoming more and
    more important. Knowledge management means easy and
    free authoring and content creation on the one hand (as one
    did on sticky notes, etc), and structuring knowledge for
    easy retrieval and for finding related information one was
    not aware of on the other hand. Also, sharing of knowledge
    is an important issue. While traditional wikis already support
    much of this, semantic wikis offer advanced searching
    and navigation capabilities as described above. They are
    therefore very well suited for knowledge management.
    Note that [6] describes in detail the application of semantic
    wikis for knowledge management.

    教育环境
    Educational Environments. In educational environments,
    semantic wikis can serve many different purposes.
    This paragraph focusses on two of them, content creation
    and learning.
    Content Creation. In today’s knowledge society,
    learning content needs to quickly adapt to the specific needs
    of learners (“just in time learning”). Creation of appropriate
    content is, however, usually a time consuming task. A
    semantic wiki can be very helpful for content creation. The
    wiki represents an easily modifiable “learning content pool”
    where content creators can author, search for, and recombine
    learning material to form learning content tailored towards
    the learner’s needs. Semantic annotations can be used
    to facilitate retrieval of related content, to “match” learning
    material in a course, and to create the structure for a new
    course, which can then be exported e.g. to SCORM.
    Learning. In constructivist and connectivist learning
    theories, users learn by constructing knowledge in their
    minds based on their experiences. Also, learning – especially
    of adults – is nowadays often at least partly selfdirected.
    Semantic wikis are a good tool to support such
    learning, as they allow learners to collect, connect, and
    structure information that they consider relevant, and to
    collaboratively collect and share information in a learning
    group. Also, they allow easy supervision/support by
    a coach.


    6 Related Work
    In the last year, a lot of semantic wiki systems with
    sometimes very different purposes and functionalities have
    been proposed, e.g. [6, 3, 1, 5]. The first such system was
    probably PlatypusWiki [5], which is focussed on the creation
    of RDF data. A constantly updated list of systems can
    be found at the SemanticWiki Interest Group website.10 As
    a response to the growing interest, the SemanticWiki workshop
    (SemWiki06), co-located with ESWC’06 in Budva,
    Montenegro, will take place for the first time.


    7 Perspectives and Conclusion
    In this article, we presented IkeWiki, a feature-rich semantic
    wiki system. Future directions for the development
    of IkeWiki might be to provide more support to knowledge
    engineers through linguistic processing techniques, identification
    of similar concepts through automated structure analysis,
    and guided questions based on underlying ontological
    knowledge. Also, it is intended to include a rule engine that
    allows users to define custom rules for the knowledge base.
    On the application side, we are currently working on several
    scenarios for the use of semantic wikis in elearning
    environments, and we are investigating the use of IkeWiki
    as part of a methodology for collaborative knowledge engineering
    developed in the project Dynamont.


    References
    [1] D. Aumueller and S. Auer. Towards a Semantic Wiki Experience
    – Desktop Integration and Interactivity in WikSAR. In
    Semantic Desktop Workshop 2005 at ISWC’05, Galway, Ireland,
    2005.
    [2] D. Beckett. Modernising Semantic Web Markup. In XML
    Europe 2004, Amsterdam, The Netherlands, 2004.
    [3] M. Kr¨otsch, D. Vrandeˇci´c, and M. V¨olkel. Wikipedia and the
    Semantic Web - The Missing Links. In Proceedings of the
    WikiMania2005, 2005.
    [4] S. Schaffert, A. Gruber, and R. Westenthaler. A Semantic
    Wiki for Collaborative Knowledge Formation. In Semantics
    2005, Vienna, Austria, November 2005.
    [5] R. Tazzoli, P. Castagna, and S. E. Campanini. Towards a
    Semantic WikiWikiWeb. In 3rd International Semantic Web
    Conference (ISWC2004), Hiroshima, Japan, 2004.
    [6] M. V¨olkel and E. Oren. Personal Knowledge Management
    with Semantic Wikis. 2006.

    IkeWiki: 协同知识管理的语义Wiki (2)

    3 Semantic Wiki Systems

    RDF,OWL,主题图,概念图...

    连接,连接!不仅仅是导向,更重要的是对连接的注释,通过对连接的注释,表达了页面间的逻辑含义,这可以让机器能够处理!例如描述莫扎特的网页和萨尔茨堡的网页间的注释应该是“生于”: 莫扎特 生于 萨尔茨堡! 
    A “semantic wiki” extends a wiki by “semantic technologies”
    like RDF, OWL, Topic Map, or Conceptual Graphs.
    The main idea is to make the inherent structure of a wiki –
    given by the strong linking between pages – accessible to
    machines (agents, services) beyond mere navigation. This
    is generally done by annotating existing navigational links
    with symbols that describe their meaning. For example, a
    link from Mozart to Salzburg could be annotated with lived
    in or born in.

    注释能够增强上下文信息的展示,能够增强相关页面间的导航,根据内容的上下文增强语义搜索。展示,导航,搜索可以以更自然的方式完成。

    Such annotations are useful for many purposes, e.g. enhanced
    presentation by displaying contextual information,
    enhanced navigation by giving easy access to relevant related
    information, and enhanced “semantic” search that respects
    the context in addition to the content. Note that presentation,
    navigation, and search can be done in a rather
    generic manner, but often profit greatly from an adaptation
    to the represented context.

    有些时候页面间的注释比页面本身内容还要重要!
    Semantic wikis exist in many different flavours (e.g. Se-
    MediaWiki [3], SemWiki [6], IkeWiki [4], PlatypusWiki
    [5]). While for some the page content is still in the foreground
    and the annotations just optional “added value”, others
    require annotations – sometimes to the extent where the
    annotation is more important than the page content itself.
    This reflects also that different systems have different purposes,
    e.g. extending existing content by annotations to allow
    for better navigation, collaborative ontology engineering,
    etc. Nonetheless, frequently found features are:

    所有的语义Wiki通过赋给连接特定的类型来注释连接。背后的含义是如果用户在一个页面中创建了一个指向另一个页面的连接,那么他一定想表达某种意思,或者某种关联,而不仅仅是简单的连接,想想莫扎特的例子!不同的系统中连接的注释方式不同。一些语义Wiki将注释作为Wiki语法的一部分(例如语义MediaWiki),而另外的系统将提供一个单独的编辑器来增加注释(例如IkeWiki)

    类型化或注释连接
    Typing/Annotating of Links. Virtually all semantic
    wikis allow to annotate links by giving them certain types.
    The idea behind this is that a link created by a user almost
    always carries meaning beyond mere navigation, as given in
    the example in the beginning of this section. The way link
    annotations are edited differs from system to system. Some
    semantic wikis include the annotations as part of the wiki
    syntax (e.g. Semantic MediaWiki [3]), while others provide
    a separate editor for adding annotations (e.g. IkeWiki).

    很多语义Wiki能够基于语义注释来改变内容的展示方法。可以在页面的某个地方显示语义相关的页面,这些相关页面的信息来源于底层的知识库(比如一个树图显示页面内容属于某个层次结构)

    具有上下文意识的展示
    Context-Aware Presentation. Many semantic wikis can
    change the way content is presented based on semantic annotations.
    This can include enriching pages by displaying
    of semantically related pages in a separate link box, displaying
    of information that can be derived from the underlying
    knowledge base (e.g. a box with a graphical tree presentation
    for content belonging to a hierarchy, or license information),
    or even rendering the content of a page in a different
    manner that is more suitable for the context (e.g. multimedia
    content vs. text content).

    传统的Wiki仅仅允许跟随一个连接(点击打开页面),语义Wiki能够做的更多,例如文本上下文出现的连接更为独立,能够在单独的相关信息栏中显示。例如莫扎特页面可以提供一个独立的信息栏显示居住于,作品等分类引用等。

    增强的导航
    Enhanced Navigation. Annotated/typed links provide
    more information for navigation. Whereas a traditional wiki
    only allows to follow a link, a semantic wiki offers additional
    information about the relation the link describes.
    Such information can be used to offer additional or more
    sophisticated navigation. For instance, links are more independent
    from the textual context they appear in and can be
    displayed e.g. in a separate “related information” box. The
    page describing Mozart could e.g. offer a separate box with
    references categorised by “lived in”, “composed”, etc.

    大部分语义Wiki能够通过SPARQL语言,提供基于底层知识库的语义搜索,这种语言用来进行RDF的查询。通过语义查询,用户能够查询”莫扎特创作的所有曲子“或”查找所有和版本许可相关工作的文档“。

    语义搜索

    Semantic Search. Most semantic wikis allow a “semantic
    search” on the underlying knowledge base. Usually, queries
    are expressed in the language SPARQL, a query language
    recently proposed as W3C recommendation for RDF querying.
    Using “semantic search”, users can ask queries like
    “retrieve all pieces composed by Mozart” or “retrieve all
    documents where the license permits derivative works”.

    推理意味着使用预定义或者用户定义的知识库规则从系统中保存的事实衍生出附加的隐含的知识。例如,系统能够从莫扎特创作了安魂曲的事实能够推理出莫扎特是个作曲家。虽然推理是个很重要的特性,但是仅仅被一小部分Wiki支持。原因有多个方面:耗时,耗内存,产生不期望的结果,或者用户无法跟踪的结果。

    推理支持
    Reasoning Support. Reasoning means deriving additional,
    implicit knowledge from the facts entered into the
    system using predefined or user-defined rules in the knowledge
    base. For example, from the fact that “Mozart” composed
    “Die Zauberfl¨ote”, a system capable of reasoning
    could deduce that “Mozart” is a “Composer”. Although
    reasoning is an important feature, it is only supported by
    a small number of Wikis. The reasons for this might be
    that it is time-consuming, memory intensive, and can yield
    results that are not expected and/or traceable by the user.

    IkeWiki: 协同知识管理的语义Wiki (1)

    作者:Sebastian Schaffert

    1 Introduction
    A serious obstacle for the development of SemanticWeb
    applications is the lack of formal ontologies and knowledge
    represented in other formal languages.

    语义网应用的困难在于缺少正式的本体论以及如何让各自领域的专家正式化自己的知识。

    Arguably, one of the
    main reasons for this is the rather high technical barrier for
    using Semantic Web technologies that deters many domain
    experts from formalising “their” knowledge. Therefore, formalised
    knowledge is currently limited to computer science
    and a small number of areas with a very high demand of
    interoperability (e.g. genetic engineering).

    语义网往往限制在计算机科学以及少数异质性需求的领域,比如遗传工程等。


    At the same time, wiki systems are becoming more and
    more popular as tools for content and knowledge management.
    Much knowledge is nowadays available in systems
    like Wikipedia. Unfortunately, this vast knowledge is not
    accessible for machines. If a small amount of this knowledge
    would be formalised, wiki systems could provide improved
    interfaces and advanced searching and navigation
    facilities.

    关于知识管理,Wiki系统是个很流行的工具。但是可惜的是机器无法理解这些知识。如果能够将知识正式化的话,有助于高级搜索以及知识向导,用户体验就会很好。


    “Semantic Wiki” systems aim to combine “traditional”
    wiki systems with Semantic Web technology. This combination
    bears much potential in many application areas. In
    this article, I present our prototype system IkeWiki (ike =
    knowledge, wiki = fast), which is a feature-rich semantic
    wiki system we developed at Salzburg Research. IkeWiki
    serves as a testbed for possible applications of semantic

    语义Wiki目标就是将传统的Wiki和语义网结合起来,IkeWiki就是这种系统的原型。

    wiki technology. I briefly outline three of these applications
    (collaborative ontology engineering, collaborative knowledge
    management, and educational environments).

    协同本体工程,协同知识管理,教育环境


    This article is structured as follows: Section 2 summarises
    important features of (traditional) wiki systems;
    Section 3 introduces SemanticWikis and describes features
    common to all or many of them; Section 4 briefly describes
    the design and architecture of IkeWiki; Section 5 presents
    the three application scenarios; Section 6 gives an overview
    over related work; finally, Section 7 concludes with some
    perspectives.

    本文第二部分介绍传统Wiki的重要特性,第三部分介绍语义Wiki的通用特性,第四部分介绍IkeWiki的设计和架构,第五部分展示上述三个应用场景,第六部分综述相关工作,第七部分展望未来。

    2 Traditional Wiki Systems
    “Wiki” is the short form for “WikiWikiWeb” and is derived
    from the Hawaiian expression “wiki wiki” meaning
    “fast” or “quick”. A wiki is essentially a collection of Web
    sites connected via hyperlinks. While there is a wide range
    of wiki systems available (e.g. MediaWiki1, MoinMoin2,
    TWiki3) with different purposes and audiences, all of them
    share the following common properties:

    通过浏览器编辑内容
    Editing via Browser. Content is usually edited via a simple
    browser interface that can be used without installing
    any additional (expensive) software. This makes editing
    simple and allows to modify pages from everywhere in the
    world with only minimal technical requirements. As a consequence,
    content creators can access and update the wiki
    from wherever they are, e.g. at work, at home, at conferences,
    nowadays even while travelling.

    简单的Wiki语法
    Simplified Wiki Syntax. Content is usually expressed in
    a simplified hypertext format (‘wiki syntax”) that is much
    easier to use for non-technical users than e.g. HTML. Formatting
    thus does not require knowledge of HTML.

    回滚机制(版本机制)

    Rollback Mechanism. Changes to the content of a wiki
    are versioned each time they are stored, i.e. previous versions
    of pages are kept. This allows to revert back to earlier
    versions of a page e.g. in case important parts have been
    accidentally deleted or undesirable modifications have been
    made by someone else. Also, most wiki systems allow to
    compare two versions of a page, making it possible to identify
    changes between edits quickly.

    非受限访问

    Unrestricted Access. In most wiki systems, access is
    completely unrestricted – i.e. anyone can correct, modify,
    complete, or even delete anything. While this might seem
    strange, and even dangerous, from a traditional perspective,
    practice shows that the system works: on the one hand, illmeaning
    users are rather rare; on the other hand, all changes
    can easily be undone using the rollback mechanism.
    Note that some wikis still allow to apply further access
    restrictions using users and groups as found in traditional
    content management systems.

    协同编辑

    Collaborative Editing. The above-mentioned properties
    combined make wikis an ideal tool for collaborative editing.
    As soon as someone creates content, others can contribute
    to it, extend it, correct it, etc. Many wiki systems provide
    further support for collaborative editing, e.g. by means of
    discussion forums, summaries of changes, and list of last
    updates.

    强连接
    Strong Linking. Pages in a wiki are usually strongly
    linked with each other using hyperlinks. The reason for this
    is that the simplified wiki syntax makes it very easy to define
    a link to another page in the wiki. For example, in many
    wikis a link is defined by enclosing a word in square brackets,
    or by using a so-called “CamelCase” where a word contains
    several upper-case letters. Links to non-existing pages
    are usually rendered in a different colour. If a user clicks on
    such a link, the system redirects him to a view where he can
    create the non-existing page. In many wikis, this is even the
    only way to create a page.
    Links in a wiki are the most important tool for navigation.
    Therefore, many systems allow not only to follow
    links in the direction they are defined but also in reverse
    direction (“back-links”).

    搜索功能
    Search Function. As a further tool for navigation, almost
    all wiki systems allow a full-text search over the content of
    all pages.

    上传其他形式的内容(图片,文件,多媒体等)
    Uploading of Other Content. In addition to creating text
    content, some of the more sophisticated wikis allow uploading
    of arbitrary (multimedia) content, like documents, images,
    program code, etc.

    Unlike other groupware or content/knowledge management
    tools, a wiki system gives users almost complete freedom
    over the content development process without rigid workflow,
    access restrictions, or predefined structures. Users
    need not adapt their practice to the ”dictate of the system”,
    but can allow their own practice to define the structure. This
    is important, because different domains often have – or even
    require – different kinds of workflow.

    Wiki的应用领域
    As a recent survey on the popular technology site Slashdot
    showed4, wiki systems are currently used for a wide
    variety of purposes, including:

    百科全书
    • encyclopaedia systems: collect knowledge in a certain
    area (e.g. Wikitravel5) or unrestricted (e.g.
    Wikipedia6) in a community effort with contributions
    from a wide range of users

    软件开发
    • software development: collaboratively create documentation,
    collect ideas, track bugs; most of today’s
    high-profile Open Source projects (e.g. Apache,
    Mozilla, OpenOffice) use wikis for coordination

    项目知识管理
    • project knowledge management: project tracking,
    brainstorming and exchange of ideas, coordination of
    activities, agenda tool for collecting topics of meetings,
    project notes repository, knowledge base, staff
    directory

    个人知识管理
    • personal knowledge management: sketchpad to collect
    and elaborate personal ideas, addresses, dates, tasks,
    bookmarks, etc. [6]

    协同写作
    • collaborative writing: authors work collectively on a
    writing (short story, novel, etc.) which is immediately
    accessible by readers for their enjoyment

    内容管理系统/知识库
    • CMS/knowledge base: collect content, connect content,
    simple publication tool

    16 October

    Netbeans Platform: Lookup! Lookup!

    Netbeans Platform的Lookup类给我们带来了什么呢?注入依赖和解耦!Lookup的基本用法常常是:

    Foo foo = someLookup.lookup(Foo.class)

    使用Lookup来查找一个Foo类的实例。你可以将Lookup想成是一个Map,键是类,值是实例。

    Netbeans中Lookup用途有:

    1. 表现一个对象的能力。IS-A关系转变为HAS-A关系。

    想想传统的一种解耦方式:将其他模块创建的对象cast到特定的类型。Netbeans,不这么做,Netbeans做法是让其他模块创建的对象实现Lookup.Provider接口(这个接口只有一个方法:public Lookup getLookup()),然后通过这个Lookup获得你需要协同工作的对象。然后你的代码询问这个对象是否拥有特定接口的实例:

    Your code  <--   interact with --> Some object -- implements --> Lookup.Provider

                                                             |__ has a Lookup Object -- maintain

                                                                                                            |__ Object 1

                                                                                                            |__ Object 2

                                                                                                            |__ Object 3 ...

    这样,通过Lookup, Some object 将 IS-A 关系(Some object实现Object1接口,Object2接口,Object3接口)转化为HAS-A关系(Some object的lookup对象拥有Object1, Object2, Object3).

    这种转化具有重要的意义!方便!快捷!动态(运行时无法改变实现的接口和类型)!弹性(运行时一个对象的能力是可能变化的,但是类型是不能变化的)!例如如果你想保存一个对象,你不必问其是否实现Saveable接口,你只需要问其是否拥有一个SaveCookie实例(SaveCookie有一个save方法)。

    2. 依赖注射和解耦

    一个模块能够定义多个接口让其他模块实现这些接口,这个模块可以使用Lookup.getDefault()方法获得全局Lookup,然后根据全局Lookup查找其接口的所有实现。

    3. 动态服务发现

    模块能够非常简单的将代表全局服务或伪单例的对象通过默认的Lookup进行注射。

    单例模式的的目的是让一个对象只拥有一个实例。实现这种模式又很多方法,例如最简单的是创建一个工厂方法,然后将构造器定义为私有的,然后维护一个实例,对所有的调用(工厂方法)都返回这个实例。单例模式在Netbeans中也有广泛的应用。通常全局服务没有必要有多个实例,例如在整个应用程序的主窗口中我们只需要一个状态显式栏实例,来显式状态。例如Netbeans的Windows系统API,你不用直接使用它,这个模块org.netbeans.core.windows将StatusDisplayer实现注射进来,放在默认的Lookup中,你仅仅使用StatusDisplayer.getDefault().setStatusText("something").就可以设置状态信息了。

    Lookup.Result 和 Lookup.Template

     

    什么样的对象需要拥有自己的Lookup呢?

    在Netbeans中的一些基本API类中又很多都有getLookup()方法,他们都实现了Lookup.Provider接口。Netbeans中有三个著名的例子:

    1. Project. Project API . Project实际就是一个将一个目录和一个Lookup结合在一起,再加点东西的一个对象。Project API 定义了能在一个Project实例的Lookup中出现的(可选的)类。不同的模块实现了Project,提供自己的实现。其他API定义一些其他的类。例如Java Project API定义了一个ClassPathProvider的接口。这个接口能在Java源代码Project的Lookup中被找到,而其他普通的Project没必要有这个接口。整个Project类定义如下:

    public interface Project extends Lookup.Provider {

    // 维护一个文件对象,代表项目目录
    FileObject getProjectDirectory();

    // 维护一个Lookup对象
    Lookup getLookup();
    }

    可以从Project的Lookup中请求多个接口。例如ProjectInformation对象能够提供Project名称等基本信息。

    2. TopComponent . 顶层组件是Netbeans的窗口系统管理的一个GUI面板。继承于TopComponent的类可以通过TopComponent.getLookup()方法来操作面板中的选择等事务。

    3. Node. 节点就是通常说得树-节点类型的对象,代表底层的数据模型。例如项目和文件窗口中的文件树就是节点树。org.openide.nodes.Node就有getLookup()方法。

    说了Netbeans中著名的三种具有Lookup对象的类,到底什么样的对象需要Lookup对象呢??

    答案是,需要暴露某些能力的对象。这些对象可以通过Lookup对象向外界表明其具备某些能力,从而让其他代码能够使用这些对象的能力。举个例子,如果你想保存一个文件对象,那么这个文件对象肯定有保存的能力。传统方式怎么做呢:

    public void actionPerformed (ActionEvent e) {
    Object o = something.getSelection();

    // 你会检查其是否实现Saveable接口
    if (o instanceof Saveable && ((Saveable) o).canSave()) {
    ((Saveable) o).save();
    }
    }

    可惜的是这种方法太不强大了。Java对象无法轻易更改他们的类型。因为情况总是在变化的。Java文件包括源文件和编译文件,有些事情你无法在只有源文件没有编译文件的情况下做,例如执行。并不是所有Java源文件都有对应的编译文件的。因此Lookup的出现能够很好的解决这种问题。Java文件的Lookup内容是可以随时变化。当Java源文件被编译后,可以向Java文件的Lookup内容添加一个编译文件对象,如果Java文件被编译了,那么Lookup内容中就保存一个编译文件对象,如果编译文件被删除了,这个编译对象也从Lookup内容中删除了。

    public void actionPerformed (ActionEvent e) {
    Lookup lkp = Utilities.actionsGlobalContext();
    SaveCookie save = lkp.lookup (SaveCookie.class);
    if (save != null) {
    save.save();
    }
    }

    事实上,Netbeans中一个正在被编辑的文件的保存过程,就是代表这个文件的节点Node的Lookup中出现了一个SaveCookie对象。这个代码并不需要知道SaveCookie.save()方法的具体细节,只需要知道SaveCookie对象在Lookup中,就可以保存。

    Lookup是一种通讯机制

    上面说得Project就是一个例子,Netbeans中有一个概念叫服务提供者接口(Service Provider Interface, SPI ). 不同的模块通过在默认的Lookup中安装ProjectFactory实例,来插入不同的项目类型project type.你可以在Netbeans的项目向导中发现你可以创建不同类型的项目。Netbeans包含多个项目接口的实现。

    Lookup和代理

    ProxyLookup允许将两个Lookup融合。

    Lookup和选择

    那我们如何在程序中使用Lookup呢?

    基本上说,我们无需自己编写Lookup(当然如果需要的话,你可以编写)。

    NetBeans 的 Lookup 可以說是无处不在,它也是 NetBeans 中最基本的模块。在执行的時候,NetBeans 将Lookup分为系统服务池的Lookup和具有焦点窗口的对象池的Lookup。我们可以从以下地方获得Lookup:TopComponentNodeUtilities.actionsGlobalContext()、和 Lookups四个地方。

    我们通过Utilities.actionsGlobalContext()来获得对象池的Lookup, 这里Netbeans已经帮我们整合过Lookup对象了.Utilities.actionsGlobalContext()将返回一个Lookup对象,这个对象是活动的(具有焦点)的顶层组件的Lookup的代理Lookup,如果顶层组件是Explorer视图的话,将代理被选择了的节点的Lookup对象们。

    我们通过Lookup.getDefault()方式获得系统服务池的Lookup.

    Netbeans平台为我们准备好了几种使用方式:

    1. 通过Lookups. 如果你需要包含固定数目对象的Lookup,你可以使用Lookups.fixed(Object... objectsToLookup) (注意:... 代表可变参数数量),也可以使用Lookups.singleton(Object objectToLookup)返回一个只包含一个对象的Lookup.

    2. AbstractLookup和InstanceContent. 如果你希望你的Lookup可以动态的包含对象(数目可变),那么你可以使用AbstractLookup和InstanceContent相结合的方式。注意AbstractLookup并不是抽象类。具体的用法这里有个很好的例子,Fox的Lookup讲解

    在这个例子中,有一个业务对象FoxObject, 有两个顶层组件:Consumer顶层组件和Producer顶层组件。Producer顶层组件中包含两个状态按钮(ToggleButton):FoxButton和DonButton。Consumer顶层组件有一个List表单。

    效果是:如果你按下Producer顶层组件窗口中的其中一个Button,就会创建一个FoxObject对象,其名字根据按钮的名字命名,例如按下DonButton将创建一个名字为Don的FoxObject. 如果程序的焦点在Producer顶层组件上(蓝色背景意味焦点在其上,灰色背景意味焦点不在其上)的话,Consumer顶层组件的List表单将出现这个名字为Don的FoxObject, 当你再次按下DonButton时,按钮的状态改变,名字为Don的FoxObject被删除,List表单中相应的对象也消失了。如果你将程序焦点换到Consumer顶层组件的时候,List表单中的所有对象都消失了,重新将焦点换到Producer顶层组件上时,List表单中的对象重新出现了。

    这是怎么实现的呢?我们看一下:

    1. 我们在Producer顶层组件中维护一个InstanceContent对象,两个FoxObject对象。在Producer顶层组件构造的时候,我们初始化Lookup:

    private void initLookup(){

            // 创建InstanceContent,然后构建一个AbstractLookup,然后将这个Lookup和Producer顶层组件关联
            m_InstancePool=new InstanceContent(); 
            this.associateLookup(new AbstractLookup(m_InstancePool)); 
        }

    在ToggleButton状态变化方法中,我们根据Button的状态,决定InstanceContent的内容(名为Don的FoxObject对象的添加和删除)

    private void m_PutDonItemStateChanged(java.awt.event.ItemEvent evt) {                                         
            if(evt.getStateChange()==ItemEvent.SELECTED){
                if(m_Don==null){
                    m_Don=FoxObject.createInstance("don", "Don, Chen");
                }
                m_InstancePool.add(m_Don);
            }else if(evt.getStateChange()==ItemEvent.DESELECTED){
                if(m_Don!=null){
                    m_InstancePool.remove(m_Don);
                }
            }
        }          

    2. 我们让Consumer顶层组件实现LookupLisenter, 因为他要根据FoxObject对象的状态来显式List表单。他维护一个JList表单以及一个Lookup.Result结果。

    final class ConsumerTopComponent extends TopComponent implements LookupListener {...

    当Consumer顶层组件被打开和关闭时:

    public void componentOpened() {
            clearList();

            // 初始化LookupQuery
            initLookupQuery();
            FoxService oService=(FoxService) Lookup.getDefault().lookup(FoxService.class);
            if(oService !=null ){
                oService.saySomething();
            }
        }
        public void componentClosed() {

            // 关闭LookupQuery
            uninitLookupQuery();
            clearList();
        }

    我们看一下,在Consumer顶层组件窗口被打开时,我们根据FoxObject类制作一个模版,然后通过Utilities.actionsGlobalContext()查找到所有FoxObject的实例,以Lookup.Result方式展现。找到这些FoxObject实例后,对代表他们的Lookup.Result添加监听器,就是Consumer顶层组件自己。然后更新结果列表。

    private void initLookupQuery(){
            Lookup.Template oFoxTemplate=new Lookup.Template(FoxObject.class);
            m_LookupResult=Utilities.actionsGlobalContext().lookup(oFoxTemplate);
            m_LookupResult.addLookupListener(this);
            refreshResultList();
        }
        private void uninitLookupQuery(){
            if(m_LookupResult!=null){
                m_LookupResult.removeLookupListener(this);
                m_LookupResult=null;
            }
        }

    实现Lookup监听器的方法:

    public void resultChanged(LookupEvent ev){
            refreshResultList();
        }

    一旦Lookup变化了,resultChanged方法就被调用,执行refreshResultList方法。这个方法获得Lookup.Result中的所有实例,如果有实例的话,重新根据这些实例绘制Consumer顶层组件的List表单。

    private void refreshResultList(){
            Collection<FoxObject> cList=m_LookupResult.allInstances();
            if(!cList.isEmpty()){
                this.m_FoxObjectList.setListData(new Vector<FoxObject>(cList));
                this.m_FoxObjectList.revalidate();
                this.m_FoxObjectList.repaint();
            }else{
                clearList();
            }
        }

    整个演示就完成了。这里我们特别要注意几点:

    1. FoxObject是业务对象,它仅仅关注自己的业务和信息,例如名字,ID等,对其他的事情一概不知。

    2. Producer顶层组件需要和一个Lookup关联,这个Lookup是AbstractLookup和InstanceContent共同完成的,以便Lookup内的对象数目可以动态改变(通过ToggleButton的状态):

    ProducerTopComponent --> AbstractLookup --> InstanceContent     --> FoxObject Class

                                                         |                       |__ Add/Remove --> Fox FoxObject <--> Button1

                                                         |                       |__ Add/Remove --> Don FoxObject <--> Button2

                                                         |

                                                         |    关键:Netbeans通过Utilities.actionsGlobalContext将

                                                         |    Producer顶层组件和Consumer顶层组件解耦,相互通过Lookup沟通

    ConsumerTopComponent --> Utilities.actionsGlobalContext().lookup(FoxObject.class)

                           |______  监听 -->      |__ Lookup.Result

                                             |______  更新 -->     JList (根据Lookup.Result的变化)

    3. 结构图

                   <--------------                                 FoxObject                       --------------->

                   |                                                              |                                                   |

                   |        <-----   Lookup (Utilitis, AbstractLookup, InstanceConent)  ------>       |

                   |         |                                                                                                |       |

         ConsumerTopComponent                                XXX                  ProducerTopComponent

    12 October

    Netbeans Platform: 注册与发现的机制

    Netbeans Platform是模块化的设计。我们看一下最基本的开发思路:

    例如,我们想要写一个XML验证器模块。我们会做一下几个事情:

    1. 设计Validator接口, 定义一些验证所需的方法。方便以后提供Manifest验证器,html验证器等。

    2. 设计实现Validation类,这个类维护一个Validator的Map, 允许添加和删除Validatior,如果需要验证的话,这个类会遍历Validator找出响应的Validator实现。

    3. 实现XMLValidator类,实现Validator接口

    4. 实现XMLModuleInstall类,继承ModuleInstall类。这个类维护一个静态的Validation类,完成XMLValidator的注册和去注册任务

    这里有个问题,就是上述办法包含太多的样板代码。例如Validation中要维护注册许多验证器。每个模块需要提供Validator的实现类的同时,还要编写另一个类继承ModuleInstall类来完成注册和去注册的任务, 例如XMLValidator还要XMLModuelInstall, XMLValidator负责验证任务,XMLModuelInstall负责注册和去注册XMLValidator. 通过ModuleInstall程序在启动时都要加载验证器,不管你到底用不用它。

    所以,Netbeans Platform需要一个好的注册模式。

    我们先看看其他已经存在的注册模式:

    java.awt.Toolkit使用一种基于属性的解决方案,property-based.

    public Toolkit getDefaultToolkit() {
    java.awt.Toolkit t = null;
    String classname =
    System.getProperty("java.awt.Toolkit"); // 从系统中获得java.awt.Toolkit属性:类名称
    if (classname != null) {
    try {
    Class c = Class.forName(classname); // 根据类名称获得响应的类
    t = (java.awt.Toolkit) c.newInstance(); // 使用类创建类实例
    } catch (Exception ex) {
    System.out.println
    ("Cannot initialize toolkit: " + classname);
    ex.printStackTrace();
    }
    }
    // Fallback
    if (t == null) {
    t = new GenericAWTToolkit(); // 如果都不成功,返回一个通用的默认的实例
    }
    }

    这种解决方案比以前有进步,没有烦人的setter方法和注册方法,不过它需要你在Java虚拟机运行时正确的设置属性。你不得不在程序启动时初始化。

    我们看看Netbeans Platform如何做这件事情。首先,设计理念是,基于现有的标准,需要的时候作些增强,必须很好的和Netbeans运行时容器提供的动态模块环境相匹配。这种解决方案必须对任何接口和类都适合才行。并且它要支持监听器,允许任何人监听已经注册了的对象的任何变化。例如,监听一个模块的激活和失活。

    Netbeans Platform如何做到这一点呢?让我们看看:Lookup!

    MetaInf Service 元信息服务

    JDK1.3的时候,Java提出了一个概念:服务提供者,Service Provider.这个概念介绍了一种完全是声明式的注册机制。实际上这种注册机制完全基于Java虚拟机的当前类路径,并没有什么其他的东西。这种注册机制使用Java类路径定义注册了的对象,非常容易使用。改变注册提供者,仅仅需要将提供者的jar包放在应用程序的类路径上就可以了。这样提供者能够迅速被查找到并且可以被其他代码访问。

    背后的基本思想是每个希望提供某些接口实现的jar文件(Netbeans的术语就是模块),例如javax.xml.parser.DocumentBuilderFactory的实现,能够创建自己的接口实现,比如org.saxon.MyFactory. 然后通过在自己jar包中创建一个META-INF/services/javax.parser.DocumentBuilderFactory文件的方式暴露给系统,这被称为系统中的服务。这个文件中每一行包含一个实现类的名字。在这个例子中,这个文件中存在:org.saxon.MyFactory一行,文件名字就是接口,里面的内容的一行就是一个实现。

    我们看一下如何运行的呢?当你使用DocumentBuilderFactory.newInstance()来创建一个实现实例的时候,系统会扫描所有的META-INF/services/javax.parser.DocumentBuilderFactory文件。如何扫描呢?通过ClassLoader.getResources("META-INF/services/javax.parser.DocumentBuilderFactory"). 系统将会读取文件的内容,通过默认构造器创建实例。究竟那一个实现会被创建呢?答案是第一个。

    这种方式很好,也很流行了,在JDK1.6中,更是增加了一个辅助类java.util.ServiceLoader. 使用这个类,能更加容易的查找到所有注册的服务,不用手工编写“查找,读取,实例化”的代码。因此在JDK1.6中上述的任务简化为:

    return ServiceLoader.load(DocumentBuilderFactory.class, someClassLoader).iterator().next();

    OK, 让我们回到Netbeans上,Netbeans的解决方案基于上述技术。它被称为Lookup!

    全局Lookup

    org.openide.util.Lookup, 它和java.util.ServiceLoader一样是service provider模式。你可能要问,为什么你要单独搞出这么个东西?原因如下:

    1. 如果你使用JDK1.6以前的版本(虽然不太可能),你可以使用Lookup作为替代

    2. Lookup能够立刻在Netbeans运行时容器中使用。它知道如何发现系统中的模块,并且读取他们定义的服务。

    3. Lookup支持监听器。客户代码可以设置监听器,监听Lookup内容的变化。这在动态环境中非常重要,模块可以在运行时激活或者失活,从而影响一系列注册服务的提供者。

    4. Lookup可以扩展和替代。JDK1.6的java.util.ServiceLoader是最终类,并且是硬编码的,而Lookup是可扩展的类,允许各种实现,这在单元测试中尤其重要。甚至你可以编写一个增强版的Lookup, 让它不仅仅从META-INF/services中读取信息。

    5. Lookup是通用的抽象层。每个classloader可以有一个JDK的ServiceLoader实例,而在Netbeans中可以有成千上万个相互独立的Lookup,每个可以代表一个单一的位置去发现和查询服务和接口。事实上,这正是Netbeans使用Lookup的方式:他代表每个对话,窗口元素,树中节点等的上下文。

    我们重新看一下Validation的例子,在先前的例子中,Validation依靠维护一个Validator的Map进行注册和去注册。那么使用Lookup后,Validation根本不需要这个Map,代码如下:

    package org.netbeans.examples.validate.api;
    import org.openide.util.Lookup;
    public final class Validations {
    private Validations() {}

    // 将Validator.class定制为一个Lookup模版 Lookup.Template,

    // 通过Lookup获得Validator.class的模版查找到Lookup.Result结果

    // 这个结果包含所有找到的Validator实例,遍历这些实例,找到相应的Validator实例来验证


    private static Lookup.Result<Validator> validators =
    Lookup.getDefault().lookup(
    new Lookup.Template<Validator>(Validator.class)
    );
    // Or in 6.0 version just:
    // Lookup.Result<Validator> validators =
    // Lookup.getDefault().lookupResult(Validator.class);


    public static void validate(String mimeType, InputStream is)
    throws IOException {
    for (Validator v : validators.allInstances()) {
    if (v.supportsMimeType(mimeType)) {
    v.validate(is);
    return;
    }
    }
    throw new IOException("No validator found for " + mimeType);
    }
    }

    使用Lookup不仅省却了Validation的Map,而且不需要registerValidator等方法。全部依赖于Lookup.getDefault的实现和其注册方式。这样Validation类只需关注validate方法就可以了。

    看看吧,现在如果我们想实现另一个验证器Manifest Validator. 我们不再需要知道ModuleInstall或者在模块初始化和结束化调用任何方法。我们仅仅需要声明ManifestValidator实现了Validator接口就可以了:

    package org.netbeans.examples.manifestvalidator;
    public final class ManifestValidator implements Validator {
    public boolean supportsMimeType(String mimeType) {
    return "text/x-manifest".equals(mimeType);
    }
    public void validate(InputStream is) throws IOException {
    // Just try to read the file as manifest:
    Manifest mf = new Manifest(is);
    }
    }

    接下来怎么将ManifestValidator注册呢?很简单,在META-INF目录下创建META-INF/services/org.netbeans.examples.validate文件,告诉人们存在实现这个接口的实现,然后在这个文件中增加一行:org.netbeans.examples.manifestvalidator.ManifestValidator。告诉人们ManifestValidator实现了这个接口。万事OK了!记住啊,我们有个org.netbeans.examples.manifestvalidator包,这个包包括一个META-INF目录,这个目录下有一个以接口名字命名的文件,这个文件中有一行实现类的类名,注册完成了!

    11 October

    Netbeans Platform: 模块版本

    Netbeans Platform中模块版本问题写作API版本 API Versionning. 我认为不是很恰当,实际上在Netbeans中只有模块项目才能设置API Versioning. 打开一个模块项目的属性表,可以看到:

    Category-->

             Sources

             Libraries

             Display

             API Versioning        <-- 负责模块的版本工作

             Build-->

                     Compiling

                     Packaging

    本质上,其他模块,或者程序是和模块本身打交道的,所以在外界看来应该是模块的版本。所以我们这里使用模块的版本来讲述API Versioning.

    Netbeans Platform: 模块间的通信

    1. 模块间交互的方式

    在Netbeans中,一个模块可以由多个package组成。需要注意的是,尽管你将package中的类声明为public,并不意味着其他模块可以使用这个类。Netbeans的模块化设计在模块之间设置了一个屏蔽用来降低模块间的耦合,从而达到弹性设计。因此在一个模块中,我们需要设置模块的public package属性, 注意只有模块Module,而不是模块组Module Suite才有这样的设置。public packages属性允许你设置模块中的那些package是可以被其他模块使用/访问的。例如,你有一个biz模块,其中包含com.you.biz 和com.you.util两个包,从字面上看util是个工具包,用来辅助biz包,只有biz包才代表真正的业务,因此将com.you.biz设为public供其他模块使用/访问,而将util包屏蔽。这样的好处不用解释。使用/访问这个包的其他模块自然要依赖于模块biz, 因此他们也需要设置模块依赖关系。例如,在他们的manifest文件中要有如下:

    OpenIDE-Module-Module-Dependencies: com.you.biz > 1.5

    这意味着这个模块依赖于你的biz模块并且版本要高于等于1.5,> 1.5是可选的,你也可以不指定这个。

    但是真的只有将模块中的package指定为public, 其他模块才能访问这个package麽?答案是否定的!Netbeans允许你绕过这条路来直接访问package, 但是要你风险自负!这个方法就是实现依赖 Implementation dependency, 这个术语有点不好理解,我们会解释的。在解释之前,我们先想一下,为什么我们要绕过public package属性,去干这件事?一个可能的情况是:你发现一个模块的作者忘记将一个package设为public了,但是你又发现,这个package里的public类你完全了解,并且知道如何使用。很可惜的是,作者忘记或者没有将这个package设为public, 原因天晓得!不过你就是希望使用这个package里的public类, 怎么办呢?那就使用实现依赖,不过这种方式有局限,就是你必须明确指定,注意是明确指定,你要使用的模块的版本。原因很简单,因为这个模块的作者根本没有将这个package设为public,所以他将来也许会改变这个packege的结构和内容,也许他认为虽然这个package要公开,但目前不成数,然而你却绕过他的设置,直接访问了!所以真正的问题在于兼容。未来的版本只保证公开的不变,其他都有变化的可能。风险在于你的模块可能因此被破坏了。所以,你必须指定确切的版本,来让Netbeans核查。这就是术语实现依赖的来源,你依赖的是模块的特定的实现。假定模块B实现依赖于模块A,除非Netbean系统核查系统中模块A的版本和模块B所依赖的模块A的版本一致,才装载模块B。在模块B中,manifest文件中如下配置:

    OpenIDE-Module-Module-Dependencies: com.you.moduleA = 3

    在模块A中,manifest文件配置如下:

    OpenIDE-Module-Implementation-Version: 3

    你可以在Netbeans图形界面中的项目属性中查看实现依赖,要求其他模块的版本号不要是负整数。你可以使用自动添加实现版本的功能。

    特别强调: 不到万不得已,不要使用实现依赖!!实际这只是一种折衷的办法。甚至在上述使用实现依赖的例子中,如果不是需要访问这个包中所有的公开类,我宁肯将我需要的类拷贝出来,违背通常的设计模式,也不要使用实现依赖。

    朋友依赖 Friend dependencies , 朋友依赖和上述有点不同,想象一下这种情况,一个模块的作者认为他开发的包还不够成熟,他只想将其开放给一些朋友模块,例如一个预定义的朋友模块列表。只有他们才能使用这些包。建议你宁可使用朋友依赖也不要使用实现依赖。