在上一篇随笔中介绍了用Jena对owl本体片断进行解析存储到mysql数据库中,本文将接上次的内容对存入到mysql中本体片断进行抽取然后可视化化显示。
把owl本体片断导入protage后的可视化的效果:
鼠标移到结点或边对象时,显示语义信息:
我所做的工作就是实现像protage一样用图形交互。我用的图形交互式可视化组件包是prefuse(到官网上下载 beta版或mater版),导入到JAVA工程中即可调用。
由于prefuse从db中读取数据->添充到自已的数据结构->着色、布置位置->渲染->呈现,这个过程是稳定,而且必须一次性完成,而且它的数据结构是稳定。
所以我的思路是,首先,建产稳定的Graph数据表,其有三个字段:url,name,type(用于标记是类还是实体),然后把所有类和对象属性实例从db中提取出来,填入到Graph数据表中,
然后,根据类之间,类与实例,实例与实例之间的语义关系添加边。
最后,可视化后鼠标移到结点或边上显示的语义信息是根据选中结点url(如果是边就是两个端点的url),从数据库中提取相应的语义信息,然后用tooltip(关于tooltip换行显示的方法可在我的随笔中找到)显示出来。
Java代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 import javax.swing.JFrame; 2 import javax.swing.JPanel; 3 import javax.swing.SwingUtilities; 4 import java.awt.BasicStroke; 5 import java.awt.Shape; 6 import java.awt.Graphics2D; 7 import java.awt.BorderLayout; 8 import java.awt.event.MouseEvent; 9 import java.util.Iterator; 10 import java.lang.String; 11 import prefuse.Constants; 12 import prefuse.Display; 13 import prefuse.Visualization; 14 import prefuse.action.ActionList; 15 import prefuse.action.GroupAction; 16 import prefuse.action.RepaintAction; 17 import prefuse.action.animate.ColorAnimator; 18 import prefuse.action.animate.PolarLocationAnimator; 19 import prefuse.action.animate.QualityControlAnimator; 20 import prefuse.action.animate.VisibilityAnimator; 21 import prefuse.action.assignment.ColorAction; 22 import prefuse.action.assignment.DataColorAction; 23 import prefuse.action.assignment.FontAction; 24 import prefuse.action.assignment.StrokeAction; 25 import prefuse.action.layout.CollapsedSubtreeLayout; 26 import prefuse.action.layout.graph.RadialTreeLayout; 27 import prefuse.activity.SlowInSlowOutPacer; 28 import prefuse.controls.ControlAdapter; 29 import prefuse.controls.DragControl; 30 import prefuse.controls.FocusControl; 31 import prefuse.controls.HoverActionControl; 32 import prefuse.controls.PanControl; 33 import prefuse.controls.WheelZoomControl; 34 import prefuse.data.Graph; 35 import prefuse.data.Node; 36 import prefuse.data.Table; 37 import prefuse.data.io.sql.*; 38 import prefuse.data.tuple.TupleSet; 39 import prefuse.render.DefaultRendererFactory; 40 import prefuse.render.LabelRenderer; 41 import prefuse.render.EdgeRenderer; 42 import prefuse.util.ColorLib; 43 import prefuse.util.FontLib; 44 import prefuse.visual.EdgeItem; 45 import prefuse.visual.VisualItem; 46 import prefuse.visual.expression.InGroupPredicate; 47 48 public class Buyer extends Display { 49 50 //jdbc driver name 51 public static final String driverName= "com.mysql.jdbc.Driver"; 52 // path for database 53 public static final String dbURL= "jdbc:mysql://localhost:3306/ontology?useUnicode=true&characterEncoding=utf8"; 54 //username 55 public static final String userName= "root"; 56 //password 57 public static final String userPwd= "sql123"; 58 59 60 private final String graph= "graph"; 61 private final String graphNodes = "graph.nodes"; 62 private final String graphEdges = "graph.edges"; 63 private final String linear = "linear"; 64 private static String label="name"; 65 private static Graph graphdata=null; 66 private static BasicStroke bsfocus=null,bslosefocus=null; 67 68 //public static Table classnodes=null; 69 //public static Table individualnodes=null; 70 public Buyer() 71 { 72 super(new Visualization()); 73 74 //第二步,创建Visualization把数据映射到abstraction中 75 graphdata=new Graph(true); //true表明有向图 76 bsfocus=new BasicStroke(4); 77 bslosefocus=new BasicStroke(1); 78 } 79 80 public void InitComponent() 81 { 82 m_vis.add(graph,graphdata); 83 //第三步,进行渲染根据abstraction中的数据 84 LabelRenderer labelrender=new LabelRenderer(label); 85 labelrender.setRoundedCorner(5,5); 86 labelrender.setMaxTextWidth(100); 87 EdgeRenderer edgesrender=new MyEdgeRenderer(Constants.EDGE_TYPE_CURVE,Constants.EDGE_ARROW_FORWARD); 88 //设置箭头大小 89 DefaultRendererFactory drf=new DefaultRendererFactory(); 90 drf.add(new InGroupPredicate(graphNodes),labelrender); 91 drf.add(new InGroupPredicate(graphEdges),edgesrender); 92 m_vis.setRendererFactory(drf); 93 int[] palette = new int[]{ColorLib.rgb(10,190,255),ColorLib.rgb(255,10,180)}; 94 95 DataColorAction fill = new DataColorAction(graphNodes, "type",Constants.NOMINAL, VisualItem.FILLCOLOR, palette); 96 ColorAction textColor = new ColorAction(graphNodes,VisualItem.TEXTCOLOR, ColorLib.gray(0)); 97 ColorAction edgesColor = new MyColorAction(graphEdges,VisualItem.STROKECOLOR); 98 FontAction fonts = new FontAction(graph, FontLib.getFont("宋体&新宋体",1,15)); 99 //着色动作100 ActionList color=new ActionList();101 color.add(fill); 102 color.add(textColor); 103 color.add(edgesColor); 104 color.add(fonts);105 m_vis.putAction("color",color);106 107 //更新动作序列108 ActionList update = new ActionList();109 update.add(new MyStrokeAction());110 update.add(new RepaintAction()); 111 m_vis.putAction("update", update);112 113 RadialTreeLayout treeLayout = new RadialTreeLayout(graph);114 //treeLayout.setAngularBounds(-Math.PI/2, Math.PI);115 m_vis.putAction("treeLayout", treeLayout);116 117 CollapsedSubtreeLayout subLayout = new CollapsedSubtreeLayout(graph);118 m_vis.putAction("subLayout", subLayout);119 120 // create the filtering and layout121 ActionList filter = new ActionList();122 filter.add(new TreeRootAction(graph));123 filter.add(color);124 filter.add(treeLayout);125 filter.add(subLayout);126 m_vis.putAction("filter", filter);127 128 // animated transition129 ActionList animate = new ActionList(1250);130 animate.setPacingFunction(new SlowInSlowOutPacer());131 132 animate.add(new QualityControlAnimator());133 animate.add(new VisibilityAnimator(graph)); //是否显示变动的动画过程134 animate.add(new PolarLocationAnimator(graph, linear));135 animate.add(new ColorAnimator(graphNodes));136 animate.add(new RepaintAction());137 m_vis.putAction("animate", animate);138 m_vis.alwaysRunAfter("filter", "animate");139 140 141 setSize(1000,700);142 addControlListener(new DragControl()); // drag items around143 addControlListener(new PanControl()); // pan with background left-drag144 addControlListener(new WheelZoomControl()); // zoom with vertical Wheel145 addControlListener(new FocusControl(1, "filter"));146 addControlListener(new HoverActionControl("repaint"));147 addControlListener(new DataMouseControl());148 // filter graph and perform layout149 m_vis.run("filter");150 }151 /**152 * @param args153 */154 public static void main(String[] args) {155 // TODO Auto-generated method stub156 DatabaseDataSource datasrc=null;157 try158 { 159 //create and load node of class 160 Table nodes= GetData("SELECT C_Uri,C_Name From ontologyclass"); 161 Table edges = GetData("SELECT x.C_Uri,y.curi FROM ontologyclass as x,tmpclass as y where x.C_Name=y.cvalue"); 162 163 164 Buyer buy=new Buyer();165 graphdata.addColumn("uri",java.lang.String.class);166 graphdata.addColumn("name", java.lang.String.class);167 graphdata.addColumn("type",java.lang.Character.class);168 169 //添加类结点170 buy.AddClassNode(nodes);171 //添加类之间的父子关系172 buy.AddEdges(edges,"C_Uri","curi","uri");173 174 //添加类之间的对象属性关系175 edges=GetData("SELECT * FROM property where Proty_Type=\'OP\'");176 buy.AddEdges(edges,"Proty_Domain","Proty_Range","name");177 178 //添加实例结点179 nodes=GetData("SELECT * from individual as x,property as y where x.Indiv_PURI=y.Proty_URI and y.Proty_Type='OP'"); 180 buy.AddIndividualNode(nodes);181 //添加实例和类之间的边182 edges=GetData("SELECT z.Indiv_ClaURI,z.Indiv_URI from property as y,individual as z where y.Proty_URI=z.Indiv_PURI and y.Proty_Type='OP'");183 buy.AddEdges(edges,"Indiv_ClaURI","Indiv_URI","uri");184 //添加实例间的关系185 edges=GetData("SELECT x.Indiv_URI,x.Indiv_PURI,y.iuri from individual as x,tmpindividual as y,property as z where x.Indiv_PVal=y.iname and y.ipuri=z.Proty_URI and z.Proty_Type='OP'");186 buy.AddEdges(edges,"Indiv_URI","iuri","uri");187 //初始化显示188 189 buy.InitComponent();190 //定制界面191 JPanel panel= new JPanel(new BorderLayout());192 panel.add(buy, BorderLayout.CENTER);193 JFrame frame = new JFrame("本体展示");194 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);195 frame.getContentPane().add(panel);196 frame.pack();197 frame.setVisible(true);198 }199 catch(Exception e)200 {201 e.printStackTrace();202 System.exit(1);203 }204 }205 206 public static Table GetData(String sql)207 {208 DatabaseDataSource datasrc =null; 209 Table table=null;210 try 211 { 212 // declare a datasource213 datasrc = ConnectionFactory.getDatabaseConnection(driverName, dbURL, userName, userPwd); 214 //create a table of data 215 table= datasrc.getData(sql); 216 } 217 catch (Exception e) 218 {219 e.printStackTrace();220 System.exit(1);221 }222 return table;223 }//end of static function GetData224 225 public static class TreeRootAction extends GroupAction 226 { 227 public TreeRootAction(String graphGroup) {228 super(graphGroup);229 230 }231 public void run(double frac) {232 TupleSet focus = m_vis.getGroup(Visualization.FOCUS_ITEMS);233 if ( focus==null || focus.getTupleCount() == 0 ) return;234 235 Graph g = (Graph)m_vis.getGroup(m_group);236 Node f = null;237 Iterator tuples = focus.tuples();238 while (tuples.hasNext() && !g.containsTuple(f=(Node)tuples.next()))239 {240 f = null;241 }242 if ( f == null ) return;243 g.getSpanningTree(f);244 }245 }//end of class TreeRootAction246 247 public class DataMouseControl extends ControlAdapter248 {249 private String uri=null; 250 String sql=null;251 private Graph g=null;252 Node startnode,targetnode;253 public String GetShowInformation()254 { 255 String relation=null;256 257 char sourcetype=(Character) startnode.get("type");258 char targettype=(Character) targetnode.get("type");259 switch(sourcetype)260 {261 case 'c':262 {263 if(targettype=='c')264 //处理都是类265 relation=GetRelationInfo(1);//表示类间关系266 else267 //处理一个类一个实例(肯定是类与实例关系)268 relation=startnode.getString("name")+"--has Individual-->"+targetnode.get("name");269 break;270 }271 272 case 's':273 { 274 //实例间的关系275 relation=GetRelationInfo(2);//表示实例间关系276 break;277 }278 279 }280 return relation;281 }282 283 public String GetRelationInfo(int type)284 { 285 String relation="";286 287 Table Relationtable;288 if (type==1)289 { //处理类间关系290 sql="SELECT C_Descript from ontologyclass where C_Name=\'"+291 targetnode.getString("name")+"\' and C_DescriptVal=\'"+startnode.getString("name")+"\'";292 Relationtable=GetData(sql);293 if(Relationtable.getRowCount()>0)294 relation=targetnode.getString("name")+"---"+Relationtable.getString(0,"C_Descript")+"--->"+startnode.getString("name");295 else296 { //说明这两个类之间不是父子关系,接下来尝试其它关系 297 sql="SELECT * FROM property where Proty_Type=\'OP\' and Proty_Domain=\'"+startnode.getString("name")+"\' and Proty_Range=\'"+targetnode.getString("name")+"\'";298 Relationtable=GetData(sql);299 for(int i=0;i值域)--->"+Relationtable.getString(i,"Proty_Range");302 }303 304 }305 }306 else307 {308 //处理实例间关系309 sql="SELECT x.Indiv_Name,x.Indiv_PURI,y.iname from individual as x,tmpindividual as y,property as z"+ 310 " where x.Indiv_PVal=y.iname and y.ipuri=z.Proty_URI and z.Proty_Type='OP' and x.Indiv_URI=\'"+startnode.getString("uri")+"\' and y.iuri=\'"+targetnode.getString("uri")+"\'";311 Relationtable=GetData(sql);312 if(Relationtable.getRowCount()>0)313 { 314 relation=Relationtable.getString(0,"Indiv_PURI").substring(Relationtable.getString(0,"Indiv_PURI").lastIndexOf("#")+1);315 relation=Relationtable.getString(0,"Indiv_Name")+"---"+relation+"--->"+Relationtable.getString(0,"iname");316 //System.out.print(relation);317 }318 319 }320 321 return relation;322 }323 public void itemEntered(VisualItem item, MouseEvent e)324 { 325 Display d = (Display)e.getSource();326 item.setHighlighted(true);327 //说明选中的是边328 if(item.getGroup().equals(graphEdges))329 { 330 //起始结点在图中结点号331 int startid=Integer.parseInt(item.getSourceTuple().getString(0));332 startnode=graphdata.getNode(startid);333 //目标结点在图中结点号334 int targetid=Integer.parseInt(item.getSourceTuple().getString(1));335 targetnode=graphdata.getNode(targetid);336 //System.out.print(relation);337 d.setToolTipText(GetShowInformation());338 m_vis.run("update");339 340 }341 else342 { 343 uri=item.getString("uri");344 String msg="";345 if((Character)item.get("type")=='c')346 { 347 //类结点处理348 msg="类名:"+item.getString("name")+" 资源URI:"+uri;349 sql="SELECT x.C_Name,z.Proty_Name,y.R_Type,y.R_Val,z.Proty_Range"350 +" FROM ontologyclass as x,propertyrestriction as y,property as z"+351 " WHERE x.C_Uri=y.R_Curi and y.R_Puri=z.Proty_URI and x.C_Uri=\'"+item.getString("uri")+"\'";352 Table restrictioninfo=GetData(sql);353 for(int i=0;i " +restrictioninfo.getstring(i,"c_name")+" "+restrictioninfo.getstring(i,"proty_name")+" "+restrictioninfo.getstring(i,"r_type")356 +"--"+restrictioninfo.getstring(i,"r_val")+" "+restrictioninfo.getstring(i,"proty_range");357 }358 ;359 } 360 else361 {362 msg="实例名:" +item.getstring("name")+" 资源URI:"+uri;363 //对象属性定义364 sql="SELECT x.Proty_Name,y.Indiv_Name,y.Indiv_PVal"365 +" FROM property as x,individual as y WHERE x.Proty_URI=y.Indiv_PURI "366 +"and x.Proty_Type='OP' and y.Indiv_URI=\'"+item.getString("uri")+"\'";367 Table restrictioninfo=GetData(sql);368 for(int i=0;i
最后的可视化效果:
蓝色结点是类,紫色结点是实例,类与类之间,类与实例,实例与实例之间用不同的线条颜色表示,鼠标移到边或结点对象时,显示相应的语义信息。
这样就完成owl本体片断的可视化,不过效果和protage的比差了些。
转载本文请标明出处。