前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >xwiki开发者指南-创建新的类属性类型

xwiki开发者指南-创建新的类属性类型

作者头像
lovelife110
发布2021-01-14 14:36:13
1.2K0
发布2021-01-14 14:36:13
举报
文章被收录于专栏:爱生活爱编程

此教程将指导你创建一个新的类属性类型,通过这种方式来扩展类编辑器。

此教程适用于XWiki 4.3M2以上版本。不要在旧版本尝试!

你应该先阅读XWiki数据模型来了解XWiki的类,对象,属性,然后编写一个XWiki组件,因为新的属性类型是通过组件来实现。

创建一个新的属性类型

作为一个例子,我们将创建一个可用于存储外部图像URL的"External Image"属性类型。让我们通过扩展PropertyClass来创建属性类型。不幸的是,这意味着你的Maven项目将不得不依赖XWiki的old core代码。

代码语言:javascript
复制
public class ExternalImageClass extends PropertyClass
{
   /**
     * Default constructor.
     */
   public ExternalImageClass()
   {
       // Specify the default name and pretty name of this XClass property. They can be overwritten from the class
       // editor when adding a property of this type to an XClass.
       super("externalImage", "External Image", null);
   }

   @Override
   public BaseProperty fromString(String value)
   {
        BaseProperty property = newProperty();
       // The stored value can be different than the value set by the user. You can do the needed transformations here.
       // In our case the value is an image URL so we keep it as it is. The reverse transformation, from the stored
       // value to the user friendly value, can be done in the property displayer.
       property.setValue(value);
       return property;
   }

   @Override
   public BaseProperty newProperty()
   {
       // The value of this XClass property is stored as a String. You have to use raw types here like StringProperty
       // because they are mapped to the database. Adding a new raw type implies modifying the Hibernate mapping and is
       // not the subject of this tutorial.
       BaseProperty property = new StringProperty();
        property.setName(getName());
       return property;
   }

   @Override
   public <T extends EntityReference> void mergeProperty(BaseProperty<T> currentProperty,
        BaseProperty<T> previousProperty, BaseProperty<T> newProperty, MergeConfiguration configuration,
        XWikiContext context, MergeResult mergeResult)
   {
       if (!Objects.equals(previousProperty, newProperty)) {
           if (Objects.equals(previousProperty, currentProperty)) {
                currentProperty.setValue(newProperty.getValue());
           } else {
               // Found conflict
               mergeResult.getLog().error("Collision found on property [{}] current has been modified", getName());
           }
       }
   }
}

注意,我们使用了一个StringProperty来存储我们的xclass属性的值。可用原始属性类型:

  • DateProperty
  • DBStringListProperty
  • DoubleProperty
  • FloatProperty
  • IntegerProperty
  • LargeStringProperty
  • LongProperty
  • StringListProperty
  • StringProperty

扩展这个列表是需要通过修改Hibernate映射,但不是这个教程的主题。你可以创建高级的类属性类型,但最终它们的值将被存储为这些原始类型之一。

此外,正如你所看到的我们为这种属性覆盖默认的mergeProperty实现,以确保URL不会合并逐个字符,而是作为整体。

下一步,我们为"External Image"属性类型创建一个provider。这用于将"External Image"属性类型添加到一个XClass(例如类编辑器)。

代码语言:javascript
复制
@Component
// Note that the component hint matches the name of the property class without the "Class" suffix. The reason is that
// the component hint must match the value returned by the #getClassType() method of your property class, which by
// default strips the "Class" suffix from the Java class name of your property class. If you want to use a different
// hint that doesn't follow this naming convention you need to override #getClassType().
@Named("ExternalImage")
@Singleton
public class ExternalImageClassProvider implements PropertyClassProvider
{
   @Override
   public PropertyClassInterface getInstance()
   {
       return new ExternalImageClass();
   }

   @Override
   public PropertyMetaClassInterface getDefinition()
   {
        PropertyMetaClass definition = new PropertyMetaClass();
       // This text will appear in the drop down list of property types to choose from in the class editor.
       definition.setPrettyName("External Image");
        definition.setName(getClass().getAnnotation(Named.class).value());

       // Add a meta property that will allows us to specify a CSS class name for the image HTML element.
       // NOTE: We define meta properties using XClass property types. This means for instance that you can define meta
       // properties of External Image type or whatever XClass property type you create.
       StringClass styleName = new StringClass();
        styleName.setName("styleName");
        styleName.setPrettyName("Style Name");
        definition.safeput(styleName.getName(), styleName);

       // The alternative text is required for a valid image HTML element so we add a meta property for it.
       StringClass placeholder = new StringClass();
        placeholder.setName("placeholder");
        placeholder.setPrettyName("Alternative Text");
        definition.safeput(placeholder.getName(), placeholder);

       // Add more meta properties here.

       return definition;
   }
}

provider就像一个我们属性类型工厂,但是它还定义了元属性列表。每一个类属性拥有元属性列表,这些控制属性如何展示和值如何解析等。这些meta属性的值是由一个类的所有实例共享。例如,如果你创建一个拥有"External Image"属性的类并且设置值,从类编辑,"styleName"元属性的值,所有类的对象将使用这值。

最后一步是在components.txt添加provider组件。

org.xwiki.example.internal.ExternalImageClassProvider

现在你可以编译你的Maven项目,把生成的jar复制到WEB-INF/lib文件夹下。重新启动服务器,就完成了。

使用新的属性类型

让我们创建一个类拥有"External Image"属性。你将在类编辑器的下拉列表框中看到"External Image"。

当你添加新属性到类之后,你可以设置它的所有的元属性。你会注意到,每个属性都有一个标准的元属性列表,比如name或者pretty name,还有一些特定的元属性,比如在我们的例子中的style name和alternative text。

保存这个类,然后在一个wiki页面上添加这个类对象(实例)。为此,你必须在对象模式来编辑wiki页面。

保存此页面,然后为我们的类创建一个sheet

{{velocity}} ; doc.displayPrettyName('screenshot', false, false) : doc.display('screenshot') {{/velocity}}

现在,如果你看看这个wiki页面,你会发现它看起来不太好看。这是因为"External Image"属性类型使用一个只显示值(图片URL)的默认的displayer。

为新的属性类型编写一个displayer

我们可以通过创建一个自定义displayer来改善我们的"External Image"属性显示。实现方法之一是通过在/templates/文件夹下创建一个Velocity模板displayer_externalimage.vm。

#if ($type == 'edit')

  #set($id = $escapetool.xml("${prefix}${name}"))

  <input type="text" id="$!id" name="$!id" value="$!escapetool.xml($value)" />

#elseif ($type == 'view')

  <img src="$escapetool.xml($value)" alt="$escapetool.xml($field.getProperty('placeholder').value)"

    class="$escapetool.xml($field.getProperty('styleName').value)" />

#else

  ## In order for the custom displayer to be taken into account, the result of its evaluation with an unknown display

  ## mode must not be empty. Let's output something.

  Unknown display mode.

#end

你可以阅读更多有关自定义displayer。现在,wiki页面应该在视图模式下好看多了。

在编辑模式下它看起来一样的,但是你可以扩展displayer提供图像预览。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/04/10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建一个新的属性类型
  • 使用新的属性类型
  • 为新的属性类型编写一个displayer
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档