Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
atlas
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
dataplatform
atlas
Commits
04997e4c
Commit
04997e4c
authored
Jan 23, 2015
by
Ballistar13
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Generalized Bridges
Replaced BridgeManager Designed EnitityBeans
parent
e0699c8f
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
290 additions
and
27 deletions
+290
-27
ABridge.java
.../main/java/org/apache/hadoop/metadata/bridge/ABridge.java
+104
-0
AEnitityBean.java
.../java/org/apache/hadoop/metadata/bridge/AEnitityBean.java
+41
-0
BridgeAssistant.java
...va/org/apache/hadoop/metadata/bridge/BridgeAssistant.java
+0
-14
BridgeException.java
...va/org/apache/hadoop/metadata/bridge/BridgeException.java
+4
-0
BridgeManager.java
...java/org/apache/hadoop/metadata/bridge/BridgeManager.java
+108
-2
IBridge.java
.../main/java/org/apache/hadoop/metadata/bridge/IBridge.java
+2
-6
HiveLineageBridge.java
...hadoop/metadata/bridge/hivelineage/HiveLineageBridge.java
+2
-2
HiveMetaImporter.java
...adoop/metadata/bridge/hivestructure/HiveMetaImporter.java
+1
-0
HiveStructureBridge.java
...op/metadata/bridge/hivestructure/HiveStructureBridge.java
+5
-3
bridge-manager.properties
...-bridge-core/src/main/resources/bridge-manager.properties
+5
-0
BridgeManagerTest.java
...apache/hadoop/metadata/bridge/test/BridgeManagerTest.java
+13
-0
test-bridge-manager.properties
...ge-core/src/test/resources/test-bridge-manager.properties
+5
-0
No files found.
metadata-bridge-parent/metadata-bridge-core/src/main/java/org/apache/hadoop/metadata/bridge/ABridge.java
0 → 100644
View file @
04997e4c
package
org
.
apache
.
hadoop
.
metadata
.
bridge
;
import
java.lang.reflect.InvocationTargetException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
javax.inject.Inject
;
import
org.apache.hadoop.metadata.ITypedReferenceableInstance
;
import
org.apache.hadoop.metadata.MetadataException
;
import
org.apache.hadoop.metadata.repository.MetadataRepository
;
import
org.apache.hadoop.metadata.storage.RepositoryException
;
import
org.apache.hadoop.metadata.types.AttributeDefinition
;
import
org.apache.hadoop.metadata.types.ClassType
;
import
org.apache.hadoop.metadata.types.HierarchicalTypeDefinition
;
import
org.apache.hadoop.metadata.types.Multiplicity
;
import
org.apache.hadoop.metadata.types.TypeSystem
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.google.common.collect.ImmutableList
;
public
abstract
class
ABridge
implements
IBridge
{
protected
ArrayList
<
Class
<
AEnitityBean
>>
typeBeanClasses
;
protected
MetadataRepository
repo
;
protected
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
"BridgeLogger"
);
protected
HierarchicalTypeDefinition
<
ClassType
>
createClassTypeDef
(
String
name
,
ImmutableList
<
String
>
superTypes
,
AttributeDefinition
...
attrDefs
)
{
return
new
HierarchicalTypeDefinition
(
ClassType
.
class
,
name
,
superTypes
,
attrDefs
);}
public
ArrayList
<
Class
<
AEnitityBean
>>
getTypeBeanClasses
()
{
return
typeBeanClasses
;
}
@Inject
ABridge
(
MetadataRepository
repo
)
{
this
.
repo
=
repo
;
}
public
<
t
extends
AEnitityBean
>
Object
get
(
String
id
)
throws
RepositoryException
{
// get from the system by id (?)
ITypedReferenceableInstance
ref
=
repo
.
getEntityDefinition
(
id
);
// turn into a HiveLineageBean
try
{
Class
<
AEnitityBean
>
c
=
getTypeBeanInListByName
(
ref
.
getTypeName
());
return
c
.
newInstance
().
convertFromITypedReferenceable
(
ref
);
}
catch
(
BridgeException
|
InstantiationException
|
IllegalAccessException
|
IllegalArgumentException
|
InvocationTargetException
|
NoSuchMethodException
|
SecurityException
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
return
null
;
}
public
String
create
(
AEnitityBean
bean
)
throws
MetadataException
{
ClassType
type
=
TypeSystem
.
getInstance
().
getDataType
(
ClassType
.
class
,
bean
.
getClass
().
getSimpleName
());
ITypedReferenceableInstance
refBean
=
null
;
try
{
refBean
=
type
.
convert
(
bean
.
convertToReferencable
(),
Multiplicity
.
REQUIRED
);
String
id
=
repo
.
createEntity
(
refBean
,
type
.
getName
());
return
id
;
}
catch
(
IllegalArgumentException
|
IllegalAccessException
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
throw
new
MetadataException
(
"Cannot create entity"
);
}
public
Iterable
<
String
>
list
()
throws
RepositoryException
{
List
<
String
>
returnList
=
null
;
for
(
Class
c
:
typeBeanClasses
){
List
<
String
>
inBetweenList
=
repo
.
getEntityList
(
c
.
getSimpleName
());
try
{
returnList
.
addAll
(
inBetweenList
);}
catch
(
NullPointerException
e
){
returnList
=
inBetweenList
;}
}
return
returnList
;
}
protected
final
boolean
containsType
(
String
s
){
for
(
Class
c:
typeBeanClasses
){
if
(
c
.
getSimpleName
().
equals
(
s
)){
return
true
;
}
}
return
false
;
}
protected
final
Class
<
AEnitityBean
>
getTypeBeanInListByName
(
String
s
)
throws
BridgeException
{
if
(
containsType
(
s
)){
for
(
Class
c:
typeBeanClasses
){
if
(
c
.
getSimpleName
().
equals
(
s
)){
return
c
;
}
}
}
else
{
throw
new
BridgeException
(
"No EntityBean Definition Found"
);
}
throw
new
BridgeException
(
"No EntityBean Definition Found"
);
}
}
metadata-bridge-parent/metadata-bridge-core/src/main/java/org/apache/hadoop/metadata/bridge/AEnitityBean.java
0 → 100644
View file @
04997e4c
package
org
.
apache
.
hadoop
.
metadata
.
bridge
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.InvocationTargetException
;
import
java.util.Map.Entry
;
import
org.apache.hadoop.metadata.ITypedReferenceableInstance
;
import
org.apache.hadoop.metadata.MetadataException
;
import
org.apache.hadoop.metadata.Referenceable
;
import
org.apache.hadoop.metadata.types.AttributeInfo
;
public
abstract
class
AEnitityBean
{
public
final
Referenceable
convertToReferencable
()
throws
IllegalArgumentException
,
IllegalAccessException
{
Referenceable
selfAware
=
new
Referenceable
(
this
.
getClass
().
getSimpleName
());
for
(
Field
f
:
this
.
getClass
().
getFields
()){
selfAware
.
set
(
f
.
getName
(),
f
.
get
(
this
));
}
return
selfAware
;
}
public
final
<
t
extends
AEnitityBean
>
Object
convertFromITypedReferenceable
(
ITypedReferenceableInstance
instance
)
throws
InstantiationException
,
IllegalAccessException
,
IllegalArgumentException
,
InvocationTargetException
,
NoSuchMethodException
,
SecurityException
,
BridgeException
{
if
(!
instance
.
getTypeName
().
equals
(
this
.
getClass
().
getSimpleName
())){
throw
new
BridgeException
(
"ReferenceableInstance type not the same as bean"
);
}
Object
retObj
=
this
.
getClass
().
newInstance
();
for
(
Entry
<
String
,
AttributeInfo
>
e
:
instance
.
fieldMapping
().
fields
.
entrySet
()){
try
{
String
convertedName
=
e
.
getKey
().
substring
(
0
,
1
).
toUpperCase
()+
e
.
getKey
().
substring
(
1
);
this
.
getClass
().
getMethod
(
"set"
+
convertedName
,
Class
.
forName
(
e
.
getValue
().
dataType
().
getName
())).
invoke
(
this
,
instance
.
get
(
e
.
getKey
()));
}
catch
(
MetadataException
|
ClassNotFoundException
e1
)
{
// TODO Auto-generated catch block
e1
.
printStackTrace
();
}
}
return
retObj
;
}
}
metadata-bridge-parent/metadata-bridge-core/src/main/java/org/apache/hadoop/metadata/bridge/BridgeAssistant.java
deleted
100644 → 0
View file @
e0699c8f
package
org
.
apache
.
hadoop
.
metadata
.
bridge
;
import
org.apache.hadoop.metadata.types.AttributeDefinition
;
import
org.apache.hadoop.metadata.types.ClassType
;
import
org.apache.hadoop.metadata.types.HierarchicalTypeDefinition
;
import
org.apache.hadoop.metadata.types.TypeSystem
;
import
com.google.common.collect.ImmutableList
;
public
class
BridgeAssistant
{
protected
HierarchicalTypeDefinition
<
ClassType
>
createClassTypeDef
(
String
name
,
ImmutableList
<
String
>
superTypes
,
AttributeDefinition
...
attrDefs
)
{
return
new
HierarchicalTypeDefinition
(
ClassType
.
class
,
name
,
superTypes
,
attrDefs
);}
}
metadata-bridge-parent/metadata-bridge-core/src/main/java/org/apache/hadoop/metadata/bridge/BridgeException.java
View file @
04997e4c
...
@@ -4,6 +4,10 @@ import org.apache.hadoop.hive.metastore.api.MetaException;
...
@@ -4,6 +4,10 @@ import org.apache.hadoop.hive.metastore.api.MetaException;
public
class
BridgeException
extends
MetaException
{
public
class
BridgeException
extends
MetaException
{
public
BridgeException
(
String
msg
)
{
super
(
string
);
}
/**
/**
*
*
*/
*/
...
...
metadata-bridge-parent/metadata-bridge-core/src/main/java/org/apache/hadoop/metadata/bridge/BridgeManager.java
View file @
04997e4c
package
org
.
apache
.
hadoop
.
metadata
.
bridge
;
package
org
.
apache
.
hadoop
.
metadata
.
bridge
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.lang.reflect.Field
;
import
java.util.ArrayList
;
import
java.util.Properties
;
import
javax.inject.Inject
;
import
org.apache.hadoop.metadata.MetadataException
;
import
org.apache.hadoop.metadata.repository.MetadataRepository
;
import
org.apache.hadoop.metadata.types.AttributeDefinition
;
import
org.apache.hadoop.metadata.types.ClassType
;
import
org.apache.hadoop.metadata.types.HierarchicalTypeDefinition
;
import
org.apache.hadoop.metadata.types.Multiplicity
;
import
org.apache.hadoop.metadata.types.TypeSystem
;
import
org.apache.hadoop.metadata.types.TypeSystem
;
public
class
BridgeManager
{
public
class
BridgeManager
{
TypeSystem
ts
;
TypeSystem
ts
;
ArrayList
<
ABridge
>
activeBridges
;
private
final
static
String
bridgeFileDefault
=
"bridge-manager.properties"
;
@Inject
BridgeManager
(
MetadataRepository
rs
){
this
.
ts
=
TypeSystem
.
getInstance
();
if
(
System
.
getProperty
(
"bridgeManager.propsFile"
)
!=
null
|
!
System
.
getProperty
(
"bridgeManager.propsFile"
).
isEmpty
()){
setActiveBridges
(
System
.
getProperty
(
"bridgeManager.propsFile"
));
}
else
{
setActiveBridges
(
System
.
getProperty
(
bridgeFileDefault
));
}
for
(
ABridge
bridge
:
activeBridges
){
try
{
this
.
loadTypes
(
bridge
,
ts
);
}
catch
(
MetadataException
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
}
// Handle some kind of errors - waiting on errors concept from typesystem
}
public
ArrayList
<
ABridge
>
getActiveBridges
(){
return
this
.
activeBridges
;
}
private
void
setActiveBridges
(
String
bridgePropFileName
){
if
(
bridgePropFileName
==
null
|
bridgePropFileName
.
isEmpty
()){
bridgePropFileName
=
BridgeManager
.
bridgeFileDefault
;
}
ArrayList
<
ABridge
>
aBList
=
new
ArrayList
<
ABridge
>();
Properties
props
=
new
Properties
();
InputStream
configStm
=
this
.
getClass
().
getResourceAsStream
(
bridgePropFileName
);
try
{
ABridge
.
LOG
.
info
(
"Loading : Active Bridge List"
);
props
.
load
(
configStm
);
String
[]
activeBridgeList
=
((
String
)
props
.
get
(
"BridgeManager.activeBridges"
)).
split
(
","
);
ABridge
.
LOG
.
info
(
"Loaded : Active Bridge List"
);
ABridge
.
LOG
.
info
(
"First Loaded :"
+
activeBridgeList
[
0
]);
for
(
String
s
:
activeBridgeList
){
Class
<?>
bridgeCls
=
(
Class
<?>)
Class
.
forName
(
s
);
if
(
bridgeCls
.
isAssignableFrom
(
ABridge
.
class
)){
aBList
.
add
((
ABridge
)
bridgeCls
.
newInstance
());
}
}
}
catch
(
IOException
e
)
{
ABridge
.
LOG
.
error
(
e
.
getMessage
(),
e
);
e
.
printStackTrace
();
}
catch
(
InstantiationException
e
)
{
ABridge
.
LOG
.
error
(
e
.
getMessage
(),
e
);
e
.
printStackTrace
();
}
catch
(
IllegalAccessException
e
)
{
ABridge
.
LOG
.
error
(
e
.
getMessage
(),
e
);
e
.
printStackTrace
();
}
catch
(
ClassNotFoundException
e
)
{
ABridge
.
LOG
.
error
(
e
.
getMessage
(),
e
);
e
.
printStackTrace
();
}
this
.
activeBridges
=
aBList
;
}
private
final
boolean
loadTypes
(
ABridge
bridge
,
TypeSystem
ts
)
throws
MetadataException
{
for
(
Class
<
AEnitityBean
>
clazz
:
bridge
.
getTypeBeanClasses
()){
ts
.
defineClassType
(
BridgeManager
.
convertEntityBeanToClassTypeDefinition
(
clazz
));
}
return
false
;
BridgeManager
(
TypeSystem
ts
){
this
.
ts
=
ts
;
}
}
public
final
static
HierarchicalTypeDefinition
<
ClassType
>
convertEntityBeanToClassTypeDefinition
(
Class
<?
extends
AEnitityBean
>
class1
){
ArrayList
<
AttributeDefinition
>
attDefAL
=
new
ArrayList
<
AttributeDefinition
>();
for
(
Field
f:
class1
.
getFields
()){
try
{
attDefAL
.
add
(
BridgeManager
.
convertFieldtoAttributeDefiniton
(
f
));
}
catch
(
MetadataException
e
)
{
ABridge
.
LOG
.
error
(
"Class "
+
class1
.
getName
()
+
" cannot be converted to TypeDefinition"
);
e
.
printStackTrace
();
}
}
HierarchicalTypeDefinition
<
ClassType
>
typeDef
=
new
HierarchicalTypeDefinition
<>(
ClassType
.
class
,
class1
.
getSimpleName
(),
null
,
(
AttributeDefinition
[])
attDefAL
.
toArray
());
return
typeDef
;
}
public
final
static
AttributeDefinition
convertFieldtoAttributeDefiniton
(
Field
f
)
throws
MetadataException
{
return
new
AttributeDefinition
(
f
.
getName
(),
f
.
getType
().
getSimpleName
(),
Multiplicity
.
REQUIRED
,
false
,
null
);
}
}
}
metadata-bridge-parent/metadata-bridge-core/src/main/java/org/apache/hadoop/metadata/bridge/Bridge.java
→
metadata-bridge-parent/metadata-bridge-core/src/main/java/org/apache/hadoop/metadata/bridge/
I
Bridge.java
View file @
04997e4c
package
org
.
apache
.
hadoop
.
metadata
.
bridge
;
package
org
.
apache
.
hadoop
.
metadata
.
bridge
;
import
org.apache.hadoop.metadata.types.AttributeDefinition
;
import
org.apache.hadoop.metadata.types.ClassType
;
import
org.apache.hadoop.metadata.types.HierarchicalTypeDefinition
;
import
org.apache.hadoop.metadata.types.TypeSystem
;
import
org.apache.hadoop.metadata.types.TypeSystem
;
import
com.google.common.collect.ImmutableList
;
public
interface
IBridge
{
public
interface
Bridge
{
boolean
defineBridgeTypes
(
TypeSystem
ts
);
boolean
defineBridgeTypes
(
TypeSystem
ts
);
}
}
metadata-bridge-parent/metadata-bridge-core/src/main/java/org/apache/hadoop/metadata/bridge/hivelineage/HiveLineageBridge.java
View file @
04997e4c
package
org
.
apache
.
hadoop
.
metadata
.
bridge
.
hivelineage
;
package
org
.
apache
.
hadoop
.
metadata
.
bridge
.
hivelineage
;
import
org.apache.hadoop.metadata.MetadataException
;
import
org.apache.hadoop.metadata.MetadataException
;
import
org.apache.hadoop.metadata.bridge.Bridge
;
import
org.apache.hadoop.metadata.bridge.
A
Bridge
;
import
org.apache.hadoop.metadata.types.AttributeDefinition
;
import
org.apache.hadoop.metadata.types.AttributeDefinition
;
import
org.apache.hadoop.metadata.types.ClassType
;
import
org.apache.hadoop.metadata.types.ClassType
;
import
org.apache.hadoop.metadata.types.HierarchicalTypeDefinition
;
import
org.apache.hadoop.metadata.types.HierarchicalTypeDefinition
;
import
org.apache.hadoop.metadata.types.Multiplicity
;
import
org.apache.hadoop.metadata.types.Multiplicity
;
import
org.apache.hadoop.metadata.types.TypeSystem
;
import
org.apache.hadoop.metadata.types.TypeSystem
;
public
class
HiveLineageBridge
implements
Bridge
{
public
class
HiveLineageBridge
extends
A
Bridge
{
static
final
String
LINEAGE_CLASS_TYPE
=
"HiveLineage"
;
static
final
String
LINEAGE_CLASS_TYPE
=
"HiveLineage"
;
...
...
metadata-bridge-parent/metadata-bridge-core/src/main/java/org/apache/hadoop/metadata/bridge/hivestructure/HiveMetaImporter.java
View file @
04997e4c
...
@@ -31,6 +31,7 @@ public class HiveMetaImporter {
...
@@ -31,6 +31,7 @@ public class HiveMetaImporter {
try
{
try
{
this
.
repo
=
repo
;
this
.
repo
=
repo
;
msc
=
new
HiveMetaStoreClient
(
new
HiveConf
());
msc
=
new
HiveMetaStoreClient
(
new
HiveConf
());
// TODO Get hive-site.conf from class path first
}
catch
(
MetaException
e
)
{
}
catch
(
MetaException
e
)
{
// TODO Auto-generated catch block
// TODO Auto-generated catch block
e
.
printStackTrace
();
e
.
printStackTrace
();
...
...
metadata-bridge-parent/metadata-bridge-core/src/main/java/org/apache/hadoop/metadata/bridge/hivestructure/HiveStructureBridge.java
View file @
04997e4c
...
@@ -3,8 +3,7 @@ package org.apache.hadoop.metadata.bridge.hivestructure;
...
@@ -3,8 +3,7 @@ package org.apache.hadoop.metadata.bridge.hivestructure;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
org.apache.hadoop.metadata.MetadataException
;
import
org.apache.hadoop.metadata.MetadataException
;
import
org.apache.hadoop.metadata.bridge.Bridge
;
import
org.apache.hadoop.metadata.bridge.ABridge
;
import
org.apache.hadoop.metadata.bridge.BridgeAssistant
;
import
org.apache.hadoop.metadata.types.AttributeDefinition
;
import
org.apache.hadoop.metadata.types.AttributeDefinition
;
import
org.apache.hadoop.metadata.types.ClassType
;
import
org.apache.hadoop.metadata.types.ClassType
;
import
org.apache.hadoop.metadata.types.HierarchicalTypeDefinition
;
import
org.apache.hadoop.metadata.types.HierarchicalTypeDefinition
;
...
@@ -12,7 +11,7 @@ import org.apache.hadoop.metadata.types.Multiplicity;
...
@@ -12,7 +11,7 @@ import org.apache.hadoop.metadata.types.Multiplicity;
import
org.apache.hadoop.metadata.types.TypeSystem
;
import
org.apache.hadoop.metadata.types.TypeSystem
;
public
class
HiveStructureBridge
extends
BridgeAssistant
implements
Bridge
{
public
class
HiveStructureBridge
extends
A
Bridge
{
static
final
String
DB_CLASS_TYPE
=
"HiveDatabase"
;
static
final
String
DB_CLASS_TYPE
=
"HiveDatabase"
;
static
final
String
TB_CLASS_TYPE
=
"HiveTable"
;
static
final
String
TB_CLASS_TYPE
=
"HiveTable"
;
...
@@ -20,6 +19,9 @@ public class HiveStructureBridge extends BridgeAssistant implements Bridge{
...
@@ -20,6 +19,9 @@ public class HiveStructureBridge extends BridgeAssistant implements Bridge{
@Override
@Override
public
boolean
defineBridgeTypes
(
TypeSystem
ts
)
{
public
boolean
defineBridgeTypes
(
TypeSystem
ts
)
{
ArrayList
<
HierarchicalTypeDefinition
<?>>
al
=
new
ArrayList
<
HierarchicalTypeDefinition
<?>>();
ArrayList
<
HierarchicalTypeDefinition
<?>>
al
=
new
ArrayList
<
HierarchicalTypeDefinition
<?>>();
// TODO
//convert to helper methods
// Add to arrayList
try
{
try
{
HierarchicalTypeDefinition
<
ClassType
>
databaseClassTypeDef
=
new
HierarchicalTypeDefinition
<
ClassType
>(
"ClassType"
,
DB_CLASS_TYPE
,
null
,
HierarchicalTypeDefinition
<
ClassType
>
databaseClassTypeDef
=
new
HierarchicalTypeDefinition
<
ClassType
>(
"ClassType"
,
DB_CLASS_TYPE
,
null
,
...
...
metadata-bridge-parent/metadata-bridge-core/src/main/resources/bridge-manager.properties
0 → 100644
View file @
04997e4c
#BridgeManager.activebridges denotes which bridge defintions to load from the classpath (Comma seperated list of fully qualified class paths)
#
BridgeManager.activebridges
=
org.apache.hadoop.metadata.bridge.hivelineage
\ No newline at end of file
metadata-bridge-parent/metadata-bridge-core/src/test/java/org/apache/hadoop/metadata/bridge/test/BridgeManagerTest.java
0 → 100644
View file @
04997e4c
package
org
.
apache
.
hadoop
.
metadata
.
bridge
.
test
;
import
org.testng.annotations.Test
;
public
class
BridgeManagerTest
{
@Test
public
void
testLoadPropertiesFile
()
throws
Exception
{
}
}
metadata-bridge-parent/metadata-bridge-core/src/test/resources/test-bridge-manager.properties
0 → 100644
View file @
04997e4c
#BridgeManager.activebridges denotes which bridge defintions to load from the classpath (Comma seperated list of fully qualified class paths)
#
BridgeManager.activebridges
=
org.apache.hadoop.metadata.bridge.hivelineage
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment