Skip to content

Commit

Permalink
GH-806 - Unrelated all subclasses and implementing classes.
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-simons committed Jul 7, 2020
1 parent 6ebdbbe commit 97d46ad
Show file tree
Hide file tree
Showing 11 changed files with 312 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ private void mapEntityReferences(final Object entity, NodeBuilder nodeBuilder, i

ClassInfo endNodeTypeClassInfo = metaData.classInfo(endNodeType);
if (endNodeTypeClassInfo != null) {
endNodeTypeClassInfo.directSubclasses()
endNodeTypeClassInfo.allSubclasses()
.stream().map(ClassInfo::getUnderlyingClass).forEach(potentiallyRelated::add);
}

Expand Down
34 changes: 34 additions & 0 deletions core/src/main/java/org/neo4j/ogm/metadata/ClassInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public class ClassInfo {
private static final Logger LOGGER = LoggerFactory.getLogger(ClassInfo.class);

private final List<ClassInfo> directSubclasses = new ArrayList<>();
private volatile Set<ClassInfo> allSubclasses;
private final List<ClassInfo> directInterfaces = new ArrayList<>();
private final List<ClassInfo> directImplementingClasses = new ArrayList<>();
/**
Expand Down Expand Up @@ -281,6 +282,39 @@ public List<ClassInfo> directSubclasses() {
return directSubclasses;
}

/**
* @return A list of all implementing and extending subclasses.
* @since 3.1.20
*/
public Collection<ClassInfo> allSubclasses() {

Set<ClassInfo> computedSubclasses = this.allSubclasses;
if (computedSubclasses == null) {
synchronized (this) {
computedSubclasses = this.allSubclasses;
if (computedSubclasses == null) {
this.allSubclasses = computeSubclasses();
computedSubclasses = this.allSubclasses;
}
}
}
return computedSubclasses;
}

private Set<ClassInfo> computeSubclasses() {

Set<ClassInfo> computedSubclasses = new HashSet<>();
for (ClassInfo classInfo : this.directSubclasses()) {
computedSubclasses.add(classInfo);
computedSubclasses.addAll(classInfo.allSubclasses());
}
for (ClassInfo classInfo : this.directImplementingClasses()) {
computedSubclasses.add(classInfo);
computedSubclasses.addAll(classInfo.allSubclasses());
}
return Collections.unmodifiableSet(computedSubclasses);
}

List<ClassInfo> directImplementingClasses() {
return directImplementingClasses;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public class Container {
@Relationship(type = "RELATES_TO", direction = "INCOMING")
Set<Element> element;

@Relationship(type = "RELATES_TO_AS_WELL", direction = "INCOMING")
Set<IElement> element2;

/**
* This is added to ensure we don't delete unrelated relationships.
*/
Expand Down Expand Up @@ -84,4 +87,12 @@ public void setElementsOfAnotherRelationship(
Set<ConcreteElement> elementsOfAnotherRelationship) {
this.elementsOfAnotherRelationship = elementsOfAnotherRelationship;
}

public Set<IElement> getElement2() {
return element2;
}

public void setElement2(Set<IElement> element2) {
this.element2 = element2;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2002-2020 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.ogm.domain.gh806;

import org.neo4j.ogm.annotation.NodeEntity;

/**
* @author Michael J. Simons
*/
@NodeEntity
public class EvenMoreConcreteElement extends VeryConcreteElementA {

public EvenMoreConcreteElement() {
}

public EvenMoreConcreteElement(String globalName) {
super(globalName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.neo4j.ogm.domain.gh806;

public interface IElement {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2002-2020 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.ogm.domain.gh806;

import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;

/**
* @author Michael J. Simons
*/
@NodeEntity
public class IElementImpl1 implements IElement{

@Id @GeneratedValue
Long id;

String name;

@Relationship(type = "RELATES_TO")
Container container;

public IElementImpl1() {
}

public IElementImpl1(String name) {
this.name = name;
}

public Long getId() {
return id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Container getContainer() {
return container;
}

public void setContainer(Container container) {
this.container = container;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2002-2020 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.ogm.domain.gh806;

import org.neo4j.ogm.annotation.NodeEntity;

/**
* @author Michael J. Simons
*/
@NodeEntity
public class IElementImpl1A extends IElementImpl1 {

public IElementImpl1A() {
}

public IElementImpl1A(String globalName) {
super(globalName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2002-2020 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.ogm.domain.gh806;

import org.neo4j.ogm.annotation.NodeEntity;

/**
* @author Michael J. Simons
*/
@NodeEntity
public class VeryConcreteElementA extends ConcreteElement {

public VeryConcreteElementA() {
}

public VeryConcreteElementA(String globalName) {
super(globalName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2002-2020 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.ogm.domain.gh806;

import org.neo4j.ogm.annotation.NodeEntity;

/**
* @author Michael J. Simons
*/
@NodeEntity
public class VeryConcreteElementB extends ConcreteElement {

public VeryConcreteElementB() {
}

public VeryConcreteElementB(String globalName) {
super(globalName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class DomainInfoTest {

@Before
public void setUp() {
domainInfo = DomainInfo.create("org.neo4j.ogm.domain.forum");
domainInfo = DomainInfo.create("org.neo4j.ogm.domain.forum", "org.neo4j.ogm.domain.gh806");
}

@Test
Expand All @@ -47,6 +47,32 @@ public void testInterfaceClassIMembership() {
assertThat(classInfo.directImplementingClasses()).hasSize(5);
}

@Test // GH-806
public void shouldFindAllSubclasses() {

ClassInfo classInfo = domainInfo.getClassSimpleName("Element");

assertThat(classInfo.allSubclasses())
.containsExactlyInAnyOrder(
domainInfo.getClassSimpleName("ConcreteElement"),
domainInfo.getClassSimpleName("VeryConcreteElementA"),
domainInfo.getClassSimpleName("VeryConcreteElementB"),
domainInfo.getClassSimpleName("EvenMoreConcreteElement")
);
}

@Test // GH-806
public void shouldFindAllImplementingClasses() {

ClassInfo classInfo = domainInfo.getClassSimpleName("IElement");

assertThat(classInfo.allSubclasses())
.containsExactlyInAnyOrder(
domainInfo.getClassSimpleName("IElementImpl1"),
domainInfo.getClassSimpleName("IElementImpl1A")
);
}

@Test
public void testAbstractClassMembership() {

Expand Down
Loading

0 comments on commit 97d46ad

Please sign in to comment.