ArchUnit: How to check for unwanted dependecies in the signature / API of a class? - archunit

I would like to implement an ArchUnit rule that checks for unwanted dependencies. That's easy to do but I'm only interested in violations that are part of the signature / API of the class.
E.g. if the class uses an unwanted dependency in a private field or as method parameter of a private method, that's fine since it's not visible from outside.
I'm struggling with the fluent API. My starting point is:
noClasses().that()
.resideInAnyPackage("..domain..", "..application..")
.should()
.dependOnClassesThat()
.resideInAnyPackage(
"badpackage1..",
"badpackage2..");
How can I refine the above rule to only trigger for non-private language elements of my classes?

You could extract an interface and apply the checks to the interface (classes().that().areInterfaces()). IDEs provide support for interface extraction.

Related

Usage of implementsInterface element on entities in guidewire

I would like to know why do we use implementsInterface element in entities. I know one example where they use it to make it as assignable entity. But I could not understand what other purpose and how/why it is being used in entities.
Example: Injuryincident entity has claimantsupplier and coveragesupplier interface
I like to see it from this prespective, simplified and assuming that you have some java background:
As you probably already know it, having an entity means in the end of the day, having a Java class... Well, by using the implementsInterface element in your entity, is similar to implement an interface in you java class.
Here you have a quick example...
Consider the following:
MyEntiti.eti
<?xml version="1.0"?>
<entity
xmlns="http://guidewire.com/datamodel"
entity="MyEntity"
table="myentity"
type="retireable"/>
AnInterface.gs
package mypkg
interface AnInterface {
function doSomething()
}
AnInterfaceImpl.gs
package mypkg
class AnInterfaceImpl implements AnInterface {
override function doSomething() {
print("Hello!")
}
}
Image that you need MyEntity to have the ability of "doSomething", you just need to add the implementsInterface:
<?xml version="1.0"?>
<entity
xmlns="http://guidewire.com/datamodel"
entity="MyEntity"
table="myentity"
type="retireable">
<implementsInterface
iface="mypkg.AnInterface"
impl="mypkg.AnInterfaceImpl"/>
</entity>
By doing that, the following code must work:
var myEntity = new MyEntity()
myEntity.doSomething() //this will call the method defined in the interface-implementation
And even better, you migth let you implementation to recognize the related object of MyEntity and use it as per your needs:
package mypkg
class AnInterfaceImpl implements AnInterface {
private final var _relatedEntity : MyEntity
construct(relatedTo : MyEntity) {
_relatedEntity = relatedTo
}
override function doSomething() {
var createUser = _relatedEntity.CreateUser // you can accees to whatever you need
print("Hello!, this is the related instace of MyEntity: ${_relatedEntity}")
}
}
Hope it helps, regards!
I won't be repeating the other answer describing how it works, but I would like to mention how implementing an interface on an entity is different (and serves different purposes) compared to using enhancements.
On basic level both approaches let you add extra functionality to your entity classes. In most cases what you really want to do is just create/expand an enhancement - they are easier to write, more convenient to modify and just as effective when all you want is to just add a new function or calculated property.
When you implement an interface, you're bringing in some more serious guns. While this approach takes more work and requires creation of several files (not to mention modifying the entity itself), it gives you two important advantages over the enhancement mechanism:
The same interface can be implemented by several entities (typically each having its own implementation class) as well as non-entity classes. Objects of all such classes can then be used interchangeably in contexts expecting the interface (you can create an array of entity instances of several entities and even gosu-only wrappers/temporary objects and present it comfortably in the UI).
You can leverage polymorphism. While enhancement functions can't be overridden, the interface implementations allow you full flexibility of polymorphic OOP. You can, for example, set up a default "do nothing" implementation on high level entity that you intend to use and then add more meaningful implementations for specific subtypes meant to really make use of the new functionality.
It does have some overhead and complicates things, however. As mentioned - Enhancements are typically simpler. In practice you should ask yourself whether the extra effort of creating and implementing the interface is worth it - in many cases even situations seemingly calling for polymorphism can be handled well enough by a simple switch typeof this in the enhancement to provide all the necessary type-based logic.
In personal experience I've used interfaces in quite a few situations, but Enhancements are my first choice in overwhelming majority of cases.
As a final note I'd like to mention a delegate entity. If what you want to add to some unrelated entities is not functionality but Properties with underlying database fields, creating a delegate entity and "implement" it with the desired standalone entities. A delegate entity does work a bit like an interface (you can use entity objects implementing the delegate interchangeably in situations where the delegate is expected) and you can set-up both interface implementation and enhancements on delegate level as well.

How to check if a field's implements an interface?

If I have an org.eclipse.jdt.internal.compiler.ast.FieldDeclaration, how would I check if the type of the field implements an interface, let's say Serializable? I don't see any documentation for org.eclipse.jdt.internal.
I found extract interface that a class implementing using AST parser, but that one talks about org.eclipse.jdt.core.dom.FieldDeclaration.
EDIT: At first I didn't look at the package and thought you were asking about org.eclipse.jdt.core.dom.FieldDeclaration. That's what the answer is good for.
If you need to work with internal classes, we expect that you know exactly what you are doing. There won't be any documentation for those (but conceptually the same approach as shown for the public API can similarly be used for the internal AST and bindings, too).
Type compatibility is best tested using the corresponding bindings, so your quest would consist of theses steps:
From the FieldDeclaration obtain the binding using resolveBinding()
From the field binding retrieve the type binding
Once get a binding representing the expected super type Serializable
Ask the actual field type isSubTypeCompatible(serializableType)
You'll find some more details - in particular on (3) - in a recent discussion in the JDT forum.

JAXB how to remove anything from JDefinedClass

i am using jaxb to generate code from an xsd.
The generated code contains a lot of annotations; for classes and fields.
I am trying to use com.sun.tools.internal.xjc.Plugin to modify the generated code.
In the plugin run() method we are given an Outline class from which we can get ClassOutline. ClassOutline has an JDefinedClass final member which has the info about actual class which will be generated.
If i want to add anything, there are apis in JDefinedClass which can be used. But if i want to remove something, there is no way.
e.g. i cannot clear annotations, because the JDefinedClass.annotations() method returns an UnmodifiableCollection. so i cannot clear it or remove anything from it.
i tried to create another JDefinedClass by invoking the _class method but the ClassOutline.implClass variable is final, so i cannot set it.
how to get a JDefinedClass which does not have any annotations?
is there another phase of code generation which i can trap into to really control the generation of JDefinedClass?
The code model is, indeed mostly "write only". But, speaking of annotations, you have probably missed the methods like com.sun.codemodel.JDefinedClass.removeAnnotation(JAnnotationUse) and com.sun.codemodel.JMethod.removeAnnotation(JAnnotationUse) (implemented from com.sun.codemodel.JAnnotatable.removeAnnotation(JAnnotationUse)).
So they're there. You can remove annotations with the normal CodeModel API.
As I can see, you can also remove fields and methods from classes. So what exactly are you missing?
JDefinedClass.annotations() It return an unmodifiable collection object and you cannot modify them.
So work around for this, you can restrict annotation addition/deletion at class and field level before building JCodeModel.
You need to create a custom Jackson2Annotator class which extends Jackson2Annotator and override their methods according to your requirement.
Following are few methods which are being used for specific type of annotation property:
propertyOrder(OTB JsonPropertyOrder)
propertyInclusion(OTB JsonInclude)
propertyField(can be used for custom defined annotation at field level)
More you can discover by looking Jackson2Annotator class what fit into your need.

Extending a JOOQ Table class

I have a 'document' table (very original) that I need to dynamically subset at runtime so that my API consumers can't see data that isn't legal to view given some temporal constraints between the application/database. JOOQ created me a nice auto-gen Document class that represents this table.
Ideally, I'd like to create an anonymous subclass of Document that actually translates to
SELECT document.* FROM document, other_table
WHERE document.id = other_table.doc_id AND other_table.foo = 'bar'
Note that bar is dynamic at runtime hence the desire to extend it anonymously. I can extend the Document class anonymously and everything looks great to my API consumers, but I can't figure out how to actually restrict the data. accept() is final and toSQL doesn't seem to have any effect.
If this isn't possible and I need to extend CustomTable, what method do I override to provide my custom SQL? The JOOQ docs say to override accept(), but that method is marked final in TableImpl, which CustomTable extends from. This is on JOOQ 3.5.3.
Thanks,
Kyle
UPDATE
I built 3.5.4 from source after removing the "final" modifier on TableImpl.accept() and was able to do exactly what I wanted. Given that the docs imply I should be able to override accept perhaps it's just a simple matter of an erroneous final declaration.
Maybe you can implement one of the interfaces
TableLike (and delegate all methods to a JOOQ implementation instance) such as TableImpl (dynamic field using a HashMap to store the Fields?)
Implement the Field interface (and make it dynamic)
Anyway you will need to remind that there are different phases while JOOQ builds the query, binds values, executes it etc. You should probably avoid changing the "foo" Field when starting to build a query.
It's been a while since I worked with JOOQ. My team ended up building a customized JOOQ. Another (dirty) trick to hook into the JOOQ library was to use the same packages, as the protected identifier makes everything visible within the same package as well as to sub classes...

Get attribute name from proxy type without using reflections

We use early-bound class for development. But occasionally we use attribute names.
There is a way to do it using reflections, but reflections are not allowed in sandbox plugins.
What are the approaches to getting an attribute from proxy types without relying on reflections?
Opportunity.OpportunityId.AttributeName
You have a couple options:
You can use a RetrieveEntityMetadata to the list of attributes that the entity contains. You won't be able to use any early binding here, but you can inspect the results at run time to see what are valid attributes for the entity.
You could also create a simple utility that uses reflection to auto-generate a class or enum that contains the list of attributes before you actually deploy. Just add the class to your plugin dll and you'd have the benefits of early binding of entity attributes when developing your plugin, without having to do reflection at runtime.

Resources