Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Eclipse Projects
Eclipse eTrice™
Eclipse eTrice
Commits
77bbfd5a
Commit
77bbfd5a
authored
May 25, 2022
by
Eyrak Paen-Rochlitz
Browse files
[generator.doc] Only include diagrams if model files can be resolved
parent
f40db328
Changes
2
Hide whitespace changes
Inline
Side-by-side
plugins/org.eclipse.etrice.generator.doc/src/org/eclipse/etrice/generator/doc/gen/AsciiDocGen.xtend
View file @
77bbfd5a
...
...
@@ -19,8 +19,6 @@ import com.google.inject.Singleton
import
java
.
util
.
List
import
org
.
eclipse
.
emf
.
ecore
.
EObject
import
org
.
eclipse
.
etrice
.
core
.
common
.
base
.
Documentation
import
org
.
eclipse
.
etrice
.
core
.
fsm
.
fSM
.
ModelComponent
import
org
.
eclipse
.
etrice
.
core
.
fsm
.
fSM
.
State
import
org
.
eclipse
.
etrice
.
core
.
fsm
.
fSM
.
StateGraph
import
org
.
eclipse
.
etrice
.
core
.
genmodel
.
etricegen
.
Root
import
org
.
eclipse
.
etrice
.
core
.
room
.
ActorClass
...
...
@@ -36,13 +34,13 @@ import org.eclipse.etrice.core.room.RoomModel
import
org
.
eclipse
.
etrice
.
core
.
room
.
SubSystemClass
import
org
.
eclipse
.
etrice
.
core
.
room
.
util
.
RoomHelpers
import
org
.
eclipse
.
etrice
.
generator
.
base
.
io
.
IGeneratorFileIO
import
org
.
eclipse
.
etrice
.
generator
.
fsm
.
base
.
CodegenHelpers
import
org
.
eclipse
.
etrice
.
generator
.
doc
.
gen
.
URIBasedDiagramResolver
.
DiagramType
import
org
.
eclipse
.
etrice
.
generator
.
doc
.
gen
.
URIBasedDiagramResolver
.
DiagramFormat
import
org
.
eclipse
.
xtext
.
documentation
.
IEObjectDocumentationProvider
import
static
org
.
eclipse
.
etrice
.
core
.
common
.
documentation
.
DocumentationMarkup
.*
import
org
.
eclipse
.
etrice
.
generator
.
doc
.
Main
import
org
.
eclipse
.
etrice
.
generator
.
base
.
AbstractGeneratorOptionsHelper
import
org
.
eclipse
.
etrice
.
core
.
room
.
StructureClass
import
static
extension
org
.
eclipse
.
xtext
.
EcoreUtil2
.
getContainerOfType
...
...
@@ -50,9 +48,9 @@ import static extension org.eclipse.xtext.EcoreUtil2.getContainerOfType
class
AsciiDocGen
{
@
Inject
extension
RoomHelpers
@
Inject
extension
CodegenHelpers
@
Inject
protected
extension
AbstractGeneratorOptionsHelper
@
Inject
IEObjectDocumentationProvider
eObjDocuProvider
@
Inject
extension
URIBasedDiagramResolver
def
doGenerate
(
Root
root
,
IGeneratorFileIO
fileIO
,
boolean
includeImages
)
{
val
packages
=
root
.
models
.
groupBy
[
name
].
entrySet
.
map
[
new
RoomPackage
(
key
,
value
)].
sortBy
[
name
]
...
...
@@ -206,9 +204,9 @@ class AsciiDocGen {
tagStart(ssc)
ssc.docText
IF includeImages
IF includeImages
&& ssc.hasDiagram(DiagramType.STRUCTURE)
includeImage(ssc.
diagramName + ".jpg
")
includeImage(ssc.
getExportedDiagramFilename(DiagramType.STRUCTURE, DiagramFormat.JPG).orElse("!!unresolved_diagram_file!!
")
)
ENDIF
tagEnd(ssc)
'''
...
...
@@ -320,9 +318,8 @@ class AsciiDocGen {
ENDIF
ELSE
==== Structure
IF includeImages
includeImage(ac.diagramName + ".jpg")
IF includeImages && ac.hasDiagram(DiagramType.STRUCTURE)
includeImage(ac.getExportedDiagramFilename(DiagramType.STRUCTURE, DiagramFormat.JPG).orElse("!!unresolved_diagram_file!!"))
ENDIF
IF !ac.allPorts.empty
...
...
@@ -360,8 +357,8 @@ class AsciiDocGen {
def
private
CharSequence
generateStateGraphDoc
(
ActorClass
ac
,
StateGraph
stateGraph
,
boolean
includeImages
,
int
depth
)
{
'''
IF includeImages
includeImage(stateGraph.
diagramName + ".jpg
")
IF includeImages
&& stateGraph.hasDiagram(DiagramType.BEHAVIOR)
includeImage(stateGraph.
getExportedDiagramFilename(DiagramType.BEHAVIOR, DiagramFormat.JPG).orElse("!!unresolved_diagram_file!!
")
)
ENDIF
FOR state: stateGraph.states
state.name::fill('
:
', depth)
...
...
@@ -467,18 +464,6 @@ class AsciiDocGen {
if
(
index
!= -1) docText.subSequence(0, index) else docText
}
def
private
dispatch
getDiagramName
(
StructureClass
sc
)
{
val
namespace
=
sc
.
getContainerOfType
(
RoomModel
)?.
name
?.
concat
(
"."
)
?:
""
namespace
+
sc
.
name
+
"_structure"
}
def
private
dispatch
getDiagramName
(
StateGraph
sg
)
{
val
namespace
=
sg
.
getContainerOfType
(
RoomModel
)?.
name
?.
concat
(
"."
)
?:
""
val
modelComponentName
=
sg
.
getContainerOfType
(
ModelComponent
)?.
componentName
?:
""
val
subStatePath
=
if
(
sg
.
eContainer
instanceof
State
)
"."
+
(
sg
.
eContainer
as
State
)?.
genStatePathName
else
""
namespace
+
modelComponentName
+
subStatePath
+
"_behavior"
}
def
private
getInstanceDiagramName
(
LogicalSystem
system
)
{
val
namespace
=
system
.
getContainerOfType
(
RoomModel
)?.
name
?.
concat
(
"."
)
?:
""
namespace
+
system
.
name
+
"_instanceTree"
...
...
plugins/org.eclipse.etrice.generator.doc/src/org/eclipse/etrice/generator/doc/gen/URIBasedDiagramResolver.java
0 → 100644
View file @
77bbfd5a
/*******************************************************************************
* Copyright (c) 2022 protos software gmbh (http://www.protos.de).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* CONTRIBUTORS:
* epaen (initial contribution)
*
*******************************************************************************/
package
org.eclipse.etrice.generator.doc.gen
;
import
java.io.File
;
import
org.eclipse.core.resources.IResource
;
import
org.eclipse.core.resources.ResourcesPlugin
;
import
org.eclipse.emf.common.util.URI
;
import
org.eclipse.emf.ecore.EAttribute
;
import
org.eclipse.emf.ecore.EObject
;
import
org.eclipse.etrice.core.fsm.fSM.ModelComponent
;
import
org.eclipse.etrice.core.fsm.fSM.State
;
import
org.eclipse.etrice.core.fsm.fSM.util.FSMSwitch
;
import
org.eclipse.etrice.core.fsm.naming.FSMNameProvider
;
import
org.eclipse.etrice.core.room.StructureClass
;
import
org.eclipse.etrice.core.room.util.RoomSwitch
;
import
org.eclipse.xtext.EcoreUtil2
;
import
java.util.Optional
;
import
com.google.inject.Inject
;
public
class
URIBasedDiagramResolver
{
@Inject
private
BehaviorBaseNameProvider
behaviorBaseProvider
;
@Inject
private
StructureBaseNameProvider
structureBaseProvider
;
public
static
final
String
DIAGRAM_SUBDIR
=
"diagrams"
;
public
static
enum
DiagramType
{
STRUCTURE
(
"_structure"
,
".structure"
),
BEHAVIOR
(
"_behavior"
,
".behavior"
);
private
final
String
exportSuffix
;
private
final
String
extension
;
DiagramType
(
String
exportSuffix
,
String
extension
)
{
this
.
exportSuffix
=
exportSuffix
;
this
.
extension
=
extension
;
}
public
String
getExportSuffix
()
{
return
exportSuffix
;
}
public
String
getExtension
()
{
return
extension
;
}
}
public
static
enum
DiagramFormat
{
JPG
(
"jpg"
),
PNG
(
"png"
),
SVG
(
"svg"
),
NO_EXT
(
""
);
private
final
String
extension
;
DiagramFormat
(
String
extension
)
{
this
.
extension
=
extension
;
}
public
String
getExtension
()
{
return
extension
;
}
}
/**
* Checks if the corresponding diagram file for a given EObject instance exists.
*
* @param obj The EObject associated with the diagram
* @param type The desired diagram type to check
* @return true if the diagram file exists, or false if none could be found
*/
public
boolean
hasDiagram
(
EObject
obj
,
DiagramType
type
)
{
Optional
<
URI
>
uri
=
getDiagramURI
(
obj
,
type
);
if
(!
uri
.
isPresent
())
{
return
false
;
}
boolean
result
=
false
;
if
(
uri
.
get
().
isPlatformResource
())
{
String
path
=
uri
.
get
().
toPlatformString
(
true
);
IResource
file
=
ResourcesPlugin
.
getWorkspace
().
getRoot
().
findMember
(
path
);
result
=
(
file
!=
null
)
&&
(
file
.
exists
());
}
else
if
(
uri
.
get
().
isFile
())
{
String
path
=
uri
.
get
().
toFileString
();
File
file
=
new
File
(
path
);
result
=
file
.
exists
();
}
return
result
;
}
/**
* Gets the corresponding exported diagram image filename for a given EObject.
*
* @param obj The EObject associated with the diagram
* @param type The diagram type of the exported diagram
* @param format The format of the exported diagram
* @return true if the diagram file exists, or false if not, or false if
* the EObject could not be mapped to a diagram file
*/
public
Optional
<
String
>
getExportedDiagramFilename
(
EObject
obj
,
DiagramType
type
,
DiagramFormat
format
)
{
Optional
<
String
>
base
=
Optional
.
empty
();
switch
(
type
)
{
case
BEHAVIOR:
base
=
behaviorBaseProvider
.
doSwitch
(
obj
);
break
;
case
STRUCTURE:
base
=
structureBaseProvider
.
doSwitch
(
obj
);
break
;
default
:
break
;
}
return
base
.
map
(
value
->
value
+
type
.
getExportSuffix
()
+
"."
+
format
.
getExtension
());
}
/**
* Gets the corresponding diagram filename for a given EObject.
*
* @param obj The EObject associated with the diagram
* @param type The desired diagram type
* @return The filename for the diagram of the EObject, or empty if none could be found
*/
public
Optional
<
String
>
getDiagramFilename
(
EObject
obj
,
DiagramType
type
)
{
Optional
<
String
>
base
=
Optional
.
empty
();
switch
(
type
)
{
case
BEHAVIOR:
// Restrict to ModelComponent, since State diagrams are nested in the same file
ModelComponent
mc
=
EcoreUtil2
.
getContainerOfType
(
obj
,
ModelComponent
.
class
);
base
=
behaviorBaseProvider
.
doSwitch
(
mc
);
break
;
case
STRUCTURE:
base
=
structureBaseProvider
.
doSwitch
(
obj
);
break
;
default
:
break
;
}
return
base
.
map
(
value
->
value
+
type
.
getExtension
());
}
/**
* Gets the corresponding URI of the diagram file for a given EObject.
*
* @param obj The EObject associated with the diagram
* @param type The diagram type of the exported diagram
* @return The URI for the diagram of the EObject, or empty if none could be found
*/
public
Optional
<
URI
>
getDiagramURI
(
EObject
obj
,
DiagramType
type
)
{
URI
diagramFolder
=
resolveDiagramFolder
(
obj
);
Optional
<
String
>
filename
=
getDiagramFilename
(
obj
,
type
);
return
filename
.
map
(
value
->
diagramFolder
.
appendSegment
(
value
));
}
private
URI
resolveDiagramFolder
(
EObject
obj
)
{
URI
uri
=
obj
.
eResource
().
getURI
();
URI
uriParent
=
uri
.
trimSegments
(
1
);
URI
uriDiagramContainer
=
uriParent
.
appendSegment
(
DIAGRAM_SUBDIR
);
return
uriDiagramContainer
;
}
/**
* Derives a base name for behavior diagrams based on a given EObject.
* The format of the base name is "[namespace.]structureClassName"
*
* <p>The provider will look for the closest containing StructureClass of
* the given EObject.</p>
*/
private
static
class
StructureBaseNameProvider
extends
RoomSwitch
<
Optional
<
String
>>
{
@Override
public
Optional
<
String
>
caseStructureClass
(
StructureClass
object
)
{
if
(
object
==
null
)
{
return
Optional
.
empty
();
}
String
namespace
=
URIBasedDiagramResolver
.
inferNamespaceName
(
object
);
if
(!
namespace
.
isEmpty
())
{
namespace
+=
"."
;
}
return
Optional
.
of
(
namespace
+
object
.
getName
());
}
@Override
public
Optional
<
String
>
defaultCase
(
EObject
object
)
{
StructureClass
sc
=
EcoreUtil2
.
getContainerOfType
(
object
,
StructureClass
.
class
);
return
caseStructureClass
(
sc
);
}
}
/**
* Derives a base name for behavior diagrams based on a given EObject.
*
* <ul>
* <li>for States this looks like "[namespace.]componentName.statePath"</li>
* <li>for ModelComponents this looks like "[namespace.]componentName"</li>
* </ul>
*
* <p>The provider will look for the closest containing State or ModelComponent
* of the given EObject, in that order.</p>
*/
private
static
class
BehaviorBaseNameProvider
extends
FSMSwitch
<
Optional
<
String
>>
{
@Inject
FSMNameProvider
nameProvider
;
@Override
public
Optional
<
String
>
caseModelComponent
(
ModelComponent
object
)
{
if
(
object
==
null
)
{
return
Optional
.
empty
();
}
String
namespace
=
URIBasedDiagramResolver
.
inferNamespaceName
(
object
);
if
(!
namespace
.
isEmpty
())
{
namespace
+=
"."
;
}
return
Optional
.
of
(
namespace
+
object
.
getComponentName
());
}
@Override
public
Optional
<
String
>
caseState
(
State
object
)
{
if
(
object
==
null
)
{
return
Optional
.
empty
();
}
ModelComponent
mc
=
EcoreUtil2
.
getContainerOfType
(
object
,
ModelComponent
.
class
);
return
caseModelComponent
(
mc
).
map
(
value
->
value
+
"."
+
nameProvider
.
getStatePathName
(
object
));
}
@Override
public
Optional
<
String
>
defaultCase
(
EObject
object
)
{
State
st
=
EcoreUtil2
.
getContainerOfType
(
object
,
State
.
class
);
if
(
st
!=
null
)
{
return
caseState
(
st
);
}
ModelComponent
mc
=
EcoreUtil2
.
getContainerOfType
(
object
,
ModelComponent
.
class
);
if
(
mc
!=
null
)
{
return
caseModelComponent
(
mc
);
}
// fallback if no match
return
Optional
.
empty
();
}
}
/**
* Looks for name attribute in a given EObject's container to use as a namespace name.
* This is done reflexively by searching for an EAttribute "name", because in the base
* FSM model there may not be a named root element to derive the namespace from.
*
* @param obj The EObject used to find the parent namespace name
* @return A namespace name as String, or empty String if none is found.
*/
private
static
String
inferNamespaceName
(
EObject
obj
)
{
EObject
container
=
obj
.
eContainer
();
if
(
container
==
null
)
{
return
""
;
}
EAttribute
namespaceAttr
=
container
.
eClass
().
getEAllAttributes
().
stream
()
.
filter
(
attr
->
attr
.
getName
().
equals
(
"name"
))
.
findFirst
()
.
orElse
(
null
);
if
(
namespaceAttr
==
null
)
{
return
""
;
}
String
name
=
container
.
eGet
(
namespaceAttr
).
toString
();
return
name
;
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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