|
1 | 1 | package dao.impl.jpa; |
2 | 2 |
|
3 | 3 | import config.MetamodelProvider; |
4 | | -import dao.ElementDao; |
5 | 4 | import dao.RelationshipDao; |
6 | 5 | import jpa.manager.JPAManager; |
7 | | -import org.hibernate.Session; |
8 | | -import org.hibernate.SessionFactory; |
9 | 6 | import org.omg.sysml.lifecycle.Commit; |
10 | | -import org.omg.sysml.lifecycle.Project; |
| 7 | +import org.omg.sysml.lifecycle.ElementVersion; |
11 | 8 | import org.omg.sysml.metamodel.Element; |
12 | 9 | import org.omg.sysml.metamodel.Relationship; |
13 | 10 | import org.omg.sysml.metamodel.impl.MofObjectImpl; |
|
17 | 14 | import javax.inject.Singleton; |
18 | 15 | import javax.persistence.NoResultException; |
19 | 16 | import javax.persistence.criteria.*; |
20 | | -import java.util.*; |
| 17 | +import java.util.List; |
| 18 | +import java.util.Optional; |
| 19 | +import java.util.Set; |
| 20 | +import java.util.UUID; |
21 | 21 | import java.util.stream.Collectors; |
22 | 22 | import java.util.stream.Stream; |
23 | 23 |
|
@@ -79,11 +79,110 @@ public void deleteAll() { |
79 | 79 | @Override |
80 | 80 | public Set<Relationship> findAllByCommitRelatedElement(Commit commit, Element relatedElement) { |
81 | 81 | return jpa.transact(em -> { |
82 | | - // TODO Commit is detached at this point. This ternary mitigates by requerying for the Commit in this transaction. A better solution would be moving transaction handling up to service layer (supported by general wisdom) and optionally migrating to using Play's @Transactional/JPAApi. Pros would include removal of repetitive transaction handling at the DAO layer and ability to interface with multiple DAOs in the same transaction (consistent view). Cons include increased temptation to keep transaction open for longer than needed, e.g. during JSON serialization due to the convenience of @Transactional (deprecated in >= 2.8.x), and the service, a higher level of abstraction, becoming aware of transactions. An alternative would be DAO-to-DAO calls (generally discouraged) and delegating to non-transactional versions of methods. |
83 | | - Commit c = em.contains(commit) ? commit : em.find(metamodelProvider.getImplementationClass(Commit.class), commit.getId()); |
84 | | - return elementDao.streamFlattenedElements(c).peek(System.out::println).filter(e -> e instanceof Relationship).map(e -> (Relationship) e) |
| 82 | +/* Commit c = em.contains(commit) ? commit : em.find(metamodelProvider.getImplementationClass(Commit.class), commit.getId()); |
| 83 | + return elementDao.streamFlattenedElements(c).filter(e -> e instanceof Relationship).map(e -> (Relationship) e) |
85 | 84 | .filter(relationship -> Stream.concat(relationship.getSource().stream(), relationship.getTarget().stream()).map(Element::getIdentifier).anyMatch(id -> id.equals(relatedElement.getIdentifier()))) |
86 | 85 | .collect(Collectors.toSet()); |
| 86 | + });*/ |
| 87 | + |
| 88 | + /*return jpa.transact(em -> { |
| 89 | + CommitIndex commitIndex = elementDao.getCommitIndex(commit, em); |
| 90 | +
|
| 91 | + CriteriaBuilder builder = em.getCriteriaBuilder(); |
| 92 | + CriteriaQuery<ElementVersionImpl> query = builder.createQuery(ElementVersionImpl.class); |
| 93 | + Root<CommitIndexImpl> commitIndexRoot = query.from(CommitIndexImpl.class); |
| 94 | + SetJoin<CommitIndexImpl, ElementVersionImpl> workingElementVersionsJoin = commitIndexRoot.join(CommitIndexImpl_.workingElementVersions); |
| 95 | + Join<ElementVersionImpl, MofObjectImpl> dataJoin = workingElementVersionsJoin.join(ElementVersionImpl_.identity); |
| 96 | + query.select(workingElementVersionsJoin).where( |
| 97 | + builder.equal(commitIndexRoot.get(CommitIndexImpl_.id), commitIndex.getId()), |
| 98 | + builder.equal(elementIdentityJoin.get(ElementIdentityImpl_.id), id) |
| 99 | + ); |
| 100 | + try { |
| 101 | + return Optional.of(em.createQuery(query).getSingleResult()).map(ElementVersion::getData).filter(mof -> mof instanceof Element).map(mof -> (Element) mof); |
| 102 | + } catch (NoResultException e) { |
| 103 | + return Optional.empty(); |
| 104 | + } |
| 105 | + });*/ |
| 106 | +/* Commit c = em.contains(commit) ? commit : em.find(metamodelProvider.getImplementationClass(Commit.class), commit.getId()); |
| 107 | + CommitIndex commitIndex = elementDao.getCommitIndex(c, em); |
| 108 | +
|
| 109 | + // Switching from Criteria API to HQL, because JPA 2 can't handle @Any for ElementVersion#data and no static metamodel is generated. |
| 110 | + // https://hibernate.atlassian.net/browse/HHH-6589 |
| 111 | + Session session = em.unwrap(Session.class); |
| 112 | +
|
| 113 | + Query<?> query2 = session.createQuery( |
| 114 | + "select relationship, source, target " + |
| 115 | + "from RelationshipImpl as relationship " + |
| 116 | + "join relationship.source source " + |
| 117 | + "join relationship.target target " + |
| 118 | + "where relationship.id in (" + |
| 119 | + "select elementVersion.data.id " + |
| 120 | + "from org.omg.sysml.internal.impl.CommitIndexImpl as commitIndex " + |
| 121 | + "join commitIndex.workingElementVersions as elementVersion " + |
| 122 | + "where commitIndex.id = :commitIndexId" + |
| 123 | + ")"); |
| 124 | + query2.setParameter("commitIndexId", commitIndex.getId()); |
| 125 | + query2.setParameter("relatedElementIdentifier", relatedElement.getIdentifier()); |
| 126 | + query2.list().forEach(System.out::println);*/ |
| 127 | + |
| 128 | + // Polymorphism ruins the day again. Attributes of @Any and @ManyToAny attributes can't be used in where or join clauses as their type is not known. Mitigating with nested queries. |
| 129 | + // Note that nested queries can only be used in select (but not from) and where clauses. |
| 130 | + |
| 131 | +/* Query<Relationship> query = session.createQuery( |
| 132 | + "select relationship " + |
| 133 | + "from org.omg.sysml.internal.impl.CommitIndexImpl as commitIndex, RelationshipImpl relationship " + |
| 134 | + "join commitIndex.workingElementVersions as elementVersion " + |
| 135 | + "join elementVersion.data as data " + |
| 136 | + "join relationship.source as source " + |
| 137 | + "join relationship.target as target " + |
| 138 | + "where commitIndex.id = :commitIndexId " + |
| 139 | + "and relationship.id = data.id " + |
| 140 | + "and relationship.class in :types " + |
| 141 | + "and (source.identifier = :relatedElementIdentifier or target.identifier = :relatedElementIdentifier)", |
| 142 | + Relationship.class); |
| 143 | + Query<Relationship> query = session.createQuery( |
| 144 | + "select relationship " + |
| 145 | + "from CommitIndexImpl commitIndex, ElementVersionImpl elementVersion, RelationshipImpl relationship " + |
| 146 | + "where commitIndex.id = :commitIndexId " + |
| 147 | + "and elementVersion. = ", |
| 148 | + Relationship.class); |
| 149 | + ); |
| 150 | + query.setParameter("commitIndexId", commitIndex.getId()); |
| 151 | + query.setParameter("types", getTypeStream().map(Class::getCanonicalName).collect(Collectors.toList())); |
| 152 | + query.setParameter("relatedElementIdentifier", relatedElement.getIdentifier()); |
| 153 | + return new LinkedHashSet<>(query.list());*/ |
| 154 | + |
| 155 | +/* Session session = em.unwrap(Session.class); |
| 156 | + Query<UUID> uuidQuery = session.createQuery( |
| 157 | + "select elementVersion.data.id " + |
| 158 | + "from org.omg.sysml.internal.impl.CommitIndexImpl as commitIndex " + |
| 159 | + "join commitIndex.workingElementVersions as elementVersion " + |
| 160 | + "where commitIndex.id = :commitIndexId", |
| 161 | + UUID.class); |
| 162 | + uuidQuery.setParameter("commitIndexId", commitIndex.getId()); |
| 163 | + List<UUID> uuids = uuidQuery.list(); |
| 164 | +
|
| 165 | + CriteriaBuilder builder = em.getCriteriaBuilder(); |
| 166 | + CriteriaQuery<RelationshipImpl> query = builder.createQuery(RelationshipImpl.class); |
| 167 | + Root<RelationshipImpl> relationshipRoot = query.from(RelationshipImpl.class); |
| 168 | + // java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [source] on this ManagedType [org.omg.sysml.metamodel.impl.MofObjectImpl] |
| 169 | + // Polymorphism strikes again... |
| 170 | + CollectionJoin<RelationshipImpl, Element> sourceJoin = relationshipRoot.joinCollection(RelationshipImpl_.SOURCE, JoinType.LEFT); |
| 171 | + CollectionJoin<RelationshipImpl, Element> targetJoin = relationshipRoot.joinCollection(RelationshipImpl_.TARGET, JoinType.LEFT); |
| 172 | +
|
| 173 | + query.select(relationshipRoot).where( |
| 174 | + relationshipRoot.get(RelationshipImpl_.id).in(uuids), |
| 175 | + builder.or( |
| 176 | + builder.equal(sourceJoin.get(ElementImpl_.IDENTIFIER), relatedElement.getIdentifier()), |
| 177 | + builder.equal(targetJoin.get(ElementImpl_.IDENTIFIER), relatedElement.getIdentifier()) |
| 178 | + ) |
| 179 | + ); |
| 180 | + return new LinkedHashSet<>(em.createQuery(query).getResultList());*/ |
| 181 | + |
| 182 | + // Reverting to non-relational streaming |
| 183 | + // TODO Commit is detached at this point. This ternary mitigates by requerying for the Commit in this transaction. A better solution would be moving transaction handling up to service layer (supported by general wisdom) and optionally migrating to using Play's @Transactional/JPAApi. Pros would include removal of repetitive transaction handling at the DAO layer and ability to interface with multiple DAOs in the same transaction (consistent view). Cons include increased temptation to keep transaction open for longer than needed, e.g. during JSON serialization due to the convenience of @Transactional (deprecated in >= 2.8.x), and the service, a higher level of abstraction, becoming aware of transactions. An alternative would be DAO-to-DAO calls (generally discouraged) and delegating to non-transactional versions of methods. |
| 184 | + Commit c = em.contains(commit) ? commit : em.find(metamodelProvider.getImplementationClass(Commit.class), commit.getId()); |
| 185 | + return elementDao.getCommitIndex(c, em).getWorkingElementVersions().stream().map(ElementVersion::getData).filter(mof -> mof instanceof Relationship).map(mof -> (Relationship) mof).filter(relationship -> Stream.concat(relationship.getSource().stream(), relationship.getTarget().stream()).map(Element::getIdentifier).anyMatch(id -> id.equals(relatedElement.getIdentifier()))).collect(Collectors.toSet()); |
87 | 186 | }); |
88 | 187 | } |
89 | 188 |
|
|
0 commit comments