Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concepts rework #12

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/main/java/org/xmolecules/ide/intellij/All.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.xmolecules.ide.intellij;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class All {
public static final List<ConceptImplementation> ALL = concat(JMolecules.ALL , Spring.ALL, JPA.ALL);

private static <T> List<T> concat(List<T> ... list) {
var size = 0;
for( var l : list) {
size += l.size();
}
var buffer = new ArrayList<T>(size);
for( var l : list) {
buffer.addAll(l);
}
return Collections.unmodifiableList(buffer);
}
}
22 changes: 14 additions & 8 deletions src/main/java/org/xmolecules/ide/intellij/Concept.java
Original file line number Diff line number Diff line change
@@ -1,38 +1,44 @@
package org.xmolecules.ide.intellij;

import java.util.function.Predicate;

import com.intellij.psi.PsiJavaFile;
import org.jetbrains.annotations.NotNull;

class Concept implements Predicate<PsiJavaFile>, Comparable<Concept> {
private final String name, plural;
import java.util.function.Predicate;

public class Concept implements Predicate<PsiJavaFile>, Comparable<Concept> {
private final String name, plural, defaultColorName;
private final Predicate<PsiJavaFile> condition;

Concept(
@NotNull final String name,
@NotNull final String plural,
@NotNull final String defaultColorName,
@NotNull final Predicate<PsiJavaFile> condition) {
this.name = name;
this.plural = plural;
this.defaultColorName = defaultColorName;
this.condition = condition;
}

@NotNull String getName() {
public @NotNull String getName() {
return name;
}

@NotNull String getPlural() {
public @NotNull String getPlural() {
return plural;
}

public @NotNull String getDefaultColorName() {
return defaultColorName;
}

@Override
public boolean test(@NotNull final PsiJavaFile psiJavaFile) {
return condition.test(psiJavaFile);
}

@Override
public int compareTo(Concept o) {
public int compareTo(final Concept o) {
return getName().compareTo(o.getName());
}
} //TODO Compare by instance
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.xmolecules.ide.intellij;

import com.intellij.psi.PsiJavaFile;

import java.util.function.Predicate;

public abstract class ConceptImplementation implements Predicate<PsiJavaFile> {
private final Concept concept;
private final Library library;
private final Predicate<PsiJavaFile> condition;
private final String fqName;

public ConceptImplementation(final Concept concept, final Library library, final String fqName, final Predicate<PsiJavaFile> condition) {
this.concept = concept;
this.library = library;
this.condition = condition;
this.fqName = fqName;
}

public Concept getConcept() {
return concept;
}

public Library getLibrary() {
return library;
}

/**
* @see com.intellij.codeInsight.daemon.quickFix.ExternalLibraryResolver
* @see nexos.intellij.ddd.DDDLibraryResolver
*/
public String getFqName() {
return fqName;
}

/*
* (non-Javadoc)
* @see java.util.function.Predicate#test(java.lang.Object)
*/
@Override
public boolean test(final PsiJavaFile psiJavaFile) {
return condition.test(psiJavaFile);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.xmolecules.ide.intellij;

import static org.xmolecules.ide.intellij.Types.implementsType;

public class ConceptViaImplements extends ConceptImplementation {
public ConceptViaImplements(final Concept concept, final Library library, final String fqName) {
super(concept, library, fqName, it -> implementsType(fqName, it));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.xmolecules.ide.intellij;

import java.util.List;

import static org.xmolecules.ide.intellij.Types.hasMethodAnnotatedWith;

public class ConceptViaMethodAnnotation extends ConceptImplementation {
public ConceptViaMethodAnnotation(final Concept concept, final Library library, final String fqName) {
super(concept, library, fqName, it -> hasMethodAnnotatedWith(it, fqName));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.xmolecules.ide.intellij;

import static org.xmolecules.ide.intellij.Types.isTypeAnnotatedWith;

public class ConceptViaTypeAnnotation extends ConceptImplementation {
public ConceptViaTypeAnnotation(final Concept concept, final Library library, final String fqName) {
super(concept, library, fqName, it -> isTypeAnnotatedWith(fqName, it));
}
}
43 changes: 28 additions & 15 deletions src/main/java/org/xmolecules/ide/intellij/Concepts.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
*/
package org.xmolecules.ide.intellij;

import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.lang.jvm.JvmModifier;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
Expand Down Expand Up @@ -46,21 +50,29 @@
/**
* @author Oliver Drotbohm
*/
class Concepts {
private static final Set<Concept> CONCEPTS;
public class Concepts {
public static final Concept FACTORY = new Concept("Factory", "Factories", "black", JMolecules::isFactory);
public static final Concept SERVICE = new Concept("Service", "Services", "black", JMolecules::isService);
public static final Concept REPOSITORY = new Concept("Repository", "Repositories", "black", any(JMolecules::isRepository, Spring::isRepository));
public static final Concept IDENTIFIER = new Concept("Identifier", "Identifiers", "black", JMolecules::isIdentifier);
public static final Concept VALUE_OBJECT = new Concept("Value Object", "Value objects", "black", it -> JMolecules.isValueObject(it) && !JMolecules.isIdentifier(it));
public static final Concept ENTITY = new Concept("Entity", "Entities", "black", it -> JMolecules.isEntity(it) && !JMolecules.isAggregateRoot(it));
public static final Concept AGGREGATE_ROOT = new Concept("Aggregate Root", "Aggregate roots", "black", JMolecules::isAggregateRoot);
public static final Concept EVENT = new Concept("Event", "Events", "black", JMolecules::isEvent);
public static final Concept EVENT_LISTENER = new Concept("Event listener", "Event listeners", "black",
any(JMolecules::isEventListener, Spring::isEventListener));

static {
CONCEPTS = Set.of(
new Concept("Factory", "Factories", JMolecules::isFactory),
new Concept("Service", "Services", JMolecules::isService),
new Concept("Repository", "Repositories", any(JMolecules::isRepository, Spring::isRepository)),
new Concept("Identifier", "Identifiers", JMolecules::isIdentifier),
new Concept("Value Object", "Value objects", it -> JMolecules.isValueObject(it) && !JMolecules.isIdentifier(it)),
new Concept("Entity", "Entities", it -> JMolecules.isEntity(it) && !JMolecules.isAggregateRoot(it)),
new Concept("Aggregate Root", "Aggregate roots", JMolecules::isAggregateRoot),
new Concept("Event", "Events", JMolecules::isEvent),
new Concept("Event listener", "Event listeners",
any(JMolecules::isEventListener, Spring::isEventListener))
var CONCEPTS = Set.of(
FACTORY,
SERVICE,
REPOSITORY,
IDENTIFIER,
VALUE_OBJECT,
ENTITY,
AGGREGATE_ROOT,
EVENT,
EVENT_LISTENER
);
}

Expand All @@ -80,9 +92,10 @@ class Concepts {
return Collections.emptyList();
}

return CachedValuesManager.getCachedValue(file, () ->
new CachedValueProvider.Result<>(CONCEPTS.stream()
return CachedValuesManager.getCachedValue(file,
() -> new CachedValueProvider.Result<>(All.ALL.stream()
.filter(it -> it.test((PsiJavaFile) file))
.map(ConceptImplementation::getConcept)
.collect(Collectors.toList()), file)
);
}
Expand Down
78 changes: 78 additions & 0 deletions src/main/java/org/xmolecules/ide/intellij/JMolecules.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.xmolecules.ide.intellij;

import com.intellij.openapi.roots.ExternalLibraryDescriptor;
import com.intellij.psi.PsiJavaFile;
import nexos.intellij.ddd.Framework;

import java.util.List;

import static org.xmolecules.ide.intellij.Types.implementsType;
import static org.xmolecules.ide.intellij.Types.isTypeAnnotatedWith;

public class JMolecules {

public static final Framework FRAMEWORK = new Framework("JMolecules");
public static final Library DDDLib = new Library(FRAMEWORK, new ExternalLibraryDescriptor("org.jmolecules","jmolecules-ddd"));
public static final Library EventsLib = new Library(FRAMEWORK, new ExternalLibraryDescriptor("org.jmolecules","jmolecules-events"));
public static final Library LayeredArchitectureLib = new Library(FRAMEWORK, new ExternalLibraryDescriptor("org.jmolecules","jmolecules-layered-architecture"));
public static final Library OnionArchitectureLib = new Library(FRAMEWORK, new ExternalLibraryDescriptor("org.jmolecules","jmolecules-onion-architecture"));

private static final String BASE_PACKAGE = "org.jmolecules";
private static final String DDD_BASE_PACKAGE = BASE_PACKAGE + ".ddd";
private static final String EVENT_BASE_PACKAGE = BASE_PACKAGE + ".event";

public static final ConceptImplementation FACTORY = new ConceptViaTypeAnnotation(Concepts.FACTORY, DDDLib, DDD_BASE_PACKAGE + ".annotation.Factory");
public static final ConceptImplementation SERVICE = new ConceptViaTypeAnnotation(Concepts.SERVICE, DDDLib, DDD_BASE_PACKAGE + ".annotation.Service");
public static final ConceptImplementation REPOSITORY_VIA_IMPLEMENTS = new ConceptViaImplements(Concepts.REPOSITORY,DDDLib, DDD_BASE_PACKAGE + ".types.Repository");
public static final ConceptImplementation REPOSITORY_VIA_TYPE_ANNOTATION = new ConceptViaTypeAnnotation(Concepts.REPOSITORY,DDDLib, DDD_BASE_PACKAGE + ".annotation.Repository");
public static final ConceptImplementation IDENTIFIER = new ConceptViaImplements(Concepts.IDENTIFIER, DDDLib, DDD_BASE_PACKAGE + ".types.Identifier");

//FIXME public static final ConceptImplementation VALUE_OBJECT = new ConceptImplementation(Concepts.VALUE_OBJECT, DDDLib, it -> JMolecules.isValueObject(it) && !JMolecules.isIdentifier(it), fqName);
//FIXME public static final ConceptImplementation ENTITY = new ConceptImplementation(Concepts.ENTITY, DDDLib, it -> JMolecules.isEntity(it) && !JMolecules.isAggregateRoot(it), fqName);

public static final ConceptImplementation AGGREGATE_ROOT_VIA_IMPLEMENTS = new ConceptViaImplements(Concepts.AGGREGATE_ROOT, DDDLib, DDD_BASE_PACKAGE + ".types.AggregateRoot");
public static final ConceptImplementation AGGREGATE_ROOT_VIA_TYPE_ANNOTATION = new ConceptViaTypeAnnotation(Concepts.AGGREGATE_ROOT, DDDLib, DDD_BASE_PACKAGE + ".annotation.AggregateRoot");
public static final ConceptImplementation EVENT_VIA_IMPLEMENTS = new ConceptViaImplements(Concepts.EVENT,EventsLib, EVENT_BASE_PACKAGE + ".types.DomainEvent");
public static final ConceptImplementation EVENT_VIA_TYPE_ANNOTATION = new ConceptViaTypeAnnotation(Concepts.EVENT,EventsLib, EVENT_BASE_PACKAGE + ".annotation.DomainEvent");
public static final ConceptImplementation EVENT_LISTENER = new ConceptViaTypeAnnotation(Concepts.EVENT_LISTENER, EventsLib,EVENT_BASE_PACKAGE + ".types.DomainEventHandler");

public static final List<ConceptImplementation> ALL = List.of(FACTORY, SERVICE, REPOSITORY_VIA_IMPLEMENTS,
REPOSITORY_VIA_TYPE_ANNOTATION, IDENTIFIER, /* VALUE_OBJECT, ENTITY, */ AGGREGATE_ROOT_VIA_IMPLEMENTS,
AGGREGATE_ROOT_VIA_TYPE_ANNOTATION, EVENT_VIA_IMPLEMENTS, EVENT_VIA_TYPE_ANNOTATION, EVENT_LISTENER);

static boolean isIdentifier(final PsiJavaFile file) {
return implementsType(DDD_BASE_PACKAGE + ".types.Identifier", file);
}

static boolean isEntity(final PsiJavaFile file) {
return implementsType(DDD_BASE_PACKAGE + ".types." + "Entity", file) ||
isTypeAnnotatedWith(DDD_BASE_PACKAGE + ".annotation." + "Entity", file);
}

static boolean isAggregateRoot(final PsiJavaFile file) {
return implementsType(DDD_BASE_PACKAGE + ".types." + "AggregateRoot", file) ||
isTypeAnnotatedWith(DDD_BASE_PACKAGE + ".annotation." + "AggregateRoot", file);
}

static boolean isValueObject(final PsiJavaFile file) {
return isTypeAnnotatedWith(DDD_BASE_PACKAGE + ".annotation.ValueObject", file);
}
}

/*
val DomainEvent = Info("org.jmolecules.event.annotation.DomainEvent", ddd_DomainEvent, EventsLib)

val ApplicationLayer = Info("org.jmolecules.architecture.layered.ApplicationLayer", ddd_ApplicationLayer, LayeredArchitectureLib)
val DomainLayer = Info("org.jmolecules.architecture.layered.DomainLayer", ddd_DomainLayer, LayeredArchitectureLib)
val InfrastructureLayer = Info("org.jmolecules.architecture.layered.InfrastructureLayer", ddd_InfrastructureLayer, LayeredArchitectureLib)
val InterfaceLayer = Info("org.jmolecules.architecture.layered.InterfaceLayer", ddd_InterfaceLayer, LayeredArchitectureLib)

val ClassicApplicationServiceRing = Info("org.jmolecules.architecture.onion.classical.ApplicationServiceRing", ddd_ClassicApplicationServiceRing, OnionArchitectureLib)
val ClassicDomainModelRing = Info("org.jmolecules.architecture.onion.classical.DomainModelRing", ddd_ClassicDomainModelRing, OnionArchitectureLib)
val ClassicInfrastructureRing = Info("org.jmolecules.architecture.onion.classical.InfrastructureRing", ddd_ClassicInfrastructureRing, OnionArchitectureLib)

val SimplifiedApplicationRing = Info("org.jmolecules.architecture.onion.simplified.ApplicationRing", ddd_SimplifiedApplicationRing, OnionArchitectureLib)
val SimplifiedDomainRing = Info("org.jmolecules.architecture.onion.simplified.DomainRing", ddd_SimplifiedDomainRing, OnionArchitectureLib)
val SimplifiedInfrastructureRing = Info("org.jmolecules.architecture.onion.simplified.InfrastructureRing", ddd_SimplifiedInfrastructureRing, OnionArchitectureLib)

*/
15 changes: 15 additions & 0 deletions src/main/java/org/xmolecules/ide/intellij/JPA.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.xmolecules.ide.intellij;

import com.intellij.openapi.roots.ExternalLibraryDescriptor;
import nexos.intellij.ddd.Framework;

import java.util.List;

public class JPA {
public static final Framework JPA = new Framework("JPA");
public static final Library LIB = new Library(JPA, new ExternalLibraryDescriptor("javax.persistence", "javax.persistence-api"));

public static final ConceptImplementation Entity = new ConceptViaTypeAnnotation(Concepts.ENTITY, LIB, "javax.persistence.Entity");
public static final ConceptImplementation Embeddable = new ConceptViaTypeAnnotation(Concepts.VALUE_OBJECT, LIB, "javax.persistence.Embeddable");
public static final List<ConceptImplementation> ALL = List.of(Entity, Embeddable);
}
22 changes: 22 additions & 0 deletions src/main/java/org/xmolecules/ide/intellij/Library.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.xmolecules.ide.intellij;

import com.intellij.openapi.roots.ExternalLibraryDescriptor;
import nexos.intellij.ddd.Framework;

public class Library {
private final Framework framework;
private final ExternalLibraryDescriptor externalLibrary;

public Library(final Framework framework, final ExternalLibraryDescriptor externalLibrary) {
this.framework = framework;
this.externalLibrary = externalLibrary;
}

public Framework getFramework() {
return framework;
}

public ExternalLibraryDescriptor getExternalLibrary() {
return externalLibrary;
}
}
24 changes: 24 additions & 0 deletions src/main/java/org/xmolecules/ide/intellij/Spring.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.xmolecules.ide.intellij;

import com.intellij.openapi.roots.ExternalLibraryDescriptor;
import com.intellij.psi.PsiJavaFile;
import nexos.intellij.ddd.Framework;

import java.util.List;

import static org.xmolecules.ide.intellij.Types.hasMethodAnnotatedWith;
import static org.xmolecules.ide.intellij.Types.implementsType;
import static org.xmolecules.ide.intellij.Types.isTypeAnnotatedWith;

public class Spring {
private static final String BASE_PACKAGE = "org.springframework.data";

private static final Framework FRAMEWORK = new Framework("Spring");
private static final Library LIB = new Library(FRAMEWORK, new ExternalLibraryDescriptor("org.springframework", ""));
public static final ConceptImplementation REPOSITORY_VIA_IMPLEMENTS = new ConceptViaImplements(Concepts.REPOSITORY,LIB, BASE_PACKAGE + ".repository.Repository");
public static final ConceptImplementation REPOSITORY_VIA_TYPE_ANNOTATION = new ConceptViaTypeAnnotation(Concepts.REPOSITORY,LIB, "org.springframework.stereotype.Repository");
public static final ConceptImplementation EVENT_LISTENER = new ConceptViaMethodAnnotation(Concepts.EVENT_LISTENER, LIB, "org.springframework.context.event.EventListener");
public static final ConceptImplementation EVENT_LISTENER_TRANSACTIONAL = new ConceptViaMethodAnnotation(Concepts.EVENT_LISTENER, LIB,"org.springframework.transaction.event.TransactionalEventListener");

public static final List<ConceptImplementation> ALL = List.of(REPOSITORY_VIA_IMPLEMENTS, REPOSITORY_VIA_TYPE_ANNOTATION, EVENT_LISTENER, EVENT_LISTENER_TRANSACTIONAL);
}
Loading
Loading