Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Christnowx
Gephi
提交
b9d67a89
G
Gephi
项目概览
Christnowx
/
Gephi
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gephi
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b9d67a89
编写于
4月 09, 2013
作者:
M
Mathieu Bastian
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update ProcessorPlugin to the latest API
上级
223da54a
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
323 addition
and
411 deletion
+323
-411
modules/ProcessorPlugin/src/main/java/org/gephi/io/processor/plugin/AbstractProcessor.java
...java/org/gephi/io/processor/plugin/AbstractProcessor.java
+96
-123
modules/ProcessorPlugin/src/main/java/org/gephi/io/processor/plugin/AppendProcessor.java
...n/java/org/gephi/io/processor/plugin/AppendProcessor.java
+78
-120
modules/ProcessorPlugin/src/main/java/org/gephi/io/processor/plugin/DefaultProcessor.java
.../java/org/gephi/io/processor/plugin/DefaultProcessor.java
+76
-95
modules/ProcessorPlugin/src/main/java/org/gephi/io/processor/plugin/DefaultScaler.java
...ain/java/org/gephi/io/processor/plugin/DefaultScaler.java
+73
-73
未找到文件。
modules/ProcessorPlugin/src/main/java/org/gephi/io/processor/plugin/AbstractProcessor.java
浏览文件 @
b9d67a89
/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package
org.gephi.io.processor.plugin
;
import
java.awt.Color
;
import
org.gephi.data.attributes.api.AttributeColumn
;
import
org.gephi.data.attributes.api.AttributeModel
;
import
org.gephi.data.attributes.api.AttributeOrigin
;
import
org.gephi.data.attributes.api.AttributeRow
;
import
org.gephi.data.attributes.api.AttributeType
;
import
org.gephi.data.attributes.api.AttributeValue
;
import
org.gephi.data.attributes.type.DynamicFloat
;
import
org.gephi.data.attributes.type.Interval
;
import
org.gephi.data.properties.PropertiesColumn
;
import
org.gephi.dynamic.api.DynamicModel
;
import
org.gephi.attribute.api.AttributeModel
;
import
org.gephi.attribute.api.Origin
;
import
org.gephi.attribute.api.Table
;
import
org.gephi.graph.api.Edge
;
import
org.gephi.graph.api.Node
;
import
org.gephi.io.importer.api.ColumnDraft
;
import
org.gephi.io.importer.api.ContainerUnloader
;
import
org.gephi.io.importer.api.EdgeDraft
Getter
;
import
org.gephi.io.importer.api.NodeDraft
Getter
;
import
org.gephi.io.importer.api.EdgeDraft
;
import
org.gephi.io.importer.api.NodeDraft
;
import
org.gephi.project.api.Workspace
;
/**
...
...
@@ -69,123 +63,102 @@ public abstract class AbstractProcessor {
protected
ContainerUnloader
container
;
protected
AttributeModel
attributeModel
;
protected
void
flushToNode
(
NodeDraftGetter
nodeDraft
,
Node
node
)
{
protected
void
flushColumns
()
{
Table
nodeTable
=
attributeModel
.
getNodeTable
();
for
(
ColumnDraft
col
:
container
.
getNodeColumns
())
{
if
(!
nodeTable
.
hasColumn
(
col
.
getId
()))
{
nodeTable
.
addColumn
(
col
.
getId
(),
col
.
getTitle
(),
col
.
getTypeClass
(),
Origin
.
DATA
,
col
.
getDefaultValue
(),
true
);
}
}
Table
edgeTable
=
attributeModel
.
getEdgeTable
();
for
(
ColumnDraft
col
:
container
.
getEdgeColumns
())
{
if
(!
edgeTable
.
hasColumn
(
col
.
getId
()))
{
edgeTable
.
addColumn
(
col
.
getId
(),
col
.
getTitle
(),
col
.
getTypeClass
(),
Origin
.
DATA
,
col
.
getDefaultValue
(),
true
);
}
}
}
protected
void
flushToNode
(
NodeDraft
nodeDraft
,
Node
node
)
{
if
(
nodeDraft
.
getColor
()
!=
null
)
{
node
.
getNodeData
().
setR
(
nodeDraft
.
getColor
().
getRed
()
/
255
f
);
node
.
getNodeData
().
setG
(
nodeDraft
.
getColor
().
getGreen
()
/
255
f
);
node
.
getNodeData
().
setB
(
nodeDraft
.
getColor
().
getBlue
()
/
255
f
);
node
.
setColor
(
nodeDraft
.
getColor
());
}
if
(
nodeDraft
.
getLabel
()
!=
null
)
{
node
.
getNodeData
().
setLabel
(
nodeDraft
.
getLabel
());
node
.
setLabel
(
nodeDraft
.
getLabel
());
}
if
(
node
.
get
NodeData
().
getTextData
()
!=
null
)
{
node
.
get
NodeData
().
getTextData
().
setVisible
(
nodeDraft
.
isLabelVisible
());
if
(
node
.
get
TextProperties
()
!=
null
)
{
node
.
get
TextProperties
().
setVisible
(
nodeDraft
.
isLabelVisible
());
}
if
(
nodeDraft
.
getLabelColor
()
!=
null
&&
node
.
get
NodeData
().
getTextData
()
!=
null
)
{
if
(
nodeDraft
.
getLabelColor
()
!=
null
&&
node
.
get
TextProperties
()
!=
null
)
{
Color
labelColor
=
nodeDraft
.
getLabelColor
();
node
.
get
NodeData
().
getTextData
().
setColor
(
labelColor
.
getRed
()
/
255
f
,
labelColor
.
getGreen
()
/
255
f
,
labelColor
.
getBlue
()
/
255
f
,
labelColor
.
getAlpha
()
/
255
f
);
node
.
get
TextProperties
().
setColor
(
labelColor
);
}
if
(
nodeDraft
.
getLabelSize
()
!=
-
1
f
&&
node
.
get
NodeData
().
getTextData
()
!=
null
)
{
node
.
get
NodeData
().
getTextData
().
setSize
(
nodeDraft
.
getLabelSize
());
if
(
nodeDraft
.
getLabelSize
()
!=
-
1
f
&&
node
.
get
TextProperties
()
!=
null
)
{
node
.
get
TextProperties
().
setSize
(
nodeDraft
.
getLabelSize
());
}
node
.
getNodeData
().
setX
(
nodeDraft
.
getX
());
node
.
getNodeData
().
setY
(
nodeDraft
.
getY
());
node
.
getNodeData
().
setZ
(
nodeDraft
.
getZ
());
node
.
setX
(
nodeDraft
.
getX
());
node
.
setY
(
nodeDraft
.
getY
());
node
.
setZ
(
nodeDraft
.
getZ
());
if
(
nodeDraft
.
getSize
()
!=
0
&&
!
Float
.
isNaN
(
nodeDraft
.
getSize
()))
{
node
.
getNodeData
().
setSize
(
nodeDraft
.
getSize
());
node
.
setSize
(
nodeDraft
.
getSize
());
}
else
{
node
.
getNodeData
().
setSize
(
10
f
);
}
if
(
nodeDraft
.
getTimeInterval
()
!=
null
)
{
AttributeColumn
col
=
attributeModel
.
getNodeTable
().
getColumn
(
DynamicModel
.
TIMEINTERVAL_COLUMN
);
if
(
col
==
null
)
{
col
=
attributeModel
.
getNodeTable
().
addColumn
(
DynamicModel
.
TIMEINTERVAL_COLUMN
,
"Time Interval"
,
AttributeType
.
TIME_INTERVAL
,
AttributeOrigin
.
PROPERTY
,
null
);
}
node
.
getNodeData
().
getAttributes
().
setValue
(
col
.
getIndex
(),
nodeDraft
.
getTimeInterval
());
node
.
setSize
(
10
f
);
}
//Attributes
flushToNodeAttributes
(
nodeDraft
,
node
);
}
protected
void
flushToNodeAttributes
(
NodeDraftGetter
nodeDraft
,
Node
node
)
{
if
(
node
.
getNodeData
().
getAttributes
()
!=
null
)
{
AttributeRow
row
=
(
AttributeRow
)
node
.
getNodeData
().
getAttributes
();
for
(
AttributeValue
val
:
nodeDraft
.
getAttributeRow
().
getValues
())
{
if
(!
val
.
getColumn
().
getOrigin
().
equals
(
AttributeOrigin
.
PROPERTY
)
&&
val
.
getValue
()
!=
null
)
{
row
.
setValue
(
val
.
getColumn
(),
val
.
getValue
());
}
protected
void
flushToNodeAttributes
(
NodeDraft
nodeDraft
,
Node
node
)
{
for
(
ColumnDraft
col
:
container
.
getNodeColumns
())
{
Object
val
=
nodeDraft
.
getValue
(
col
.
getId
());
if
(
val
!=
null
)
{
node
.
setAttribute
(
col
.
getId
(),
val
);
}
}
}
protected
void
flushToEdge
(
EdgeDraft
Getter
edgeDraft
,
Edge
edge
)
{
protected
void
flushToEdge
(
EdgeDraft
edgeDraft
,
Edge
edge
)
{
if
(
edgeDraft
.
getColor
()
!=
null
)
{
edge
.
getEdgeData
().
setR
(
edgeDraft
.
getColor
().
getRed
()
/
255
f
);
edge
.
getEdgeData
().
setG
(
edgeDraft
.
getColor
().
getGreen
()
/
255
f
);
edge
.
getEdgeData
().
setB
(
edgeDraft
.
getColor
().
getBlue
()
/
255
f
);
edge
.
setColor
(
edgeDraft
.
getColor
());
}
else
{
edge
.
getEdgeData
().
setR
(-
1
f
);
edge
.
getEdgeData
().
setG
(-
1
f
);
edge
.
getEdgeData
().
setB
(-
1
f
);
edge
.
setR
(-
1
f
);
edge
.
setG
(-
1
f
);
edge
.
setB
(-
1
f
);
}
if
(
edgeDraft
.
getLabel
()
!=
null
)
{
edge
.
getEdgeData
().
setLabel
(
edgeDraft
.
getLabel
());
edge
.
setLabel
(
edgeDraft
.
getLabel
());
}
if
(
edge
.
get
EdgeData
().
getTextData
()
!=
null
)
{
edge
.
get
EdgeData
().
getTextData
().
setVisible
(
edgeDraft
.
isLabelVisible
());
if
(
edge
.
get
TextProperties
()
!=
null
)
{
edge
.
get
TextProperties
().
setVisible
(
edgeDraft
.
isLabelVisible
());
}
if
(
edgeDraft
.
getLabelSize
()
!=
-
1
f
&&
edge
.
get
EdgeData
().
getTextData
()
!=
null
)
{
edge
.
get
EdgeData
().
getTextData
().
setSize
(
edgeDraft
.
getLabelSize
());
if
(
edgeDraft
.
getLabelSize
()
!=
-
1
f
&&
edge
.
get
TextProperties
()
!=
null
)
{
edge
.
get
TextProperties
().
setSize
(
edgeDraft
.
getLabelSize
());
}
if
(
edgeDraft
.
getLabelColor
()
!=
null
&&
edge
.
get
EdgeData
().
getTextData
()
!=
null
)
{
if
(
edgeDraft
.
getLabelColor
()
!=
null
&&
edge
.
get
TextProperties
()
!=
null
)
{
Color
labelColor
=
edgeDraft
.
getLabelColor
();
edge
.
getEdgeData
().
getTextData
().
setColor
(
labelColor
.
getRed
()
/
255
f
,
labelColor
.
getGreen
()
/
255
f
,
labelColor
.
getBlue
()
/
255
f
,
labelColor
.
getAlpha
()
/
255
f
);
}
if
(
edgeDraft
.
getTimeInterval
()
!=
null
)
{
AttributeColumn
col
=
attributeModel
.
getEdgeTable
().
getColumn
(
DynamicModel
.
TIMEINTERVAL_COLUMN
);
if
(
col
==
null
)
{
col
=
attributeModel
.
getEdgeTable
().
addColumn
(
DynamicModel
.
TIMEINTERVAL_COLUMN
,
"Time Interval"
,
AttributeType
.
TIME_INTERVAL
,
AttributeOrigin
.
PROPERTY
,
null
);
}
edge
.
getEdgeData
().
getAttributes
().
setValue
(
col
.
getIndex
(),
edgeDraft
.
getTimeInterval
());
edge
.
getTextProperties
().
setColor
(
labelColor
);
}
//Attributes
flushToEdgeAttributes
(
edgeDraft
,
edge
);
}
protected
void
flushToEdgeAttributes
(
EdgeDraftGetter
edgeDraft
,
Edge
edge
)
{
if
(
edge
.
getEdgeData
().
getAttributes
()
!=
null
)
{
AttributeRow
row
=
(
AttributeRow
)
edge
.
getEdgeData
().
getAttributes
();
for
(
AttributeValue
val
:
edgeDraft
.
getAttributeRow
().
getValues
())
{
if
(!
val
.
getColumn
().
getOrigin
().
equals
(
AttributeOrigin
.
PROPERTY
)
&&
val
.
getValue
()
!=
null
)
{
row
.
setValue
(
val
.
getColumn
(),
val
.
getValue
());
}
}
}
//Dynamic Weight
AttributeColumn
dynamicWeightCol
=
container
.
getAttributeModel
().
getEdgeTable
().
getColumn
(
PropertiesColumn
.
EDGE_WEIGHT
.
getTitle
(),
AttributeType
.
DYNAMIC_FLOAT
);
if
(
dynamicWeightCol
!=
null
)
{
DynamicFloat
weight
=
(
DynamicFloat
)
edgeDraft
.
getAttributeRow
().
getValue
(
dynamicWeightCol
.
getIndex
());
AttributeRow
row
=
(
AttributeRow
)
edge
.
getEdgeData
().
getAttributes
();
if
(
weight
==
null
)
{
row
.
setValue
(
PropertiesColumn
.
EDGE_WEIGHT
.
getIndex
(),
new
DynamicFloat
(
new
Interval
<
Float
>(
Double
.
NEGATIVE_INFINITY
,
Double
.
POSITIVE_INFINITY
,
edgeDraft
.
getWeight
())));
}
else
{
row
.
setValue
(
PropertiesColumn
.
EDGE_WEIGHT
.
getIndex
(),
weight
);
protected
void
flushToEdgeAttributes
(
EdgeDraft
edgeDraft
,
Edge
edge
)
{
for
(
ColumnDraft
col
:
container
.
getEdgeColumns
())
{
Object
val
=
edgeDraft
.
getValue
(
col
.
getId
());
if
(
val
!=
null
)
{
edge
.
setAttribute
(
col
.
getId
(),
val
);
}
}
}
...
...
modules/ProcessorPlugin/src/main/java/org/gephi/io/processor/plugin/AppendProcessor.java
浏览文件 @
b9d67a89
/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package
org.gephi.io.processor.plugin
;
import
java.util.HashMap
;
import
java.util.Map
;
import
org.gephi.data.attributes.api.AttributeController
;
import
org.gephi.data.properties.PropertiesColumn
;
import
org.gephi.dynamic.api.DynamicController
;
import
org.gephi.dynamic.api.DynamicModel.TimeFormat
;
import
org.gephi.graph.api.Edge
;
import
org.gephi.graph.api.Graph
;
import
org.gephi.graph.api.GraphController
;
import
org.gephi.graph.api.GraphFactory
;
import
org.gephi.graph.api.GraphModel
;
import
org.gephi.graph.api.HierarchicalGraph
;
import
org.gephi.graph.api.Node
;
import
org.gephi.io.importer.api.EdgeD
raft.EdgeType
;
import
org.gephi.io.importer.api.EdgeDraft
Getter
;
import
org.gephi.io.importer.api.NodeDraft
Getter
;
import
org.gephi.io.importer.api.EdgeD
irection
;
import
org.gephi.io.importer.api.EdgeDraft
;
import
org.gephi.io.importer.api.NodeDraft
;
import
org.gephi.io.processor.spi.Processor
;
import
org.gephi.project.api.ProjectController
;
import
org.openide.util.Lookup
;
...
...
@@ -63,21 +58,23 @@ import org.openide.util.NbBundle;
import
org.openide.util.lookup.ServiceProvider
;
/**
* Processor 'Append graph' that tries to find in the current workspace nodes
and
*
edges in the container to only append new elements. It uses elements' id an
d
* label to do the matching.
* Processor 'Append graph' that tries to find in the current workspace nodes
*
and edges in the container to only append new elements. It uses elements' i
d
*
and
label to do the matching.
* <p>
* The attibutes are not merged and values are from the latest element imported.
*
*
* @author Mathieu Bastian
*/
@ServiceProvider
(
service
=
Processor
.
class
)
public
class
AppendProcessor
extends
AbstractProcessor
implements
Processor
{
@Override
public
String
getDisplayName
()
{
return
NbBundle
.
getMessage
(
AppendProcessor
.
class
,
"AppendProcessor.displayName"
);
}
@Override
public
void
process
()
{
ProjectController
pc
=
Lookup
.
getDefault
().
lookup
(
ProjectController
.
class
);
//Workspace
...
...
@@ -94,28 +91,15 @@ public class AppendProcessor extends AbstractProcessor implements Processor {
}
//Architecture
GraphModel
graphModel
=
Lookup
.
getDefault
().
lookup
(
GraphController
.
class
).
getModel
();
HierarchicalGraph
graph
=
null
;
switch
(
container
.
getEdgeDefault
())
{
case
DIRECTED:
graph
=
graphModel
.
getHierarchicalDirectedGraph
();
break
;
case
UNDIRECTED:
graph
=
graphModel
.
getHierarchicalUndirectedGraph
();
break
;
case
MIXED:
graph
=
graphModel
.
getHierarchicalMixedGraph
();
break
;
default
:
graph
=
graphModel
.
getHierarchicalMixedGraph
();
break
;
}
GraphController
graphController
=
Lookup
.
getDefault
().
lookup
(
GraphController
.
class
);
GraphModel
graphModel
=
Lookup
.
getDefault
().
lookup
(
GraphController
.
class
).
getGraphModel
();
Graph
graph
=
graphModel
.
getGraph
();
GraphFactory
factory
=
graphModel
.
factory
();
//Attributes - Creates columns for properties
attributeModel
=
Lookup
.
getDefault
().
lookup
(
AttributeController
.
class
).
get
Model
();
attributeModel
.
mergeModel
(
container
.
getAttributeModel
()
);
attributeModel
=
graphController
.
getAttribute
Model
();
flushColumns
(
);
//Dynamic
if
(
container
.
getTimeFormat
()
!=
null
)
{
...
...
@@ -123,73 +107,47 @@ public class AppendProcessor extends AbstractProcessor implements Processor {
dynamicController
.
setTimeFormat
(
container
.
getTimeFormat
());
}
//Index existing graph
Map
<
String
,
Node
>
map
=
new
HashMap
<
String
,
Node
>();
for
(
Node
n
:
graph
.
getNodes
())
{
String
id
=
n
.
getNodeData
().
getId
();
if
(
id
!=
null
&&
!
id
.
equalsIgnoreCase
(
String
.
valueOf
(
n
.
getId
())))
{
map
.
put
(
id
,
n
);
}
if
(
n
.
getNodeData
().
getLabel
()
!=
null
&&
!
n
.
getNodeData
().
getLabel
().
isEmpty
())
{
map
.
put
(
n
.
getNodeData
().
getLabel
(),
n
);
}
}
int
nodeCount
=
0
;
//Create all nodes
for
(
NodeDraftGetter
draftNode
:
container
.
getNodes
())
{
Node
n
;
for
(
NodeDraft
draftNode
:
container
.
getNodes
())
{
String
id
=
draftNode
.
getId
();
String
label
=
draftNode
.
getLabel
();
if
(!
draftNode
.
isAutoId
()
&&
id
!=
null
&&
map
.
get
(
id
)
!=
null
)
{
n
=
map
.
get
(
id
);
}
else
if
(
label
!=
null
&&
map
.
get
(
label
)
!=
null
)
{
n
=
map
.
get
(
label
);
}
else
{
n
=
factory
.
newNode
(
draftNode
.
isAutoId
()?
null
:
id
);
Node
node
=
graph
.
getNode
(
id
);
if
(
node
==
null
)
{
node
=
factory
.
newNode
(
id
);
graph
.
addNode
(
node
);
nodeCount
++;
}
flushToNode
(
draftNode
,
n
);
draftNode
.
setNode
(
n
);
}
//Push nodes in data structure
for
(
NodeDraftGetter
draftNode
:
container
.
getNodes
())
{
Node
n
=
draftNode
.
getNode
();
NodeDraftGetter
[]
parents
=
draftNode
.
getParents
();
if
(
parents
!=
null
)
{
for
(
int
i
=
0
;
i
<
parents
.
length
;
i
++)
{
Node
parent
=
parents
[
i
].
getNode
();
graph
.
addNode
(
n
,
parent
);
}
}
else
{
graph
.
addNode
(
n
);
}
flushToNode
(
draftNode
,
node
);
}
//Create all edges and push to data structure
int
edgeCount
=
0
;
for
(
EdgeDraftGetter
edge
:
container
.
getEdges
())
{
Node
source
=
edge
.
getSource
().
getNode
();
Node
target
=
edge
.
getTarget
().
getNode
();
if
(
graph
.
getEdge
(
source
,
target
)
==
null
)
{
Edge
e
=
null
;
for
(
EdgeDraft
draftEdge
:
container
.
getEdges
())
{
String
id
=
draftEdge
.
getId
();
String
sourceId
=
draftEdge
.
getSource
().
getId
();
String
targetId
=
draftEdge
.
getTarget
().
getId
();
Node
source
=
graph
.
getNode
(
sourceId
);
Node
target
=
graph
.
getNode
(
targetId
);
Object
type
=
draftEdge
.
getType
();
int
edgeType
=
graphModel
.
addEdgeType
(
type
);
Edge
edge
=
graph
.
getEdge
(
source
,
target
,
edgeType
);
if
(
edge
==
null
)
{
switch
(
container
.
getEdgeDefault
())
{
case
DIRECTED:
e
=
factory
.
newEdge
(
edge
.
isAutoId
()?
null
:
edge
.
getId
(),
source
,
target
,
e
dge
.
getWeight
(),
true
);
e
dge
=
factory
.
newEdge
(
id
,
source
,
target
,
edgeType
,
draftE
dge
.
getWeight
(),
true
);
break
;
case
UNDIRECTED:
e
=
factory
.
newEdge
(
edge
.
isAutoId
()?
null
:
edge
.
getId
(),
source
,
target
,
edge
.
getWeight
(),
fals
e
);
e
dge
=
factory
.
newEdge
(
id
,
source
,
target
,
edgeType
,
draftEdge
.
getWeight
(),
tru
e
);
break
;
case
MIXED:
e
=
factory
.
newEdge
(
edge
.
isAutoId
()?
null
:
edge
.
getId
(),
source
,
target
,
edge
.
getWeight
(),
edge
.
getType
().
equals
(
EdgeType
.
UNDIRECTED
)
?
false
:
true
)
;
break
;
boolean
directed
=
draftEdge
.
getDirection
().
equals
(
EdgeDirection
.
UNDIRECTED
)
?
false
:
true
;
edge
=
factory
.
newEdge
(
id
,
source
,
target
,
edgeType
,
draftEdge
.
getWeight
(),
directed
)
;
}
flushToEdge
(
edge
,
e
);
edgeCount
++;
graph
.
addEdge
(
e
);
graph
.
addEdge
(
e
dge
);
}
flushToEdge
(
draftEdge
,
edge
);
}
System
.
out
.
println
(
"# New Nodes appended: "
+
nodeCount
+
"\n# New Edges appended: "
+
edgeCount
);
...
...
modules/ProcessorPlugin/src/main/java/org/gephi/io/processor/plugin/DefaultProcessor.java
浏览文件 @
b9d67a89
/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package
org.gephi.io.processor.plugin
;
import
org.gephi.data.attributes.api.AttributeController
;
import
org.gephi.dynamic.api.DynamicController
;
import
org.gephi.graph.api.Edge
;
import
org.gephi.graph.api.Graph
;
import
org.gephi.graph.api.GraphController
;
import
org.gephi.graph.api.GraphFactory
;
import
org.gephi.graph.api.GraphModel
;
import
org.gephi.graph.api.HierarchicalGraph
;
import
org.gephi.graph.api.Node
;
import
org.gephi.io.importer.api.EdgeD
raft.EdgeType
;
import
org.gephi.io.importer.api.EdgeDraft
Getter
;
import
org.gephi.io.importer.api.NodeDraft
Getter
;
import
org.gephi.io.importer.api.EdgeD
irection
;
import
org.gephi.io.importer.api.EdgeDraft
;
import
org.gephi.io.importer.api.NodeDraft
;
import
org.gephi.io.processor.spi.Processor
;
import
org.gephi.project.api.ProjectController
;
import
org.openide.util.Lookup
;
...
...
@@ -61,16 +60,18 @@ import org.openide.util.lookup.ServiceProvider;
/**
* Processor 'Add full graph' that unloads the complete container into the
* workspace.
*
* @author
Mathieu Bastian
*
* @author Mathieu Bastian
*/
@ServiceProvider
(
service
=
Processor
.
class
,
position
=
10
)
public
class
DefaultProcessor
extends
AbstractProcessor
implements
Processor
{
@Override
public
String
getDisplayName
()
{
return
NbBundle
.
getMessage
(
DefaultProcessor
.
class
,
"DefaultProcessor.displayName"
);
}
@Override
public
void
process
()
{
//Workspace
ProjectController
pc
=
Lookup
.
getDefault
().
lookup
(
ProjectController
.
class
);
...
...
@@ -83,28 +84,15 @@ public class DefaultProcessor extends AbstractProcessor implements Processor {
}
//Architecture
GraphModel
graphModel
=
Lookup
.
getDefault
().
lookup
(
GraphController
.
class
).
getModel
();
HierarchicalGraph
graph
=
null
;
switch
(
container
.
getEdgeDefault
())
{
case
DIRECTED:
graph
=
graphModel
.
getHierarchicalDirectedGraph
();
break
;
case
UNDIRECTED:
graph
=
graphModel
.
getHierarchicalUndirectedGraph
();
break
;
case
MIXED:
graph
=
graphModel
.
getHierarchicalMixedGraph
();
break
;
default
:
graph
=
graphModel
.
getHierarchicalMixedGraph
();
break
;
}
GraphController
graphController
=
Lookup
.
getDefault
().
lookup
(
GraphController
.
class
);
GraphModel
graphModel
=
Lookup
.
getDefault
().
lookup
(
GraphController
.
class
).
getGraphModel
();
Graph
graph
=
graphModel
.
getGraph
();;
GraphFactory
factory
=
graphModel
.
factory
();
//Attributes - Creates columns for properties
attributeModel
=
Lookup
.
getDefault
().
lookup
(
AttributeController
.
class
).
get
Model
();
attributeModel
.
mergeModel
(
container
.
getAttributeModel
()
);
attributeModel
=
graphController
.
getAttribute
Model
();
flushColumns
(
);
//Dynamic
if
(
container
.
getTimeFormat
()
!=
null
)
{
...
...
@@ -116,50 +104,43 @@ public class DefaultProcessor extends AbstractProcessor implements Processor {
int
nodeCount
=
0
;
//Create all nodes
for
(
NodeDraftGetter
draftNode
:
container
.
getNodes
())
{
Node
n
=
factory
.
newNode
(
draftNode
.
isAutoId
()
?
null
:
draftNode
.
getId
());
flushToNode
(
draftNode
,
n
);
draftNode
.
setNode
(
n
);
//Create all nodes
for
(
NodeDraft
draftNode
:
container
.
getNodes
())
{
String
id
=
draftNode
.
getId
();
Node
node
=
factory
.
newNode
(
id
);
graph
.
addNode
(
node
);
nodeCount
++;
}
//Push nodes in data structure
for
(
NodeDraftGetter
draftNode
:
container
.
getNodes
())
{
Node
n
=
draftNode
.
getNode
();
NodeDraftGetter
[]
parents
=
draftNode
.
getParents
();
if
(
parents
!=
null
)
{
for
(
int
i
=
0
;
i
<
parents
.
length
;
i
++)
{
Node
parent
=
parents
[
i
].
getNode
();
graph
.
addNode
(
n
,
parent
);
}
}
else
{
graph
.
addNode
(
n
);
}
flushToNode
(
draftNode
,
node
);
}
//Create all edges and push to data structure
int
edgeCount
=
0
;
for
(
EdgeDraftGetter
edge
:
container
.
getEdges
())
{
Node
source
=
edge
.
getSource
().
getNode
();
Node
target
=
edge
.
getTarget
().
getNode
();
Edge
e
=
null
;
for
(
EdgeDraft
draftEdge
:
container
.
getEdges
())
{
String
id
=
draftEdge
.
getId
();
String
sourceId
=
draftEdge
.
getSource
().
getId
();
String
targetId
=
draftEdge
.
getTarget
().
getId
();
Node
source
=
graph
.
getNode
(
sourceId
);
Node
target
=
graph
.
getNode
(
targetId
);
Object
type
=
draftEdge
.
getType
();
int
edgeType
=
graphModel
.
addEdgeType
(
type
);
Edge
edge
=
graph
.
getEdge
(
source
,
target
,
edgeType
);
switch
(
container
.
getEdgeDefault
())
{
case
DIRECTED:
e
=
factory
.
newEdge
(
edge
.
isAutoId
()
?
null
:
edge
.
getId
(),
source
,
target
,
e
dge
.
getWeight
(),
true
);
e
dge
=
factory
.
newEdge
(
id
,
source
,
target
,
edgeType
,
draftE
dge
.
getWeight
(),
true
);
break
;
case
UNDIRECTED:
e
=
factory
.
newEdge
(
edge
.
isAutoId
()
?
null
:
edge
.
getId
(),
source
,
target
,
edge
.
getWeight
(),
fals
e
);
e
dge
=
factory
.
newEdge
(
id
,
source
,
target
,
edgeType
,
draftEdge
.
getWeight
(),
tru
e
);
break
;
case
MIXED:
e
=
factory
.
newEdge
(
edge
.
isAutoId
()
?
null
:
edge
.
getId
(),
source
,
target
,
edge
.
getWeight
(),
edge
.
getType
().
equals
(
EdgeType
.
UNDIRECTED
)
?
false
:
true
)
;
break
;
boolean
directed
=
draftEdge
.
getDirection
().
equals
(
EdgeDirection
.
UNDIRECTED
)
?
false
:
true
;
edge
=
factory
.
newEdge
(
id
,
source
,
target
,
edgeType
,
draftEdge
.
getWeight
(),
directed
)
;
}
flushToEdge
(
edge
,
e
);
edgeCount
++;
graph
.
addEdge
(
e
);
}
graph
.
addEdge
(
edge
);
flushToEdge
(
draftEdge
,
edge
);
}
System
.
out
.
println
(
"# Nodes loaded: "
+
nodeCount
+
"\n# Edges loaded: "
+
edgeCount
);
workspace
=
null
;
}
...
...
modules/ProcessorPlugin/src/main/java/org/gephi/io/processor/plugin/DefaultScaler.java
浏览文件 @
b9d67a89
/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package
org.gephi.io.processor.plugin
;
import
java.util.Collection
;
import
org.gephi.io.importer.api.Container
;
import
org.gephi.io.importer.api.NodeDraft
Getter
;
import
org.gephi.io.importer.api.NodeDraft
;
import
org.gephi.io.processor.spi.Scaler
;
import
org.openide.util.lookup.ServiceProvider
;
...
...
@@ -68,6 +67,7 @@ public class DefaultScaler implements Scaler {
octreeLimit
=
5000
;
}
@Override
public
void
doScale
(
Container
container
)
{
setDefaults
();
...
...
@@ -82,24 +82,24 @@ public class DefaultScaler implements Scaler {
float
sizeRatio
=
0
f
;
float
averageSize
=
2.5f
;
Collection
<?
extends
NodeDraftGetter
>
nodes
=
container
.
getUnloader
().
getNodes
();
//Recenter
double
centroidX
=
0
;
double
centroidY
=
0
;
for
(
NodeDraftGetter
node
:
nodes
)
{
int
nodeSize
=
0
;
for
(
NodeDraft
node
:
container
.
getUnloader
().
getNodes
())
{
centroidX
+=
node
.
getX
();
centroidY
+=
node
.
getY
();
nodeSize
++;
}
centroidX
/=
node
s
.
size
()
;
centroidY
/=
node
s
.
size
()
;
for
(
NodeDraft
Getter
node
:
nodes
)
{
centroidX
/=
node
Size
;
centroidY
/=
node
Size
;
for
(
NodeDraft
node
:
container
.
getUnloader
().
getNodes
()
)
{
node
.
setX
((
float
)
(
node
.
getX
()
-
centroidX
));
node
.
setY
((
float
)
(
node
.
getY
()
-
centroidY
));
}
//Measure
for
(
NodeDraft
Getter
node
:
nodes
)
{
for
(
NodeDraft
node
:
container
.
getUnloader
().
getNodes
()
)
{
sizeMin
=
Math
.
min
(
node
.
getSize
(),
sizeMin
);
sizeMax
=
Math
.
max
(
node
.
getSize
(),
sizeMax
);
xMin
=
Math
.
min
(
node
.
getX
(),
xMin
);
...
...
@@ -141,7 +141,7 @@ public class DefaultScaler implements Scaler {
averageSize
=
0
f
;
//Scale node size
for
(
NodeDraft
Getter
node
:
nodes
)
{
for
(
NodeDraft
node
:
container
.
getUnloader
().
getNodes
()
)
{
float
size
=
(
node
.
getSize
()
-
sizeMin
)
*
sizeRatio
+
sizeMinimum
;
node
.
setSize
(
size
);
node
.
setX
(
node
.
getX
()
*
sizeRatio
);
...
...
@@ -149,30 +149,30 @@ public class DefaultScaler implements Scaler {
node
.
setZ
(
node
.
getZ
()
*
sizeRatio
);
averageSize
+=
size
;
}
averageSize
/=
container
.
getUnloader
().
getNodes
().
size
()
;
averageSize
/=
nodeSize
;
}
/*
float weightMin = Float.POSITIVE_INFINITY;
float weightMax = Float.NEGATIVE_INFINITY;
float weightRatio = 0f;
//Measure
weightMaximum = averageSize * 0.8f;
for (EdgeDraftGetter edge : container.getUnloader().getEdges()) {
weightMin = Math.min(edge.getWeight(), weightMin);
weightMax = Math.max(edge.getWeight(), weightMax);
}
if (weightMin == weightMax) {
weightRatio = weightMinimum / weightMin;
} else {
weightRatio = Math.abs((weightMaximum - weightMinimum) / (weightMax - weightMin));
}
//Scale edge weight
for (EdgeDraftGetter edge : container.getUnloader().getEdges()) {
float weight = (edge.getWeight() - weightMin) * weightRatio + weightMinimum;
assert !Float.isNaN(weight);
edge.setWeight(weight);
}*/
float weightMin = Float.POSITIVE_INFINITY;
float weightMax = Float.NEGATIVE_INFINITY;
float weightRatio = 0f;
//Measure
weightMaximum = averageSize * 0.8f;
for (EdgeDraftGetter edge : container.getUnloader().getEdges()) {
weightMin = Math.min(edge.getWeight(), weightMin);
weightMax = Math.max(edge.getWeight(), weightMax);
}
if (weightMin == weightMax) {
weightRatio = weightMinimum / weightMin;
} else {
weightRatio = Math.abs((weightMaximum - weightMinimum) / (weightMax - weightMin));
}
//Scale edge weight
for (EdgeDraftGetter edge : container.getUnloader().getEdges()) {
float weight = (edge.getWeight() - weightMin) * weightRatio + weightMinimum;
assert !Float.isNaN(weight);
edge.setWeight(weight);
}*/
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录