plantuml : strange behavior when including multiple times startsub parts - plantuml

Taking this small example to illustrate my problem.
common.puml
#startuml common
!startsub COMMON
abstract Common {
id : uuid
}
!endsub
#enduml
myclass1.puml
#startuml myclass1
!includesub common.puml!COMMON
class MyClass1 extends Common {
text: string
}
#enduml
myclass2.puml
#startuml myclass1
!includesub common.puml!COMMON
class MyClass2 extends Common {
value: int
}
#enduml
all.puml
#startuml all
!include ./sub/common.puml
!include ./sub/myclass1.puml
!include ./sub/myclass2.puml
#enduml
When redering the all.puml diagram, I have a strange result in the Common part.
Attributes are rendered 3 times !
Any idea ?

It's either a feature or a bug. Include files just put the code from the file inside another. Since common.puml ends up being included three times (once in all, once in myclass1, and once in myclass2), you wind up more or less with:
abstract Common {
id : uuid
}
abstract Common {
id : uuid
}
abstract Common {
id : uuid
}
which will produce
Maybe you can prevent this from happening by defining a variable, e.g., !$common = 1 inside the part of common.puml that you don't want to repeat, and check before doing the !includesub, e.g.
...
!if (%not($common == 1))
!includesub common.puml!COMMON
!endif
...
(Note - I didn't test this!)

Related

Sorting a 2 dimensional array of objects in Kotlin

I have a static 2 dimensional array of objects in a Kotlin project:
class Tables {
companion object{
lateinit var finalTable: Array<Array<Any?>?>
}
}
It is a little clearer in Java:
public class Tables {
public static Object[][] finalTable;
}
The third element in one row of objects in the table, is a string boxed as an object. In other words: finalTable[*][2] is a string describing the item. When I add an item to the array in Kotlin, I want to sort the entire array in alphabetical order of the description.
In Java this is easy:
Arrays.sort(Tables.finalTable, Comparator.comparing(o -> (String) o[2]));
When I try to use Android Studio to translate the Java code into Kotlin, it produces the following:
Arrays.sort( Tables.finalTable, Comparator.comparing( Function { o: Array<Any?>? -> o[2] as String }) )
This does not work, you have change the String cast as follows:
Arrays.sort( Tables.finalTable, Comparator.comparing( Function { o: Array<Any?>? -> o[2].toString() }) )
This version will compile and run, but it totally messes up the sorting of the table, so it does not work. I have tried variations on this theme, without any success. To get my project to work, I had to create a Java class in the Kotlin project with the functional Java code listed above:
public class ArraySort {
public void sortArray(){
Arrays.sort(Tables.finalTable, Comparator.comparing(o -> (String) o[2]));
}
}
This sorts the table like a charm, but I would prefer to keep my project "pure Kotlin". Can anyone suggest a pure Kotlin method to sort such an array? Thanks!
Unless I'm missing something, you can just do this:
Tables.finalTable.sortBy { it[2] as String }
which sorts your array in place. sortedBy will produce a new copy of the original if that's what you want instead, and might be why the comment suggestions weren't working for you.
But this whole unstructured array situation isn't ideal, the solution is brittle because it would be easy to put the wrong type in that position for a row, or have a row without enough elements, etc. Creating a data structure (e.g. a data class) would allow you to have named parameters you can refer to (making the whole thing safer and more readable) and give you type checking too

How to include classes from another Plantuml file into a class diagram?

I have two class diagrams in PlantUML and would like to define a class in one file and reuse it in the other. See the example below.
diagram1.puml:
#startuml diagram1
class "Foo" as foo {
...attributes
}
#enduml
and diagram2:
#startuml diagram2
!include diagram1!foo
class "Bar" as bar {
...attributes
}
#enduml
Now my expectation is that diagram2 will show me both classes Foo and Bar in the diagram. However, the included class is not shown in the render.
How can this be solved?
The plantuml include statement includes code as if it was typed in that included place (like include files for e.g C / C++ etc. do too). So the code should be like:
For Diagram2:
#startuml diagram2
!include diagram1!foo
class "Bar" as bar {
...attributes
}
#enduml
and for diagram1
class "Foo" as foo {
...attributes
}
When you want also show diagram1 as a separate file you have to add an extra file with:
#startuml diagram1_show
!include diagram1!foo
#enduml

How do I (continue to, post-Kotlin Android Extensions) access widgets as array elements (which are doubly-included)?

I am "modernizing" some 15-month-old code to take advantage of
Kotlin Extension View Binding (migrating away from the deprecated
Kotlin Android Extensions compiler plugin).
The issue I'm having is related to the practice of using vars of
type Array<ConstraintLayout> throughout my code. This is
exemplified by charKeys throughout this posting.
I'm using nested includes within the XML.
I am struggling to figure the correct new syntax or approach. I
cannot get this code to compile yet.
NOTE: All Kotlin & XML has been reduced to relevant sections only.
First, the "old" way - which is working perfectly.
PuzzleFragment.kt
import kotlinx.android.synthetic.main.fragment_puzzle.*
import kotlinx.android.synthetic.main.item_keyboard.*
import kotlinx.android.synthetic.main.item_keyboard.view.*
import kotlinx.android.synthetic.main.item_kkey.view.*
:
class PuzzleFragment : Fragment() {
lateinit var charKeys: Array<ConstraintLayout>
charKeys = arrayOf(
kbd_char_0,
kbd_char_1
:
)
fragment_puzzle.xml
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/puzzle_fragment"
>
<include layout="#layout/item_keyboard" />
</androidx.constraintlayout.widget.ConstraintLayout>
item_keyboard.xml
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/keyboard"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/kbd_char_0"
>
<include layout="#layout/item_kkey" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/kbd_char_1"
>
<include layout="#layout/item_kkey" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
item_kkey.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android"
>
<TextView
android:id="#+id/kkey"
/>
</merge>
Again, all of that is (was) working (using Kotlin Android
Extensions). And this code allows (allowed) me to do things
like:
PuzzleFragment.kt
for (x in 0 until someNumber) {
val shape = charKeys[x].background as GradientDrawable
shape.setStroke(...)
charKeys[x].kkey.setTextColor(...)
for (key in charKeys)
key.isEnabled = false
for ((kx, key) in charKeys.withIndex())
key.elevation = ... //using kx
for (cx in 0 until maxGuessLength)
makeKeyRed(charKeys[cx], true)
private fun makeKeyRed(key: ConstraintLayout, doRed: Boolean) {
when {
doRed -> key.kkey.setTextColor(...)
key.kkey.text != "#" -> key.kkey.setTextColor(...)
else -> key.kkey.setTextColor(...)
}
}
So - that's the old way. Everything's cool. Now I'm converting this code. I have:
PuzzleFragment.kt
import com.zazzem.thats.databinding.FragmentPuzzleBinding
class PuzzleFragment : Fragment(R.layout.fragment_puzzle) {
private var _binding: FragmentPuzzleBinding? = null
private val binding get() = _binding!!
The following code seems ok (no "highlighted" errors in the IDE):
lateinit var charKeys: Array<ConstraintLayout>
charKeys = arrayOf(
binding.item_keyboard.kbd_char_0,
binding.item_keyboard.kbd_char_1,
:
)
for (x in 0 until someNumber) {
val shape = charKeys[x].background as GradientDrawable
shape.setStroke(...)
But it "falls apart" with the next line of code:
charKeys[x].kkey.setTextColor(...)
It doesn't like "kkey" here ("Unresolved reference"). And, in fact,
Basic code completion (Ctrl + Space) shows none of the widgets which
are part of item_kkey.
I don't know if I'm simply missing something obvious? Or if this
whole "array of 'vaguely-typed' ConstraintLayouts" approach isn't
valid (any longer)? Or if it's something in between?
Your .kkey is another use of a synthetic property, so you can't do that without Kotlin Android Extensions. The synthetic property is under the hood using findViewById on whatever ConstraintLayout you call it on to find the child view.
With view binding, no such properties of Views exist. But the generated class does have properties for include blocks. These properties return the generated binding classes of the layout files that you're including. However, you have not used android:id elements on your include elements, so they won't be accessible via your binding class.
Even if you did, that wouldn't be compatible with your ConstraintLayout Array strategy here.
I suggest for ease of converting your code, you create a direct replacement for the synthetic property, like this:
val ConstraintLayout.kkey: TextView get() = findViewById(R.id.kkey)
One downside to this compared to the synthetic property is that it has to find the view every time you use it, which is slightly slower than synthetic properties when they are repeatedly used. But I don't think it will be very significant here, since this particular view is always the sole child of the layout you are searching in.
Note, this strategy has the same weakness that they deprecated Android Extensions for. It's not safe to call this on any arbitrary ConstraintLayout.

How to mix different plantuml diagram type elements?

I want to have deployment and sequence stuff in one and the same rendered plantuml picture. So I tried the following but it does not work, the rendering shows the sequence stuff for A, B and C as deployment.
How can I force rendering for "A->B" and "B->C" as sequence diagram stuff?
#startuml
file main.c
note right: I want to have description text here
A -> B : main()
note left : program\nentry function
B -> C : load()
note left : another important function
#enduml
I think you need to add your note later:
#startuml
title file main.c
A -> B : main()
note left : program\nentry function
B -> C : load()
note left : another important function
note right: I want to have description text here
#enduml
Result:

OWLAPI slow calculating disjoint axioms

My goal: find the disjoint axioms (asserted and inferred) in an ontology which contains around 5000 axioms.
My code:
for (OWLClass clazz1 : ontology.getClassesInSignature()) {
for (OWLClass clazz2 : ontology.getClassesInSignature()) {
OWLAxiom axiom = MyModel.factory.getOWLDisjointClassesAxiom(clazz2, clazz1);
if( !(ontology.containsAxiom(axiom)) && reasoner.isEntailed(axiom))
{
System.out.println(clazz2.toString() + " disjoint with " + clazz1.toString());
}
The problem: the execution time is extremely slow, I'd say eternal. Even if I reduce the number of comparison with some if statement, the situation is still the same.
Protege seems to be very quick to compute those inferred axioms and it's based on the same API I am using (OWLAPI). So, am I in the wrong approach?
Profiling the code will very likely reveal that the slow part is
reasoner.isEntailed(axiom)
This form requires the reasoner to recompute entailments for each class pair, including the pairs where clazz1 and clazz2 are equal (you might want to skip that).
Alternatively, you can iterate through the classes in signature once and use the reasoner to get all disjoint classes:
Set<OWLClass> visited=new HashSet<>();
for (OWLClass c: ontology.getClassesInSignature()) {
if (visited.add(c)) {
NodeSet set = reasoner.getDisjointClasses(c);
for (Node node: set.getNodes()) {
System.out.println("Disjoint with "+c+": "+node);
visited.addAll(node.getEntities());
}
}
}
Worst case scenario, this will make one reasoner call per class (because no class is disjoint). Best case scenario, all classes are disjoint or equivalent to another class, so only one reasoner call is required.

Resources