From fec2ebe2133680a0ab68eebcf7b76b80163e8789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francesco=20Chicchiricc=C3=B2?= Date: Fri, 19 Jun 2026 15:00:42 +0200 Subject: [PATCH 1/3] Fixing Neo4j with workaround from https://github.com/spring-projects/spring-data-commons/issues/3500 --- core/persistence-neo4j/pom.xml | 6 - .../converters/AccessPolicyConfConverter.java | 28 ++++ .../neo4j/converters/AttrListConverter.java | 47 ++++++ .../AttrReleasePolicyConfConverter.java | 28 ++++ .../converters/AttrRepoConfConverter.java | 28 ++++ .../converters/AuthModuleConfConverter.java | 28 ++++ .../converters/AuthPolicyConfConverter.java | 28 ++++ .../ConnConfPropertyListConverter.java | 35 +++++ .../converters/ConnPoolConfConverter.java | 28 ++++ .../ConnectorCapabilitySetConverter.java | 35 +++++ .../GoogleMfaAuthAccountListConverter.java | 35 +++++ .../GoogleMfaAuthTokenListConverter.java | 35 +++++ .../ImpersonationAccountListConverter.java | 35 +++++ .../neo4j/converters/ItemListConverter.java | 34 +++++ .../converters/Locale2StringMapConverter.java | 35 +++++ .../MfaTrustedDeviceListConverter.java | 34 +++++ .../converters/OIDCGrantTypeSetConverter.java | 34 +++++ .../OIDCResponseTypeSetConverter.java | 34 +++++ .../neo4j/converters/OrgUnitConverter.java | 28 ++++ .../PasswordManagementConfConverter.java | 28 ++++ .../converters/ProvisionListConverter.java | 34 +++++ .../converters/SerializableConverter.java | 46 ++++++ .../converters/SerializableListConverter.java | 46 ++++++ .../converters/SerializableMapConverter.java | 46 ++++++ .../converters/SerializableSetConverter.java | 46 ++++++ .../String2SetOfStringMapConverter.java | 35 +++++ .../converters/String2StringMapConverter.java | 34 +++++ .../neo4j/converters/StringListConverter.java | 33 +++++ .../neo4j/converters/StringSetConverter.java | 33 +++++ .../TicketExpirationPolicyConfConverter.java | 28 ++++ ...sernameAttributeProviderConfConverter.java | 28 ++++ .../WAConsentDecisionListConverter.java | 35 +++++ ...WebAuthnDeviceCredentialListConverter.java | 35 +++++ .../XmlSecAlgorithmListConverter.java | 35 +++++ .../neo4j/dao/Neo4jOIDCOpEntityDAO.java | 5 +- .../persistence/neo4j/dao/Neo4jTaskDAO.java | 14 -- .../neo4j/dao/repo/AttrRepoRepoExtImpl.java | 6 +- .../neo4j/dao/repo/AuthModuleRepoExtImpl.java | 5 +- .../dao/repo/AuthProfileRepoExtImpl.java | 5 +- .../dao/repo/ConnInstanceRepoExtImpl.java | 2 - .../neo4j/dao/repo/DerSchemaRepoExtImpl.java | 3 - .../dao/repo/ExternalResourceRepoExtImpl.java | 4 - .../dao/repo/NotificationRepoExtImpl.java | 5 +- .../dao/repo/OIDCRPClientAppRepoExtImpl.java | 5 +- .../dao/repo/PlainSchemaRepoExtImpl.java | 3 - .../neo4j/dao/repo/RoleRepoExtImpl.java | 2 - .../dao/repo/SAML2SPClientAppRepoExtImpl.java | 5 +- .../neo4j/entity/AbstractNode.java | 3 - .../neo4j/entity/Neo4jConnInstance.java | 64 ++------ .../neo4j/entity/Neo4jExternalResource.java | 85 +++-------- .../neo4j/entity/Neo4jNotification.java | 52 +------ .../neo4j/entity/Neo4jPlainSchema.java | 47 +----- .../persistence/neo4j/entity/Neo4jRole.java | 39 +---- .../persistence/neo4j/entity/Neo4jSchema.java | 42 +----- .../neo4j/entity/am/AbstractClientApp.java | 26 ++-- .../entity/am/Neo4JPasswordManagement.java | 16 +- .../neo4j/entity/am/Neo4jAttrRepo.java | 53 ++----- .../neo4j/entity/am/Neo4jAuthModule.java | 53 ++----- .../neo4j/entity/am/Neo4jAuthProfile.java | 137 ++++-------------- .../neo4j/entity/am/Neo4jOIDCOpEntity.java | 40 +---- .../neo4j/entity/am/Neo4jOIDCRPClientApp.java | 92 ++---------- .../entity/am/Neo4jSAML2SPClientApp.java | 129 +++-------------- .../neo4j/entity/am/Neo4jWAConfigEntry.java | 16 +- .../entity/policy/Neo4jAccessPolicy.java | 11 +- .../entity/policy/Neo4jAttrReleasePolicy.java | 11 +- .../neo4j/entity/policy/Neo4jAuthPolicy.java | 13 +- .../policy/Neo4jTicketExpirationPolicy.java | 13 +- .../entity/task/Neo4jFormPropertyDef.java | 55 ++----- .../neo4j/entity/task/Neo4jLiveSyncTask.java | 6 +- .../neo4j/entity/task/Neo4jMacroTask.java | 6 +- .../entity/task/Neo4jNotificationTask.java | 45 +----- .../entity/task/Neo4jPropagationTask.java | 6 +- .../neo4j/entity/task/Neo4jPullTask.java | 6 +- .../neo4j/entity/task/Neo4jPushTask.java | 48 ++---- .../neo4j/entity/task/Neo4jSchedTask.java | 6 +- .../neo4j/entity/user/Neo4jUser.java | 21 +-- .../spring/security/SecurityProperties.java | 10 -- .../src/main/resources/core.properties | 2 - fit/core-reference/pom.xml | 6 - 79 files changed, 1395 insertions(+), 965 deletions(-) create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AccessPolicyConfConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrReleasePolicyConfConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrRepoConfConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AuthModuleConfConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AuthPolicyConfConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnConfPropertyListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnPoolConfConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnectorCapabilitySetConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/GoogleMfaAuthAccountListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/GoogleMfaAuthTokenListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ImpersonationAccountListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ItemListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/Locale2StringMapConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/MfaTrustedDeviceListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OIDCGrantTypeSetConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OIDCResponseTypeSetConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OrgUnitConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/PasswordManagementConfConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ProvisionListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableMapConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableSetConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/String2SetOfStringMapConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/String2StringMapConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/StringListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/StringSetConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/TicketExpirationPolicyConfConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/UsernameAttributeProviderConfConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/WAConsentDecisionListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/WebAuthnDeviceCredentialListConverter.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/XmlSecAlgorithmListConverter.java diff --git a/core/persistence-neo4j/pom.xml b/core/persistence-neo4j/pom.xml index dd4815e8ff6..9860f16f7f3 100644 --- a/core/persistence-neo4j/pom.xml +++ b/core/persistence-neo4j/pom.xml @@ -43,12 +43,6 @@ under the License. org.springframework.boot spring-boot-starter-data-neo4j - - - org.springframework.data - spring-data-commons - 4.0.5 - org.apache.syncope.core diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AccessPolicyConfConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AccessPolicyConfConverter.java new file mode 100644 index 00000000000..487e5060436 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AccessPolicyConfConverter.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import org.apache.syncope.common.lib.policy.AccessPolicyConf; + +public class AccessPolicyConfConverter extends SerializableConverter { + + public AccessPolicyConfConverter() { + super(AccessPolicyConf.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrListConverter.java new file mode 100644 index 00000000000..680dd2c4b00 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrListConverter.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import org.apache.syncope.common.lib.Attr; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.neo4j.driver.Value; +import org.neo4j.driver.Values; +import org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverter; +import tools.jackson.core.type.TypeReference; + +public class AttrListConverter implements Neo4jPersistentPropertyConverter> { + + protected static final TypeReference> TYPEREF = new TypeReference>() { + }; + + @Override + public Value write(final List source) { + return Optional.ofNullable(source). + map(POJOHelper::serialize).map(Values::value).orElse(Values.value(List.of())); + } + + @Override + public List read(final Value source) { + return Optional.ofNullable(source). + map(data -> POJOHelper.deserialize(source.asString(), TYPEREF)).orElseGet(ArrayList::new); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrReleasePolicyConfConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrReleasePolicyConfConverter.java new file mode 100644 index 00000000000..89c58fa475e --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrReleasePolicyConfConverter.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf; + +public class AttrReleasePolicyConfConverter extends SerializableConverter { + + public AttrReleasePolicyConfConverter() { + super(AttrReleasePolicyConf.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrRepoConfConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrRepoConfConverter.java new file mode 100644 index 00000000000..fb4094ccb5b --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AttrRepoConfConverter.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import org.apache.syncope.common.lib.attr.AttrRepoConf; + +public class AttrRepoConfConverter extends SerializableConverter { + + public AttrRepoConfConverter() { + super(AttrRepoConf.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AuthModuleConfConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AuthModuleConfConverter.java new file mode 100644 index 00000000000..857f3e7c16a --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AuthModuleConfConverter.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import org.apache.syncope.common.lib.auth.AuthModuleConf; + +public class AuthModuleConfConverter extends SerializableConverter { + + public AuthModuleConfConverter() { + super(AuthModuleConf.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AuthPolicyConfConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AuthPolicyConfConverter.java new file mode 100644 index 00000000000..114180278cf --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/AuthPolicyConfConverter.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import org.apache.syncope.common.lib.policy.AuthPolicyConf; + +public class AuthPolicyConfConverter extends SerializableConverter { + + public AuthPolicyConfConverter() { + super(AuthPolicyConf.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnConfPropertyListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnConfPropertyListConverter.java new file mode 100644 index 00000000000..b958b3b9f63 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnConfPropertyListConverter.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.List; +import org.apache.syncope.common.lib.types.ConnConfProperty; +import tools.jackson.core.type.TypeReference; + +public class ConnConfPropertyListConverter extends SerializableListConverter { + + protected static final TypeReference> TYPEREF = + new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnPoolConfConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnPoolConfConverter.java new file mode 100644 index 00000000000..578369d645c --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnPoolConfConverter.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import org.apache.syncope.common.lib.types.ConnPoolConf; + +public class ConnPoolConfConverter extends SerializableConverter { + + public ConnPoolConfConverter() { + super(ConnPoolConf.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnectorCapabilitySetConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnectorCapabilitySetConverter.java new file mode 100644 index 00000000000..010ca80816f --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ConnectorCapabilitySetConverter.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.Set; +import org.apache.syncope.common.lib.types.ConnectorCapability; +import tools.jackson.core.type.TypeReference; + +public class ConnectorCapabilitySetConverter extends SerializableSetConverter { + + protected static final TypeReference> TYPEREF = + new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/GoogleMfaAuthAccountListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/GoogleMfaAuthAccountListConverter.java new file mode 100644 index 00000000000..bbb85eff8a0 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/GoogleMfaAuthAccountListConverter.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.List; +import org.apache.syncope.common.lib.wa.GoogleMfaAuthAccount; +import tools.jackson.core.type.TypeReference; + +public class GoogleMfaAuthAccountListConverter extends SerializableListConverter { + + protected static final TypeReference> TYPEREF = + new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/GoogleMfaAuthTokenListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/GoogleMfaAuthTokenListConverter.java new file mode 100644 index 00000000000..9bc30bca6bd --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/GoogleMfaAuthTokenListConverter.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.List; +import org.apache.syncope.common.lib.wa.GoogleMfaAuthToken; +import tools.jackson.core.type.TypeReference; + +public class GoogleMfaAuthTokenListConverter extends SerializableListConverter { + + protected static final TypeReference> TYPEREF = + new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ImpersonationAccountListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ImpersonationAccountListConverter.java new file mode 100644 index 00000000000..c0935b45374 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ImpersonationAccountListConverter.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.List; +import org.apache.syncope.common.lib.wa.ImpersonationAccount; +import tools.jackson.core.type.TypeReference; + +public class ImpersonationAccountListConverter extends SerializableListConverter { + + protected static final TypeReference> TYPEREF = + new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ItemListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ItemListConverter.java new file mode 100644 index 00000000000..050220abb3d --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ItemListConverter.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.List; +import org.apache.syncope.common.lib.to.Item; +import tools.jackson.core.type.TypeReference; + +public class ItemListConverter extends SerializableListConverter { + + protected static final TypeReference> TYPEREF = new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/Locale2StringMapConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/Locale2StringMapConverter.java new file mode 100644 index 00000000000..f8d230ba71f --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/Locale2StringMapConverter.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.HashMap; +import java.util.Locale; +import tools.jackson.core.type.TypeReference; + +public class Locale2StringMapConverter extends SerializableMapConverter { + + protected static final TypeReference> TYPEREF = + new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/MfaTrustedDeviceListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/MfaTrustedDeviceListConverter.java new file mode 100644 index 00000000000..b2fea9227c4 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/MfaTrustedDeviceListConverter.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.List; +import org.apache.syncope.common.lib.wa.MfaTrustedDevice; +import tools.jackson.core.type.TypeReference; + +public class MfaTrustedDeviceListConverter extends SerializableListConverter { + + protected static final TypeReference> TYPEREF = new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OIDCGrantTypeSetConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OIDCGrantTypeSetConverter.java new file mode 100644 index 00000000000..796e152c671 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OIDCGrantTypeSetConverter.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.Set; +import org.apache.syncope.common.lib.types.OIDCGrantType; +import tools.jackson.core.type.TypeReference; + +public class OIDCGrantTypeSetConverter extends SerializableSetConverter { + + protected static final TypeReference> TYPEREF = new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OIDCResponseTypeSetConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OIDCResponseTypeSetConverter.java new file mode 100644 index 00000000000..f666f81168d --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OIDCResponseTypeSetConverter.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.Set; +import org.apache.syncope.common.lib.types.OIDCResponseType; +import tools.jackson.core.type.TypeReference; + +public class OIDCResponseTypeSetConverter extends SerializableSetConverter { + + protected static final TypeReference> TYPEREF = new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OrgUnitConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OrgUnitConverter.java new file mode 100644 index 00000000000..cc0d6adc553 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/OrgUnitConverter.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import org.apache.syncope.common.lib.to.OrgUnit; + +public class OrgUnitConverter extends SerializableConverter { + + public OrgUnitConverter() { + super(OrgUnit.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/PasswordManagementConfConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/PasswordManagementConfConverter.java new file mode 100644 index 00000000000..3ccff8697a8 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/PasswordManagementConfConverter.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import org.apache.syncope.common.lib.password.PasswordManagementConf; + +public class PasswordManagementConfConverter extends SerializableConverter { + + public PasswordManagementConfConverter() { + super(PasswordManagementConf.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ProvisionListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ProvisionListConverter.java new file mode 100644 index 00000000000..e08b47521b7 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/ProvisionListConverter.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.List; +import org.apache.syncope.common.lib.to.Provision; +import tools.jackson.core.type.TypeReference; + +public class ProvisionListConverter extends SerializableListConverter { + + protected static final TypeReference> TYPEREF = new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableConverter.java new file mode 100644 index 00000000000..37c92ab2541 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableConverter.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.io.Serializable; +import java.util.Optional; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.neo4j.driver.Value; +import org.neo4j.driver.Values; +import org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverter; + +abstract class SerializableConverter implements Neo4jPersistentPropertyConverter { + + protected final Class reference; + + protected SerializableConverter(final Class reference) { + this.reference = reference; + } + + @Override + public Value write(final T source) { + return Optional.ofNullable(source).map(POJOHelper::serialize).map(Values::value).orElse(Values.NULL); + } + + @Override + public T read(final Value source) { + return Optional.ofNullable(source). + map(data -> POJOHelper.deserialize(source.asString(), reference)).orElse(null); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableListConverter.java new file mode 100644 index 00000000000..aecfb3359cd --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableListConverter.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.neo4j.driver.Value; +import org.neo4j.driver.Values; +import org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverter; +import tools.jackson.core.type.TypeReference; + +abstract class SerializableListConverter implements Neo4jPersistentPropertyConverter> { + + protected abstract TypeReference> typeRef(); + + @Override + public Value write(final List source) { + return Optional.ofNullable(source).map(POJOHelper::serialize).map(Values::value). + orElse(Values.value(List.of())); + } + + @Override + public List read(final Value source) { + return Optional.ofNullable(source). + map(data -> POJOHelper.deserialize(source.asString(), typeRef())).orElseGet(ArrayList::new); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableMapConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableMapConverter.java new file mode 100644 index 00000000000..f1b1e498021 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableMapConverter.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.neo4j.driver.Value; +import org.neo4j.driver.Values; +import org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverter; +import tools.jackson.core.type.TypeReference; + +abstract class SerializableMapConverter + implements Neo4jPersistentPropertyConverter> { + + protected abstract TypeReference> typeRef(); + + @Override + public Value write(final Map source) { + return Optional.ofNullable(source).map(POJOHelper::serialize).map(Values::value).orElse(Values.EmptyMap); + } + + @Override + public Map read(final Value source) { + return Optional.ofNullable(source). + map(data -> POJOHelper.deserialize(source.asString(), typeRef())).orElseGet(HashMap::new); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableSetConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableSetConverter.java new file mode 100644 index 00000000000..2c94d93e92a --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/SerializableSetConverter.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.neo4j.driver.Value; +import org.neo4j.driver.Values; +import org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverter; +import tools.jackson.core.type.TypeReference; + +abstract class SerializableSetConverter implements Neo4jPersistentPropertyConverter> { + + protected abstract TypeReference> typeRef(); + + @Override + public Value write(final Set source) { + return Optional.ofNullable(source).map(POJOHelper::serialize).map(Values::value). + orElse(Values.value(Set.of())); + } + + @Override + public Set read(final Value source) { + return Optional.ofNullable(source). + map(data -> POJOHelper.deserialize(source.asString(), typeRef())).orElseGet(HashSet::new); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/String2SetOfStringMapConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/String2SetOfStringMapConverter.java new file mode 100644 index 00000000000..8b9ab41525a --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/String2SetOfStringMapConverter.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.HashMap; +import java.util.Set; +import tools.jackson.core.type.TypeReference; + +public class String2SetOfStringMapConverter extends SerializableMapConverter> { + + protected static final TypeReference>> TYPEREF = + new TypeReference>>() { + }; + + @Override + protected TypeReference>> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/String2StringMapConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/String2StringMapConverter.java new file mode 100644 index 00000000000..cd64db8fa05 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/String2StringMapConverter.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.HashMap; +import tools.jackson.core.type.TypeReference; + +public class String2StringMapConverter extends SerializableMapConverter { + + protected static final TypeReference> TYPEREF = + new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/StringListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/StringListConverter.java new file mode 100644 index 00000000000..5cd20f4ba7f --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/StringListConverter.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.List; +import tools.jackson.core.type.TypeReference; + +public class StringListConverter extends SerializableListConverter { + + protected static final TypeReference> TYPEREF = new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/StringSetConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/StringSetConverter.java new file mode 100644 index 00000000000..72df8325951 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/StringSetConverter.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.Set; +import tools.jackson.core.type.TypeReference; + +public class StringSetConverter extends SerializableSetConverter { + + protected static final TypeReference> TYPEREF = new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/TicketExpirationPolicyConfConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/TicketExpirationPolicyConfConverter.java new file mode 100644 index 00000000000..1c87bc54c94 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/TicketExpirationPolicyConfConverter.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import org.apache.syncope.common.lib.policy.TicketExpirationPolicyConf; + +public class TicketExpirationPolicyConfConverter extends SerializableConverter { + + public TicketExpirationPolicyConfConverter() { + super(TicketExpirationPolicyConf.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/UsernameAttributeProviderConfConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/UsernameAttributeProviderConfConverter.java new file mode 100644 index 00000000000..95bc2e4efb8 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/UsernameAttributeProviderConfConverter.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import org.apache.syncope.common.lib.clientapps.UsernameAttributeProviderConf; + +public class UsernameAttributeProviderConfConverter extends SerializableConverter { + + public UsernameAttributeProviderConfConverter() { + super(UsernameAttributeProviderConf.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/WAConsentDecisionListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/WAConsentDecisionListConverter.java new file mode 100644 index 00000000000..de016e06277 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/WAConsentDecisionListConverter.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.List; +import org.apache.syncope.common.lib.wa.WAConsentDecision; +import tools.jackson.core.type.TypeReference; + +public class WAConsentDecisionListConverter extends SerializableListConverter { + + protected static final TypeReference> TYPEREF = + new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/WebAuthnDeviceCredentialListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/WebAuthnDeviceCredentialListConverter.java new file mode 100644 index 00000000000..2e8e2a21f51 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/WebAuthnDeviceCredentialListConverter.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.List; +import org.apache.syncope.common.lib.wa.WebAuthnDeviceCredential; +import tools.jackson.core.type.TypeReference; + +public class WebAuthnDeviceCredentialListConverter extends SerializableListConverter { + + protected static final TypeReference> TYPEREF = + new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/XmlSecAlgorithmListConverter.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/XmlSecAlgorithmListConverter.java new file mode 100644 index 00000000000..e9f8715883a --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/converters/XmlSecAlgorithmListConverter.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.persistence.neo4j.converters; + +import java.util.List; +import org.apache.syncope.common.lib.types.XmlSecAlgorithm; +import tools.jackson.core.type.TypeReference; + +public class XmlSecAlgorithmListConverter extends SerializableListConverter { + + protected static final TypeReference> TYPEREF = + new TypeReference>() { + }; + + @Override + protected TypeReference> typeRef() { + return TYPEREF; + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jOIDCOpEntityDAO.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jOIDCOpEntityDAO.java index 8280fae9c45..3dcf7e7ee07 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jOIDCOpEntityDAO.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jOIDCOpEntityDAO.java @@ -45,10 +45,7 @@ public Optional get() { @Override public OIDCOpEntity save(final OIDCOpEntity oidcOp) { - ((Neo4jOIDCOpEntity) oidcOp).map2json(); - OIDCOpEntity saved = neo4jTemplate.save(nodeValidator.validate(oidcOp)); - ((Neo4jOIDCOpEntity) saved).postSave(); - return saved; + return neo4jTemplate.save(nodeValidator.validate(oidcOp)); } @Override diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jTaskDAO.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jTaskDAO.java index 924d553d285..1d934be33d9 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jTaskDAO.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jTaskDAO.java @@ -484,21 +484,9 @@ public > List findAll( public > T save(final T task) { task.getExecs().forEach(exec -> neo4jTemplate.save(nodeValidator.validate(exec))); - switch (task) { - case Neo4jNotificationTask notificationTask -> - notificationTask.list2json(); - case Neo4jPushTask pushTask -> - pushTask.map2json(); - default -> { - } - } - T saved = neo4jTemplate.save(nodeValidator.validate(task)); switch (saved) { - case Neo4jNotificationTask notificationTask -> - notificationTask.postSave(); - case Neo4jPullTask pullTask -> neo4jTemplate.findById(pullTask.getKey(), Neo4jPullTask.class).ifPresent(t -> { if (t.getReconFilterBuilder() != null && pullTask.getReconFilterBuilder() == null) { @@ -519,8 +507,6 @@ public > T save(final T task) { }); case Neo4jPushTask pushTask -> { - pushTask.postSave(); - neo4jTemplate.findById(pushTask.getKey(), Neo4jPushTask.class). ifPresent(t -> t.getActions().stream().filter(act -> !pushTask.getActions().contains(act)). forEach(impl -> deleteRelationship( diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AttrRepoRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AttrRepoRepoExtImpl.java index acc9fa32fc1..97e664570d9 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AttrRepoRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AttrRepoRepoExtImpl.java @@ -19,7 +19,6 @@ package org.apache.syncope.core.persistence.neo4j.dao.repo; import org.apache.syncope.core.persistence.api.entity.am.AttrRepo; -import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jAttrRepo; import org.apache.syncope.core.persistence.neo4j.spring.NodeValidator; import org.springframework.data.neo4j.core.Neo4jTemplate; @@ -36,9 +35,6 @@ public AttrRepoRepoExtImpl(final Neo4jTemplate neo4jTemplate, final NodeValidato @Override public AttrRepo save(final AttrRepo attrRepo) { - ((Neo4jAttrRepo) attrRepo).list2json(); - AttrRepo saved = neo4jTemplate.save(nodeValidator.validate(attrRepo)); - ((Neo4jAttrRepo) saved).postSave(); - return saved; + return neo4jTemplate.save(nodeValidator.validate(attrRepo)); } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AuthModuleRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AuthModuleRepoExtImpl.java index ab26c528520..66fc844512e 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AuthModuleRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AuthModuleRepoExtImpl.java @@ -46,10 +46,7 @@ public AuthModuleRepoExtImpl( @Override public AuthModule save(final AuthModule authModule) { - ((Neo4jAuthModule) authModule).list2json(); - AuthModule saved = neo4jTemplate.save(nodeValidator.validate(authModule)); - ((Neo4jAuthModule) saved).postSave(); - return saved; + return neo4jTemplate.save(nodeValidator.validate(authModule)); } @Override diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AuthProfileRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AuthProfileRepoExtImpl.java index 9f266e3b6c1..c7735b6e870 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AuthProfileRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/AuthProfileRepoExtImpl.java @@ -66,9 +66,6 @@ public long countByOwnerLike(final String owner) { @Override public AuthProfile save(final AuthProfile connector) { - ((Neo4jAuthProfile) connector).list2json(); - AuthProfile saved = neo4jTemplate.save(nodeValidator.validate(connector)); - ((Neo4jAuthProfile) saved).postSave(); - return saved; + return neo4jTemplate.save(nodeValidator.validate(connector)); } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/ConnInstanceRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/ConnInstanceRepoExtImpl.java index 71b8a4a9181..34eb3360ab7 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/ConnInstanceRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/ConnInstanceRepoExtImpl.java @@ -110,9 +110,7 @@ public List findAll() { @Override public ConnInstance save(final ConnInstance connector) { - ((Neo4jConnInstance) connector).list2json(); ConnInstance saved = neo4jTemplate.save(nodeValidator.validate(connector)); - ((Neo4jConnInstance) saved).postSave(); resourceDAO.findByConnInstance(saved.getKey()). forEach(resource -> resourceCache.remove(EntityCacheKey.of(resource.getKey()))); diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/DerSchemaRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/DerSchemaRepoExtImpl.java index a92911bfabd..f33ab1eb0e7 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/DerSchemaRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/DerSchemaRepoExtImpl.java @@ -28,7 +28,6 @@ import org.apache.syncope.core.persistence.api.entity.Schema; import org.apache.syncope.core.persistence.neo4j.entity.EntityCacheKey; import org.apache.syncope.core.persistence.neo4j.entity.Neo4jDerSchema; -import org.apache.syncope.core.persistence.neo4j.entity.Neo4jSchema; import org.apache.syncope.core.persistence.neo4j.spring.NodeValidator; import org.springframework.data.neo4j.core.Neo4jClient; import org.springframework.data.neo4j.core.Neo4jTemplate; @@ -77,9 +76,7 @@ public List findByAnyTypeClasses(final Collection schemaKey.equals(item.getIntAttrName()))))); if (removed.get()) { - resource.list2json(); Neo4jExternalResource saved = neo4jTemplate.save(resource); - saved.postSave(); cache.put(EntityCacheKey.of(resource.getKey()), saved); } }); diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/NotificationRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/NotificationRepoExtImpl.java index 125a75261a6..bc04f588bc4 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/NotificationRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/NotificationRepoExtImpl.java @@ -64,10 +64,7 @@ public List findByTemplate(final MailTemplate template) { @Override public Notification save(final Notification notification) { - ((Neo4jNotification) notification).list2json(); - Notification saved = neo4jTemplate.save(nodeValidator.validate(notification)); - ((Neo4jNotification) saved).postSave(); - return saved; + return neo4jTemplate.save(nodeValidator.validate(notification)); } @Override diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/OIDCRPClientAppRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/OIDCRPClientAppRepoExtImpl.java index e5f1bc1564c..e8ae4cb61b7 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/OIDCRPClientAppRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/OIDCRPClientAppRepoExtImpl.java @@ -54,9 +54,6 @@ public List findAllByRealm(final Realm realm) { @Override public OIDCRPClientApp save(final OIDCRPClientApp clientApp) { - ((Neo4jOIDCRPClientApp) clientApp).list2json(); - OIDCRPClientApp saved = neo4jTemplate.save(nodeValidator.validate(clientApp)); - ((Neo4jOIDCRPClientApp) saved).postSave(); - return saved; + return neo4jTemplate.save(nodeValidator.validate(clientApp)); } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PlainSchemaRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PlainSchemaRepoExtImpl.java index 008db24074b..0fb55654b86 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PlainSchemaRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PlainSchemaRepoExtImpl.java @@ -35,7 +35,6 @@ import org.apache.syncope.core.persistence.neo4j.entity.Neo4jImplementation; import org.apache.syncope.core.persistence.neo4j.entity.Neo4jPlainSchema; import org.apache.syncope.core.persistence.neo4j.entity.Neo4jRealm; -import org.apache.syncope.core.persistence.neo4j.entity.Neo4jSchema; import org.apache.syncope.core.persistence.neo4j.entity.anyobject.Neo4jAnyObject; import org.apache.syncope.core.persistence.neo4j.entity.group.Neo4jGroup; import org.apache.syncope.core.persistence.neo4j.entity.user.Neo4jLinkedAccount; @@ -180,9 +179,7 @@ public PlainSchema save(final PlainSchema schema) { } }); - ((Neo4jSchema) schema).map2json(); PlainSchema saved = neo4jTemplate.save(nodeValidator.validate(schema)); - ((Neo4jSchema) saved).postSave(); plainSchemaCache.put(EntityCacheKey.of(schema.getKey()), (Neo4jPlainSchema) saved); diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/RoleRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/RoleRepoExtImpl.java index 67e1b6dd39f..b540e2ca0eb 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/RoleRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/RoleRepoExtImpl.java @@ -84,9 +84,7 @@ public List findByRealms(final Realm realm) { @Override public Role save(final Role role) { - ((Neo4jRole) role).list2json(); Role saved = neo4jTemplate.save(nodeValidator.validate(role)); - ((Neo4jRole) saved).postSave(); cache.put(EntityCacheKey.of(saved.getKey()), (Neo4jRole) saved); return saved; } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/SAML2SPClientAppRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/SAML2SPClientAppRepoExtImpl.java index a06168731d9..eaac6973b89 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/SAML2SPClientAppRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/SAML2SPClientAppRepoExtImpl.java @@ -54,9 +54,6 @@ public List findAllByRealm(final Realm realm) { @Override public SAML2SPClientApp save(final SAML2SPClientApp clientApp) { - ((Neo4jSAML2SPClientApp) clientApp).list2json(); - SAML2SPClientApp saved = neo4jTemplate.save(nodeValidator.validate(clientApp)); - ((Neo4jSAML2SPClientApp) saved).postSave(); - return saved; + return neo4jTemplate.save(nodeValidator.validate(clientApp)); } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/AbstractNode.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/AbstractNode.java index f7e238110c8..5021630c8f0 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/AbstractNode.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/AbstractNode.java @@ -18,15 +18,12 @@ */ package org.apache.syncope.core.persistence.neo4j.entity; -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.fasterxml.jackson.annotation.ObjectIdGenerators; import java.util.Objects; import org.apache.syncope.core.persistence.api.entity.Entity; import org.apache.syncope.core.persistence.api.entity.Implementation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "key") public abstract class AbstractNode implements Entity { private static final long serialVersionUID = -9017214159540857901L; diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jConnInstance.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jConnInstance.java index 3661ada1e93..2b18f198a78 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jConnInstance.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jConnInstance.java @@ -30,12 +30,12 @@ import org.apache.syncope.core.persistence.api.entity.ConnInstance; import org.apache.syncope.core.persistence.api.entity.Realm; import org.apache.syncope.core.persistence.common.validation.ConnInstanceCheck; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.apache.syncope.core.persistence.neo4j.converters.ConnConfPropertyListConverter; +import org.apache.syncope.core.persistence.neo4j.converters.ConnPoolConfConverter; +import org.apache.syncope.core.persistence.neo4j.converters.ConnectorCapabilitySetConverter; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; import org.springframework.data.neo4j.core.schema.Relationship; -import tools.jackson.core.type.TypeReference; @Node(Neo4jConnInstance.NODE) @ConnInstanceCheck @@ -45,14 +45,6 @@ public class Neo4jConnInstance extends AbstractGeneratedKeyNode implements ConnI public static final String NODE = "ConnInstance"; - protected static final TypeReference> CONNECTOR_CAPABILITY_TYPEREF = - new TypeReference>() { - }; - - protected static final TypeReference> CONN_CONF_PROPS_TYPEREF = - new TypeReference>() { - }; - /** * URI identifying the local / remote ConnId location where the related connector bundle is found. */ @@ -77,10 +69,8 @@ public class Neo4jConnInstance extends AbstractGeneratedKeyNode implements ConnI @NotNull private String version; - private String capabilities; - - @Transient - private Set capabilitiesSet = new HashSet<>(); + @ConvertWith(converter = ConnectorCapabilitySetConverter.class) + private Set capabilities = new HashSet<>(); /** * The main configuration for the connector instance. This is directly implemented by the Configuration bean class @@ -88,10 +78,8 @@ public class Neo4jConnInstance extends AbstractGeneratedKeyNode implements ConnI * * @see org.identityconnectors.framework.api.ConfigurationProperty */ - private String jsonConf; - - @Transient - private List conf = new ArrayList<>(); + @ConvertWith(converter = ConnConfPropertyListConverter.class) + private List jsonConf = new ArrayList<>(); private String displayName; @@ -102,7 +90,8 @@ public class Neo4jConnInstance extends AbstractGeneratedKeyNode implements ConnI */ private Integer connRequestTimeout = DEFAULT_TIMEOUT; - private String poolConf; + @ConvertWith(converter = ConnPoolConfConverter.class) + private ConnPoolConf poolConf; @Relationship(direction = Relationship.Direction.OUTGOING, cascadeUpdates = false) private Neo4jRealm adminRealm; @@ -160,7 +149,7 @@ public void setVersion(final String version) { @Override public List getConf() { - return conf; + return jsonConf; } @Override @@ -175,7 +164,7 @@ public void setDisplayName(final String displayName) { @Override public Set getCapabilities() { - return capabilitiesSet; + return capabilities; } @Override @@ -190,36 +179,11 @@ public void setConnRequestTimeout(final Integer timeout) { @Override public ConnPoolConf getPoolConf() { - return Optional.ofNullable(poolConf).map(pc -> POJOHelper.deserialize(pc, ConnPoolConf.class)).orElse(null); + return poolConf; } @Override public void setPoolConf(final ConnPoolConf poolConf) { - this.poolConf = Optional.ofNullable(poolConf).map(POJOHelper::serialize).orElse(null); - } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getCapabilities().clear(); - getConf().clear(); - } - Optional.ofNullable(capabilities). - ifPresent(v -> getCapabilities().addAll(POJOHelper.deserialize(v, CONNECTOR_CAPABILITY_TYPEREF))); - Optional.ofNullable(jsonConf). - ifPresent(v -> getConf().addAll(POJOHelper.deserialize(v, CONN_CONF_PROPS_TYPEREF))); - } - - @PostLoad - public void postLoad() { - json2list(false); - } - - public void postSave() { - json2list(true); - } - - public void list2json() { - capabilities = POJOHelper.serialize(getCapabilities()); - jsonConf = POJOHelper.serialize(getConf()); + this.poolConf = poolConf; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jExternalResource.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jExternalResource.java index dca3a66ac39..8b76ca05408 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jExternalResource.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jExternalResource.java @@ -20,12 +20,14 @@ import jakarta.validation.constraints.NotNull; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; -import org.apache.commons.lang3.StringUtils; +import java.util.function.Predicate; import org.apache.syncope.common.lib.to.OrgUnit; import org.apache.syncope.common.lib.to.Provision; import org.apache.syncope.common.lib.types.ConnConfProperty; @@ -41,17 +43,19 @@ import org.apache.syncope.core.persistence.api.entity.policy.PropagationPolicy; import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy; import org.apache.syncope.core.persistence.common.validation.ExternalResourceCheck; +import org.apache.syncope.core.persistence.neo4j.converters.ConnConfPropertyListConverter; +import org.apache.syncope.core.persistence.neo4j.converters.ConnectorCapabilitySetConverter; +import org.apache.syncope.core.persistence.neo4j.converters.OrgUnitConverter; +import org.apache.syncope.core.persistence.neo4j.converters.ProvisionListConverter; import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jAccountPolicy; import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jInboundPolicy; import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jPasswordPolicy; import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jPropagationPolicy; import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jPushPolicy; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; import org.springframework.data.annotation.Transient; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; import org.springframework.data.neo4j.core.schema.Relationship; -import tools.jackson.core.type.TypeReference; @Node(Neo4jExternalResource.NODE) @ExternalResourceCheck @@ -77,18 +81,6 @@ public class Neo4jExternalResource extends AbstractProvidedKeyNode implements Ex public static final String RESOURCE_PROPAGATION_ACTIONS_REL = "RESOURCE_PROPAGATION_ACTIONS"; - protected static final TypeReference> CONN_CONF_PROPS_TYPEREF = - new TypeReference>() { - }; - - protected static final TypeReference> CONNECTOR_CAPABILITY_TYPEREF = - new TypeReference>() { - }; - - protected static final TypeReference> PROVISION_TYPEREF = - new TypeReference>() { - }; - /** * Should this resource enforce the mandatory constraints? */ @@ -115,16 +107,17 @@ public class Neo4jExternalResource extends AbstractProvidedKeyNode implements Ex /** * Configuration properties that are override from the connector instance. */ - private String jsonConf; + @ConvertWith(converter = ConnConfPropertyListConverter.class) + private List jsonConf = new ArrayList<>(); - private String capabilitiesOverride; + @ConvertWith(converter = ConnectorCapabilitySetConverter.class) + private Set capabilitiesOverride = new HashSet<>(); - private String provisions; + @ConvertWith(converter = ProvisionListConverter.class) + private List provisions = new ArrayList<>(); - @Transient - private final List provisionList = new ArrayList<>(); - - private String orgUnit; + @ConvertWith(converter = OrgUnitConverter.class) + private OrgUnit orgUnit; /** * The resource type is identified by the associated connector. @@ -185,17 +178,17 @@ public Optional getProvisionByObjectClass(final String objectClass) { @Override public List getProvisions() { - return provisionList; + return provisions; } @Override public OrgUnit getOrgUnit() { - return Optional.ofNullable(orgUnit).map(ou -> POJOHelper.deserialize(ou, OrgUnit.class)).orElse(null); + return orgUnit; } @Override public void setOrgUnit(final OrgUnit orgUnit) { - this.orgUnit = orgUnit == null ? null : POJOHelper.serialize(orgUnit); + this.orgUnit = orgUnit; } @Override @@ -329,30 +322,23 @@ public void setProvisionSorter(final Implementation provisionSorter) { @Override public Optional> getConfOverride() { - return StringUtils.isBlank(jsonConf) - ? Optional.empty() - : Optional.of(POJOHelper.deserialize(jsonConf, CONN_CONF_PROPS_TYPEREF)); + return Optional.ofNullable(jsonConf).filter(Predicate.not(Collection::isEmpty)); + } @Override public void setConfOverride(final Optional> confOverride) { - confOverride.ifPresentOrElse( - conf -> jsonConf = POJOHelper.serialize(conf), - () -> jsonConf = null); + jsonConf = confOverride.orElse(null); } @Override public Optional> getCapabilitiesOverride() { - return StringUtils.isBlank(capabilitiesOverride) - ? Optional.empty() - : Optional.of(POJOHelper.deserialize(capabilitiesOverride, CONNECTOR_CAPABILITY_TYPEREF)); + return Optional.ofNullable(capabilitiesOverride).filter(Predicate.not(Collection::isEmpty)); } @Override public void setCapabilitiesOverride(final Optional> capabilitiesOverride) { - capabilitiesOverride.ifPresentOrElse( - override -> this.capabilitiesOverride = POJOHelper.serialize(override), - () -> this.capabilitiesOverride = null); + this.capabilitiesOverride = capabilitiesOverride.orElse(null); } @Override @@ -367,27 +353,4 @@ public boolean add(final Implementation propagationAction) { public List getPropagationActions() { return sortedPropagationActions; } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getProvisions().clear(); - } - if (provisions != null) { - getProvisions().addAll(POJOHelper.deserialize(provisions, PROVISION_TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - sortedPropagationActions = new SortedSetList<>(propagationActions, Neo4jImplementationRelationship.builder()); - json2list(false); - } - - public void postSave() { - json2list(true); - } - - public void list2json() { - provisions = POJOHelper.serialize(getProvisions()); - } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jNotification.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jNotification.java index f6c78f382b5..143e5e577c6 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jNotification.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jNotification.java @@ -29,12 +29,10 @@ import org.apache.syncope.core.persistence.api.entity.Implementation; import org.apache.syncope.core.persistence.api.entity.MailTemplate; import org.apache.syncope.core.persistence.api.entity.Notification; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.apache.syncope.core.persistence.neo4j.converters.StringListConverter; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; import org.springframework.data.neo4j.core.schema.Relationship; -import tools.jackson.core.type.TypeReference; @Node(Neo4jNotification.NODE) public class Neo4jNotification extends AbstractGeneratedKeyNode implements Notification { @@ -45,23 +43,16 @@ public class Neo4jNotification extends AbstractGeneratedKeyNode implements Notif public static final String NOTIFICATION_ABOUT_REL = "NOTIFICATION_ABOUT"; - protected static final TypeReference> TYPEREF = new TypeReference>() { - }; - - private String events; - - @Transient - private List eventsList = new ArrayList<>(); + @ConvertWith(converter = StringListConverter.class) + private List events = new ArrayList<>(); @Relationship(type = NOTIFICATION_ABOUT_REL, direction = Relationship.Direction.INCOMING) private List abouts = new ArrayList<>(); private String recipientsFIQL; - private String staticRecipients; - - @Transient - private List staticRecipientsList = new ArrayList<>(); + @ConvertWith(converter = StringListConverter.class) + private List staticRecipients = new ArrayList<>(); @NotNull private String recipientAttrName; @@ -122,7 +113,7 @@ public void setRecipientsProvider(final Implementation recipientsProvider) { @Override public List getEvents() { - return eventsList; + return events; } @Override @@ -143,7 +134,7 @@ public List getAbouts() { @Override public List getStaticRecipients() { - return staticRecipientsList; + return staticRecipients; } @Override @@ -207,31 +198,4 @@ public boolean isActive() { public void setActive(final boolean active) { this.active = active; } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getEvents().clear(); - getStaticRecipients().clear(); - } - if (events != null) { - getEvents().addAll(POJOHelper.deserialize(events, TYPEREF)); - } - if (staticRecipients != null) { - getStaticRecipients().addAll(POJOHelper.deserialize(staticRecipients, TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2list(false); - } - - public void postSave() { - json2list(true); - } - - public void list2json() { - events = POJOHelper.serialize(getEvents()); - staticRecipients = POJOHelper.serialize(getStaticRecipients()); - } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jPlainSchema.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jPlainSchema.java index 8c717988eee..5ae5fbf7c16 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jPlainSchema.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jPlainSchema.java @@ -28,12 +28,10 @@ import org.apache.syncope.core.persistence.api.entity.Implementation; import org.apache.syncope.core.persistence.api.entity.PlainSchema; import org.apache.syncope.core.persistence.common.validation.PlainSchemaCheck; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.apache.syncope.core.persistence.neo4j.converters.String2StringMapConverter; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; import org.springframework.data.neo4j.core.schema.Relationship; -import tools.jackson.core.type.TypeReference; @Node(Neo4jPlainSchema.NODE) @PlainSchemaCheck @@ -47,10 +45,6 @@ public class Neo4jPlainSchema extends Neo4jSchema implements PlainSchema { public static final String PLAIN_SCHEMA_ATTR_VALUE_VALIDATOR_REL = "PLAIN_SCHEMA_ATTR_VALUE_VALIDATOR"; - protected static final TypeReference> ENUMVALUES_TYPEREF = - new TypeReference>() { - }; - @NotNull private AttrSchemaType type = AttrSchemaType.String; @@ -65,10 +59,8 @@ public class Neo4jPlainSchema extends Neo4jSchema implements PlainSchema { private String conversionPattern; - private String enumValues; - - @Transient - private Map enumValuesMap = new HashMap<>(); + @ConvertWith(converter = String2StringMapConverter.class) + private Map enumValues = new HashMap<>(); @Relationship(type = PLAIN_SCHEMA_DROPDOWN_VALUE_PROVIDER_REL, direction = Relationship.Direction.OUTGOING, cascadeUpdates = false) @@ -215,35 +207,6 @@ public void setValidator(final Implementation validator) { @Override public Map getEnumValues() { - return enumValuesMap; - } - - @Override - protected void json2map(final boolean clearFirst) { - super.json2map(clearFirst); - - if (clearFirst) { - getEnumValues().clear(); - } - if (enumValues != null) { - getEnumValues().putAll(POJOHelper.deserialize(enumValues, ENUMVALUES_TYPEREF)); - } - } - - @PostLoad - @Override - public void postLoad() { - json2map(false); - } - - @Override - public void postSave() { - json2map(true); - } - - @Override - public void map2json() { - super.map2json(); - enumValues = POJOHelper.serialize(getEnumValues()); + return enumValues; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jRole.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jRole.java index 0f31b5a23a8..b2e1e05db9c 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jRole.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jRole.java @@ -25,12 +25,10 @@ import org.apache.syncope.core.persistence.api.entity.Realm; import org.apache.syncope.core.persistence.api.entity.Role; import org.apache.syncope.core.persistence.common.validation.RoleCheck; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.apache.syncope.core.persistence.neo4j.converters.StringSetConverter; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; import org.springframework.data.neo4j.core.schema.Relationship; -import tools.jackson.core.type.TypeReference; @Node(Neo4jRole.NODE) @RoleCheck @@ -42,13 +40,8 @@ public class Neo4jRole extends AbstractProvidedKeyNode implements Role { public static final String ROLE_REALM_REL = "ROLE_REALM"; - protected static final TypeReference> TYPEREF = new TypeReference>() { - }; - - private String entitlements; - - @Transient - private Set entitlementsSet = new HashSet<>(); + @ConvertWith(converter = StringSetConverter.class) + private Set entitlements = new HashSet<>(); private String anyLayout; @@ -57,7 +50,7 @@ public class Neo4jRole extends AbstractProvidedKeyNode implements Role { @Override public Set getEntitlements() { - return entitlementsSet; + return entitlements; } @Override @@ -80,26 +73,4 @@ public String getAnyLayout() { public void setAnyLayout(final String anyLayout) { this.anyLayout = anyLayout; } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getEntitlements().clear(); - } - if (entitlements != null) { - getEntitlements().addAll(POJOHelper.deserialize(entitlements, TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2list(false); - } - - public void postSave() { - json2list(true); - } - - public void list2json() { - entitlements = POJOHelper.serialize(getEntitlements()); - } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jSchema.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jSchema.java index 400a8d0b3c2..1626e1b4a79 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jSchema.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jSchema.java @@ -24,11 +24,9 @@ import java.util.Optional; import org.apache.syncope.core.persistence.api.entity.Schema; import org.apache.syncope.core.persistence.common.validation.SchemaKeyCheck; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.apache.syncope.core.persistence.neo4j.converters.Locale2StringMapConverter; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; -import tools.jackson.core.type.TypeReference; @Node(Neo4jSchema.NODE) @SchemaKeyCheck @@ -38,44 +36,16 @@ public abstract class Neo4jSchema extends AbstractProvidedKeyNode implements Sch public static final String NODE = "Schema"; - protected static final TypeReference> LABEL_TYPEREF = - new TypeReference>() { - }; - - private String labels; - - @Transient - private Map labelMap = new HashMap<>(); + @ConvertWith(converter = Locale2StringMapConverter.class) + private Map labels = new HashMap<>(); @Override public Optional getLabel(final Locale locale) { - return Optional.ofNullable(labelMap.get(locale)); + return Optional.ofNullable(labels.get(locale)); } @Override public Map getLabels() { - return labelMap; - } - - protected void json2map(final boolean clearFirst) { - if (clearFirst) { - getLabels().clear(); - } - if (labels != null) { - getLabels().putAll(POJOHelper.deserialize(labels, LABEL_TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2map(false); - } - - public void postSave() { - json2map(true); - } - - public void map2json() { - labels = POJOHelper.serialize(getLabels()); + return labels; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/AbstractClientApp.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/AbstractClientApp.java index 58499750f03..094f28943e5 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/AbstractClientApp.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/AbstractClientApp.java @@ -21,7 +21,6 @@ import jakarta.validation.constraints.NotNull; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import org.apache.syncope.common.lib.Attr; import org.apache.syncope.common.lib.clientapps.UsernameAttributeProviderConf; import org.apache.syncope.common.lib.types.LogoutType; @@ -31,23 +30,21 @@ import org.apache.syncope.core.persistence.api.entity.policy.AttrReleasePolicy; import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy; import org.apache.syncope.core.persistence.api.entity.policy.TicketExpirationPolicy; +import org.apache.syncope.core.persistence.neo4j.converters.AttrListConverter; +import org.apache.syncope.core.persistence.neo4j.converters.UsernameAttributeProviderConfConverter; import org.apache.syncope.core.persistence.neo4j.entity.AbstractGeneratedKeyNode; import org.apache.syncope.core.persistence.neo4j.entity.Neo4jRealm; import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jAccessPolicy; import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jAttrReleasePolicy; import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jAuthPolicy; import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jTicketExpirationPolicy; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Relationship; -import tools.jackson.core.type.TypeReference; public abstract class AbstractClientApp extends AbstractGeneratedKeyNode implements ClientApp { private static final long serialVersionUID = 7422422526695279794L; - protected static final TypeReference> ATTR_TYPEREF = new TypeReference>() { - }; - @NotNull private String name; @@ -60,7 +57,8 @@ public abstract class AbstractClientApp extends AbstractGeneratedKeyNode impleme private String logo; - private String usernameAttributeProviderConf; + @ConvertWith(converter = UsernameAttributeProviderConfConverter.class) + private UsernameAttributeProviderConf usernameAttributeProviderConf; private String theme; @@ -83,7 +81,8 @@ public abstract class AbstractClientApp extends AbstractGeneratedKeyNode impleme @Relationship(direction = Relationship.Direction.OUTGOING, cascadeUpdates = false) private Neo4jTicketExpirationPolicy ticketExpirationPolicy; - private String properties; + @ConvertWith(converter = AttrListConverter.class) + private List properties = new ArrayList<>(); private LogoutType logoutType; @@ -169,13 +168,12 @@ public void setPrivacyUrl(final String privacyUrl) { @Override public UsernameAttributeProviderConf getUsernameAttributeProviderConf() { - return Optional.ofNullable(usernameAttributeProviderConf). - map(conf -> POJOHelper.deserialize(conf, UsernameAttributeProviderConf.class)).orElse(null); + return usernameAttributeProviderConf; } @Override public void setUsernameAttributeProviderConf(final UsernameAttributeProviderConf conf) { - this.usernameAttributeProviderConf = conf == null ? null : POJOHelper.serialize(conf); + usernameAttributeProviderConf = conf; } @Override @@ -235,14 +233,12 @@ public void setRealm(final Realm realm) { @Override public List getProperties() { - return properties == null - ? new ArrayList<>(0) - : POJOHelper.deserialize(properties, ATTR_TYPEREF); + return properties; } @Override public void setProperties(final List properties) { - this.properties = POJOHelper.serialize(properties); + this.properties = properties; } @Override diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4JPasswordManagement.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4JPasswordManagement.java index e1bcca8581e..67ee130e059 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4JPasswordManagement.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4JPasswordManagement.java @@ -19,12 +19,12 @@ package org.apache.syncope.core.persistence.neo4j.entity.am; import jakarta.validation.constraints.NotNull; -import org.apache.commons.lang3.StringUtils; import org.apache.syncope.common.lib.password.PasswordManagementConf; import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; import org.apache.syncope.core.persistence.common.validation.PasswordManagementCheck; +import org.apache.syncope.core.persistence.neo4j.converters.PasswordManagementConfConverter; import org.apache.syncope.core.persistence.neo4j.entity.AbstractProvidedKeyNode; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; @Node(Neo4JPasswordManagement.NODE) @@ -40,7 +40,8 @@ public class Neo4JPasswordManagement extends AbstractProvidedKeyNode implements @NotNull private boolean enabled; - private String jsonConf; + @ConvertWith(converter = PasswordManagementConfConverter.class) + private PasswordManagementConf jsonConf; @Override public String getDescription() { @@ -64,16 +65,11 @@ public void setEnabled(final boolean enabled) { @Override public PasswordManagementConf getConf() { - PasswordManagementConf conf = null; - if (!StringUtils.isBlank(jsonConf)) { - conf = POJOHelper.deserialize(jsonConf, PasswordManagementConf.class); - } - - return conf; + return jsonConf; } @Override public void setConf(final PasswordManagementConf conf) { - jsonConf = POJOHelper.serialize(conf); + jsonConf = conf; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAttrRepo.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAttrRepo.java index 2281ed1d6cb..aba8545545f 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAttrRepo.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAttrRepo.java @@ -22,17 +22,15 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import org.apache.commons.lang3.StringUtils; import org.apache.syncope.common.lib.attr.AttrRepoConf; import org.apache.syncope.common.lib.to.Item; import org.apache.syncope.common.lib.types.AttrRepoState; import org.apache.syncope.core.persistence.api.entity.am.AttrRepo; +import org.apache.syncope.core.persistence.neo4j.converters.AttrRepoConfConverter; +import org.apache.syncope.core.persistence.neo4j.converters.ItemListConverter; import org.apache.syncope.core.persistence.neo4j.entity.AbstractProvidedKeyNode; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; -import tools.jackson.core.type.TypeReference; @Node(Neo4jAttrRepo.NODE) public class Neo4jAttrRepo extends AbstractProvidedKeyNode implements AttrRepo { @@ -41,9 +39,6 @@ public class Neo4jAttrRepo extends AbstractProvidedKeyNode implements AttrRepo { public static final String NODE = "AttrRepo"; - protected static final TypeReference> TYPEREF = new TypeReference>() { - }; - private String description; @NotNull @@ -52,12 +47,11 @@ public class Neo4jAttrRepo extends AbstractProvidedKeyNode implements AttrRepo { @NotNull private Integer attrRepoOrder = 0; - private String items; - - @Transient - private final List itemList = new ArrayList<>(); + @ConvertWith(converter = ItemListConverter.class) + private List items = new ArrayList<>(); - private String jsonConf; + @ConvertWith(converter = AttrRepoConfConverter.class) + private AttrRepoConf jsonConf; @Override public String getDescription() { @@ -91,43 +85,16 @@ public void setOrder(final int order) { @Override public List getItems() { - return itemList; + return items; } @Override public AttrRepoConf getConf() { - AttrRepoConf conf = null; - if (!StringUtils.isBlank(jsonConf)) { - conf = POJOHelper.deserialize(jsonConf, AttrRepoConf.class); - } - - return conf; + return jsonConf; } @Override public void setConf(final AttrRepoConf conf) { - jsonConf = POJOHelper.serialize(conf); - } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getItems().clear(); - } - if (items != null) { - getItems().addAll(POJOHelper.deserialize(items, TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2list(false); - } - - public void postSave() { - json2list(true); - } - - public void list2json() { - items = POJOHelper.serialize(getItems()); + jsonConf = conf; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAuthModule.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAuthModule.java index be5d5ace26a..94873e6aeb3 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAuthModule.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAuthModule.java @@ -22,17 +22,15 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import org.apache.commons.lang3.StringUtils; import org.apache.syncope.common.lib.auth.AuthModuleConf; import org.apache.syncope.common.lib.to.Item; import org.apache.syncope.common.lib.types.AuthModuleState; import org.apache.syncope.core.persistence.api.entity.am.AuthModule; +import org.apache.syncope.core.persistence.neo4j.converters.AuthModuleConfConverter; +import org.apache.syncope.core.persistence.neo4j.converters.ItemListConverter; import org.apache.syncope.core.persistence.neo4j.entity.AbstractProvidedKeyNode; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; -import tools.jackson.core.type.TypeReference; @Node(Neo4jAuthModule.NODE) public class Neo4jAuthModule extends AbstractProvidedKeyNode implements AuthModule { @@ -41,9 +39,6 @@ public class Neo4jAuthModule extends AbstractProvidedKeyNode implements AuthModu public static final String NODE = "AuthModule"; - protected static final TypeReference> TYPEREF = new TypeReference>() { - }; - private String description; @NotNull @@ -52,12 +47,11 @@ public class Neo4jAuthModule extends AbstractProvidedKeyNode implements AuthModu @NotNull private Integer authModuleOrder = 0; - private String items; - - @Transient - private final List itemList = new ArrayList<>(); + @ConvertWith(converter = ItemListConverter.class) + private List items = new ArrayList<>(); - private String jsonConf; + @ConvertWith(converter = AuthModuleConfConverter.class) + private AuthModuleConf jsonConf; @Override public String getDescription() { @@ -91,43 +85,16 @@ public void setOrder(final int order) { @Override public List getItems() { - return itemList; + return items; } @Override public AuthModuleConf getConf() { - AuthModuleConf conf = null; - if (!StringUtils.isBlank(jsonConf)) { - conf = POJOHelper.deserialize(jsonConf, AuthModuleConf.class); - } - - return conf; + return jsonConf; } @Override public void setConf(final AuthModuleConf conf) { - jsonConf = POJOHelper.serialize(conf); - } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getItems().clear(); - } - if (items != null) { - getItems().addAll(POJOHelper.deserialize(items, TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2list(false); - } - - public void postSave() { - json2list(true); - } - - public void list2json() { - items = POJOHelper.serialize(getItems()); + jsonConf = conf; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAuthProfile.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAuthProfile.java index 3acc813781b..a63858d58be 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAuthProfile.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jAuthProfile.java @@ -21,7 +21,6 @@ import jakarta.validation.constraints.NotNull; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import org.apache.syncope.common.lib.wa.GoogleMfaAuthAccount; import org.apache.syncope.common.lib.wa.GoogleMfaAuthToken; import org.apache.syncope.common.lib.wa.ImpersonationAccount; @@ -29,12 +28,15 @@ import org.apache.syncope.common.lib.wa.WAConsentDecision; import org.apache.syncope.common.lib.wa.WebAuthnDeviceCredential; import org.apache.syncope.core.persistence.api.entity.am.AuthProfile; +import org.apache.syncope.core.persistence.neo4j.converters.GoogleMfaAuthAccountListConverter; +import org.apache.syncope.core.persistence.neo4j.converters.GoogleMfaAuthTokenListConverter; +import org.apache.syncope.core.persistence.neo4j.converters.ImpersonationAccountListConverter; +import org.apache.syncope.core.persistence.neo4j.converters.MfaTrustedDeviceListConverter; +import org.apache.syncope.core.persistence.neo4j.converters.WAConsentDecisionListConverter; +import org.apache.syncope.core.persistence.neo4j.converters.WebAuthnDeviceCredentialListConverter; import org.apache.syncope.core.persistence.neo4j.entity.AbstractGeneratedKeyNode; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; -import tools.jackson.core.type.TypeReference; @Node(Neo4jAuthProfile.NODE) public class Neo4jAuthProfile extends AbstractGeneratedKeyNode implements AuthProfile { @@ -43,62 +45,26 @@ public class Neo4jAuthProfile extends AbstractGeneratedKeyNode implements AuthPr public static final String NODE = "AuthProfile"; - protected static final TypeReference> GOOGLE_MFA_TOKENS_TYPEREF = - new TypeReference>() { - }; - - protected static final TypeReference> GOOGLE_MFA_ACCOUNTS_TYPEREF = - new TypeReference>() { - }; - - protected static final TypeReference> MFA_TRUSTED_DEVICE_TYPEREF = - new TypeReference>() { - }; - - protected static final TypeReference> IMPERSONATION_TYPEREF = - new TypeReference>() { - }; - - protected static final TypeReference> WEBAUTHN_TYPEREF = - new TypeReference>() { - }; - - protected static final TypeReference> WA_CONSENT_DECISION_TYPEREF = - new TypeReference>() { - }; - @NotNull private String owner; - private String googleMfaAuthAccounts; - - @Transient - private List googleMfaAuthAccountsList = new ArrayList<>(); - - private String googleMfaAuthTokens; - - @Transient - private List googleMfaAuthTokensList = new ArrayList<>(); - - private String mfaTrustedDevices; + @ConvertWith(converter = GoogleMfaAuthAccountListConverter.class) + private List googleMfaAuthAccounts = new ArrayList<>(); - @Transient - private List mfaTrustedDevicesList = new ArrayList<>(); + @ConvertWith(converter = GoogleMfaAuthTokenListConverter.class) + private List googleMfaAuthTokens = new ArrayList<>(); - private String impersonationAccounts; + @ConvertWith(converter = MfaTrustedDeviceListConverter.class) + private List mfaTrustedDevices = new ArrayList<>(); - @Transient - private List impersonationAccountsList = new ArrayList<>(); + @ConvertWith(converter = ImpersonationAccountListConverter.class) + private List impersonationAccounts = new ArrayList<>(); - private String webAuthnDeviceCredentials; + @ConvertWith(converter = WebAuthnDeviceCredentialListConverter.class) + private List webAuthnDeviceCredentials = new ArrayList<>(); - @Transient - private List webAuthnDeviceCredentialsList = new ArrayList<>(); - - private String waConsentDecisions; - - @Transient - private List waConsentDecisionsList = new ArrayList<>(); + @ConvertWith(converter = WAConsentDecisionListConverter.class) + private List waConsentDecisions = new ArrayList<>(); @Override public String getOwner() { @@ -112,102 +78,61 @@ public void setOwner(final String owner) { @Override public boolean add(final GoogleMfaAuthToken googleMfaAuthToken) { - return googleMfaAuthTokensList.add(googleMfaAuthToken); + return googleMfaAuthTokens.add(googleMfaAuthToken); } @Override public List getGoogleMfaAuthTokens() { - return googleMfaAuthTokensList; + return googleMfaAuthTokens; } @Override public boolean add(final GoogleMfaAuthAccount googleMfaAuthAccount) { - return googleMfaAuthAccountsList.add(googleMfaAuthAccount); + return googleMfaAuthAccounts.add(googleMfaAuthAccount); } @Override public List getGoogleMfaAuthAccounts() { - return googleMfaAuthAccountsList; + return googleMfaAuthAccounts; } @Override public boolean add(final MfaTrustedDevice mfaTrustedDevice) { - return mfaTrustedDevicesList.add(mfaTrustedDevice); + return mfaTrustedDevices.add(mfaTrustedDevice); } @Override public List getMfaTrustedDevices() { - return mfaTrustedDevicesList; + return mfaTrustedDevices; } @Override public boolean add(final ImpersonationAccount impersonationAccount) { - return impersonationAccountsList.add(impersonationAccount); + return impersonationAccounts.add(impersonationAccount); } @Override public List getImpersonationAccounts() { - return impersonationAccountsList; + return impersonationAccounts; } @Override public boolean add(final WebAuthnDeviceCredential webAuthnDeviceCredential) { - return webAuthnDeviceCredentialsList.add(webAuthnDeviceCredential); + return webAuthnDeviceCredentials.add(webAuthnDeviceCredential); } @Override public List getWebAuthnDeviceCredentials() { - return webAuthnDeviceCredentialsList; + return webAuthnDeviceCredentials; } @Override public boolean add(final WAConsentDecision consentDecision) { - return waConsentDecisionsList.contains(consentDecision); + return waConsentDecisions.contains(consentDecision); } @Override public List getConsentDecisions() { - return waConsentDecisionsList; - } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getGoogleMfaAuthTokens().clear(); - getGoogleMfaAuthAccounts().clear(); - getMfaTrustedDevices().clear(); - getImpersonationAccounts().clear(); - getWebAuthnDeviceCredentials().clear(); - getConsentDecisions().clear(); - } - Optional.ofNullable(googleMfaAuthTokens).ifPresent(v -> getGoogleMfaAuthTokens(). - addAll(POJOHelper.deserialize(v, GOOGLE_MFA_TOKENS_TYPEREF))); - Optional.ofNullable(googleMfaAuthAccounts).ifPresent(v -> getGoogleMfaAuthAccounts(). - addAll(POJOHelper.deserialize(v, GOOGLE_MFA_ACCOUNTS_TYPEREF))); - Optional.ofNullable(mfaTrustedDevices).ifPresent(v -> getMfaTrustedDevices(). - addAll(POJOHelper.deserialize(v, MFA_TRUSTED_DEVICE_TYPEREF))); - Optional.ofNullable(impersonationAccounts).ifPresent(v -> getImpersonationAccounts(). - addAll(POJOHelper.deserialize(v, IMPERSONATION_TYPEREF))); - Optional.ofNullable(webAuthnDeviceCredentials).ifPresent(v -> getWebAuthnDeviceCredentials(). - addAll(POJOHelper.deserialize(v, WEBAUTHN_TYPEREF))); - Optional.ofNullable(waConsentDecisions).ifPresent(v -> getConsentDecisions(). - addAll(POJOHelper.deserialize(v, WA_CONSENT_DECISION_TYPEREF))); - } - - @PostLoad - public void postLoad() { - json2list(false); - } - - public void postSave() { - json2list(true); - } - - public void list2json() { - googleMfaAuthTokens = POJOHelper.serialize(getGoogleMfaAuthTokens()); - googleMfaAuthAccounts = POJOHelper.serialize(getGoogleMfaAuthAccounts()); - mfaTrustedDevices = POJOHelper.serialize(getMfaTrustedDevices()); - impersonationAccounts = POJOHelper.serialize(getImpersonationAccounts()); - webAuthnDeviceCredentials = POJOHelper.serialize(getWebAuthnDeviceCredentials()); - waConsentDecisions = POJOHelper.serialize(getConsentDecisions()); + return waConsentDecisions; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jOIDCOpEntity.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jOIDCOpEntity.java index fcf53736dd1..724c3292d5d 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jOIDCOpEntity.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jOIDCOpEntity.java @@ -24,12 +24,10 @@ import java.util.Set; import org.apache.commons.lang3.ArrayUtils; import org.apache.syncope.core.persistence.api.entity.am.OIDCOpEntity; +import org.apache.syncope.core.persistence.neo4j.converters.String2SetOfStringMapConverter; import org.apache.syncope.core.persistence.neo4j.entity.AbstractGeneratedKeyNode; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; -import tools.jackson.core.type.TypeReference; @Node(Neo4jOIDCOpEntity.NODE) public class Neo4jOIDCOpEntity extends AbstractGeneratedKeyNode implements OIDCOpEntity { @@ -38,17 +36,11 @@ public class Neo4jOIDCOpEntity extends AbstractGeneratedKeyNode implements OIDCO public static final String NODE = "OIDCOpEntity"; - protected static final TypeReference>> CUSTOMSCOPES_TYPEREF = - new TypeReference>>() { - }; - @NotNull private byte[] jwks; - private String customScopes; - - @Transient - private Map> customScopesMap = new HashMap<>(); + @ConvertWith(converter = String2SetOfStringMapConverter.class) + private Map> customScopes = new HashMap<>(); @Override public byte[] getJWKS() { @@ -62,28 +54,6 @@ public void setJWKS(final byte[] jwks) { @Override public Map> getCustomScopes() { - return customScopesMap; - } - - protected void json2map(final boolean clearFirst) { - if (clearFirst) { - getCustomScopes().clear(); - } - if (customScopes != null) { - getCustomScopes().putAll(POJOHelper.deserialize(customScopes, CUSTOMSCOPES_TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2map(false); - } - - public void postSave() { - json2map(true); - } - - public void map2json() { - customScopes = POJOHelper.serialize(getCustomScopes()); + return customScopes; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jOIDCRPClientApp.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jOIDCRPClientApp.java index 54c6f475474..5516f0a5f51 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jOIDCRPClientApp.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jOIDCRPClientApp.java @@ -30,11 +30,11 @@ import org.apache.syncope.common.lib.types.OIDCTokenEncryptionEncoding; import org.apache.syncope.common.lib.types.OIDCTokenSigningAlg; import org.apache.syncope.core.persistence.api.entity.am.OIDCRPClientApp; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.apache.syncope.core.persistence.neo4j.converters.OIDCGrantTypeSetConverter; +import org.apache.syncope.core.persistence.neo4j.converters.OIDCResponseTypeSetConverter; +import org.apache.syncope.core.persistence.neo4j.converters.StringSetConverter; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; -import tools.jackson.core.type.TypeReference; @Node(Neo4jOIDCRPClientApp.NODE) public class Neo4jOIDCRPClientApp extends AbstractClientApp implements OIDCRPClientApp { @@ -43,21 +43,6 @@ public class Neo4jOIDCRPClientApp extends AbstractClientApp implements OIDCRPCli public static final String NODE = "OIDCRPClientApp"; - protected static final TypeReference> STRING_TYPEREF = new TypeReference>() { - }; - - protected static final TypeReference> GRANT_TYPE_TYPEREF = - new TypeReference>() { - }; - - protected static final TypeReference> RESPONSE_TYPE_TYPEREF = - new TypeReference>() { - }; - - protected static final TypeReference> SCOPE_TYPEREF = - new TypeReference>() { - }; - @NotNull private String clientId; @@ -91,25 +76,17 @@ public class Neo4jOIDCRPClientApp extends AbstractClientApp implements OIDCRPCli private OIDCApplicationType applicationType = OIDCApplicationType.WEB; - private String redirectUris; - - @Transient - private Set redirectUrisSet = new HashSet<>(); + @ConvertWith(converter = StringSetConverter.class) + private Set redirectUris = new HashSet<>(); - private String supportedGrantTypes; + @ConvertWith(converter = OIDCGrantTypeSetConverter.class) + private Set supportedGrantTypes = new HashSet<>(); - @Transient - private Set supportedGrantTypesSet = new HashSet<>(); + @ConvertWith(converter = OIDCResponseTypeSetConverter.class) + private Set supportedResponseTypes = new HashSet<>(); - private String supportedResponseTypes; - - @Transient - private Set supportedResponseTypesSet = new HashSet<>(); - - private String scopes; - - @Transient - private Set scopesSet = new HashSet<>(); + @ConvertWith(converter = StringSetConverter.class) + private Set scopes = new HashSet<>(); private String jwks; @@ -119,7 +96,6 @@ public class Neo4jOIDCRPClientApp extends AbstractClientApp implements OIDCRPCli private String logoutUri; - private String accessTokenMaxTimeToLive; private String accessTokenTimeToKill; @@ -134,7 +110,7 @@ public class Neo4jOIDCRPClientApp extends AbstractClientApp implements OIDCRPCli @Override public Set getRedirectUris() { - return redirectUrisSet; + return redirectUris; } @Override @@ -299,17 +275,17 @@ public void setApplicationType(final OIDCApplicationType applicationType) { @Override public Set getSupportedGrantTypes() { - return supportedGrantTypesSet; + return supportedGrantTypes; } @Override public Set getSupportedResponseTypes() { - return supportedResponseTypesSet; + return supportedResponseTypes; } @Override public Set getScopes() { - return scopesSet; + return scopes; } @Override @@ -413,40 +389,4 @@ public String getAccessTokenMaxTimeToLive() { public void setAccessTokenMaxTimeToLive(final String accessTokenMaxTimeToLive) { this.accessTokenMaxTimeToLive = accessTokenMaxTimeToLive; } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getRedirectUris().clear(); - getSupportedGrantTypes().clear(); - getSupportedResponseTypes().clear(); - } - if (redirectUris != null) { - getRedirectUris().addAll(POJOHelper.deserialize(redirectUris, STRING_TYPEREF)); - } - if (supportedGrantTypes != null) { - getSupportedGrantTypes().addAll(POJOHelper.deserialize(supportedGrantTypes, GRANT_TYPE_TYPEREF)); - } - if (supportedResponseTypes != null) { - getSupportedResponseTypes().addAll(POJOHelper.deserialize(supportedResponseTypes, RESPONSE_TYPE_TYPEREF)); - } - if (scopes != null) { - getScopes().addAll(POJOHelper.deserialize(scopes, SCOPE_TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2list(false); - } - - public void postSave() { - json2list(true); - } - - public void list2json() { - redirectUris = POJOHelper.serialize(getRedirectUris()); - supportedGrantTypes = POJOHelper.serialize(getSupportedGrantTypes()); - supportedResponseTypes = POJOHelper.serialize(getSupportedResponseTypes()); - scopes = POJOHelper.serialize(getScopes()); - } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jSAML2SPClientApp.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jSAML2SPClientApp.java index dbc9fcbe2ea..b97556d1f4e 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jSAML2SPClientApp.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jSAML2SPClientApp.java @@ -30,11 +30,10 @@ import org.apache.syncope.common.lib.types.SigningCredentialType; import org.apache.syncope.common.lib.types.XmlSecAlgorithm; import org.apache.syncope.core.persistence.api.entity.am.SAML2SPClientApp; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.apache.syncope.core.persistence.neo4j.converters.StringSetConverter; +import org.apache.syncope.core.persistence.neo4j.converters.XmlSecAlgorithmListConverter; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; -import tools.jackson.core.type.TypeReference; @Node(Neo4jSAML2SPClientApp.NODE) public class Neo4jSAML2SPClientApp extends AbstractClientApp implements SAML2SPClientApp { @@ -43,13 +42,6 @@ public class Neo4jSAML2SPClientApp extends AbstractClientApp implements SAML2SPC public static final String NODE = "SAML2SPClientApp"; - protected static final TypeReference> STRING_TYPEREF = new TypeReference>() { - }; - - protected static final TypeReference> XMLSECAGO_TYPEREF = - new TypeReference>() { - }; - @NotNull private String entityId; @@ -119,48 +111,34 @@ public class Neo4jSAML2SPClientApp extends AbstractClientApp implements SAML2SPC private String nameIdQualifier; - private String assertionAudiences; - private MetadataCriteriaDirection metadataCriteriaDirection; private SigningCredentialType signingCredentialType; private SAML2BindingType logoutResponseBinding; - @Transient - private Set assertionAudiencesSet = new HashSet<>(); + @ConvertWith(converter = StringSetConverter.class) + private Set assertionAudiences = new HashSet<>(); private String serviceProviderNameIdQualifier; - private String signingSignatureAlgorithms; - - @Transient - private List signingSignatureAlgorithmsList = new ArrayList<>(); - - private String signingSignatureReferenceDigestMethods; - - @Transient - private List signingSignatureReferenceDigestMethodsList = new ArrayList<>(); - - private String encryptionDataAlgorithms; - - @Transient - private List encryptionDataAlgorithmsList = new ArrayList<>(); - - private String encryptionKeyAlgorithms; + @ConvertWith(converter = XmlSecAlgorithmListConverter.class) + private List signingSignatureAlgorithms = new ArrayList<>(); - @Transient - private List encryptionKeyAlgorithmsList = new ArrayList<>(); + @ConvertWith(converter = XmlSecAlgorithmListConverter.class) + private List signingSignatureReferenceDigestMethods = new ArrayList<>(); - private String signingSignatureBlackListedAlgorithms; + @ConvertWith(converter = XmlSecAlgorithmListConverter.class) + private List encryptionDataAlgorithms = new ArrayList<>(); - @Transient - private List signingSignatureBlackListedAlgorithmsList = new ArrayList<>(); + @ConvertWith(converter = XmlSecAlgorithmListConverter.class) + private List encryptionKeyAlgorithms = new ArrayList<>(); - private String encryptionBlackListedAlgorithms; + @ConvertWith(converter = XmlSecAlgorithmListConverter.class) + private List signingSignatureBlackListedAlgorithms = new ArrayList<>(); - @Transient - private List encryptionBlackListedAlgorithmsList = new ArrayList<>(); + @ConvertWith(converter = XmlSecAlgorithmListConverter.class) + private List encryptionBlackListedAlgorithms = new ArrayList<>(); @Override public String getEntityId() { @@ -539,7 +517,7 @@ public void setNameIdQualifier(final String nameIdQualifier) { @Override public Set getAssertionAudiences() { - return assertionAudiencesSet; + return assertionAudiences; } @Override @@ -554,90 +532,31 @@ public void setServiceProviderNameIdQualifier(final String serviceProviderNameId @Override public List getSigningSignatureAlgorithms() { - return signingSignatureAlgorithmsList; + return signingSignatureAlgorithms; } @Override public List getSigningSignatureReferenceDigestMethods() { - return signingSignatureReferenceDigestMethodsList; + return signingSignatureReferenceDigestMethods; } @Override public List getEncryptionDataAlgorithms() { - return encryptionDataAlgorithmsList; + return encryptionDataAlgorithms; } @Override public List getEncryptionKeyAlgorithms() { - return encryptionKeyAlgorithmsList; + return encryptionKeyAlgorithms; } @Override public List getSigningSignatureBlackListedAlgorithms() { - return signingSignatureBlackListedAlgorithmsList; + return signingSignatureBlackListedAlgorithms; } @Override public List getEncryptionBlackListedAlgorithms() { - return encryptionBlackListedAlgorithmsList; - } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getAssertionAudiences().clear(); - getSigningSignatureAlgorithms().clear(); - getSigningSignatureReferenceDigestMethods().clear(); - getEncryptionDataAlgorithms().clear(); - getEncryptionKeyAlgorithms().clear(); - getSigningSignatureBlackListedAlgorithms().clear(); - getEncryptionBlackListedAlgorithms().clear(); - } - if (assertionAudiences != null) { - getAssertionAudiences().addAll( - POJOHelper.deserialize(assertionAudiences, STRING_TYPEREF)); - } - if (signingSignatureAlgorithms != null) { - getSigningSignatureAlgorithms().addAll( - POJOHelper.deserialize(signingSignatureAlgorithms, XMLSECAGO_TYPEREF)); - } - if (signingSignatureReferenceDigestMethods != null) { - getSigningSignatureReferenceDigestMethods().addAll( - POJOHelper.deserialize(signingSignatureReferenceDigestMethods, XMLSECAGO_TYPEREF)); - } - if (encryptionDataAlgorithms != null) { - getEncryptionDataAlgorithms().addAll( - POJOHelper.deserialize(encryptionDataAlgorithms, XMLSECAGO_TYPEREF)); - } - if (encryptionKeyAlgorithms != null) { - getEncryptionKeyAlgorithms().addAll( - POJOHelper.deserialize(encryptionKeyAlgorithms, XMLSECAGO_TYPEREF)); - } - if (signingSignatureBlackListedAlgorithms != null) { - getSigningSignatureBlackListedAlgorithms().addAll( - POJOHelper.deserialize(signingSignatureBlackListedAlgorithms, XMLSECAGO_TYPEREF)); - } - if (encryptionBlackListedAlgorithms != null) { - getEncryptionBlackListedAlgorithms().addAll( - POJOHelper.deserialize(encryptionBlackListedAlgorithms, XMLSECAGO_TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2list(false); - } - - public void postSave() { - json2list(true); - } - - public void list2json() { - assertionAudiences = POJOHelper.serialize(getAssertionAudiences()); - signingSignatureAlgorithms = POJOHelper.serialize(getSigningSignatureAlgorithms()); - signingSignatureReferenceDigestMethods = POJOHelper.serialize(getSigningSignatureReferenceDigestMethods()); - encryptionDataAlgorithms = POJOHelper.serialize(getEncryptionDataAlgorithms()); - encryptionKeyAlgorithms = POJOHelper.serialize(getEncryptionKeyAlgorithms()); - signingSignatureBlackListedAlgorithms = POJOHelper.serialize(getSigningSignatureBlackListedAlgorithms()); - encryptionBlackListedAlgorithms = POJOHelper.serialize(getEncryptionBlackListedAlgorithms()); + return encryptionBlackListedAlgorithms; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jWAConfigEntry.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jWAConfigEntry.java index de072bf1aba..a196688bb4e 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jWAConfigEntry.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jWAConfigEntry.java @@ -18,13 +18,13 @@ */ package org.apache.syncope.core.persistence.neo4j.entity.am; +import java.util.ArrayList; import java.util.List; -import java.util.Optional; import org.apache.syncope.core.persistence.api.entity.am.WAConfigEntry; +import org.apache.syncope.core.persistence.neo4j.converters.StringListConverter; import org.apache.syncope.core.persistence.neo4j.entity.AbstractProvidedKeyNode; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import tools.jackson.core.type.TypeReference; @Node(Neo4jWAConfigEntry.NODE) public class Neo4jWAConfigEntry extends AbstractProvidedKeyNode implements WAConfigEntry { @@ -33,18 +33,16 @@ public class Neo4jWAConfigEntry extends AbstractProvidedKeyNode implements WACon public static final String NODE = "WAConfigEntry"; - protected static TypeReference> TYPEREF = new TypeReference>() { - }; - - private String waConfigValues; + @ConvertWith(converter = StringListConverter.class) + private List waConfigValues = new ArrayList<>(); @Override public List getValues() { - return Optional.ofNullable(waConfigValues).map(v -> POJOHelper.deserialize(v, TYPEREF)).orElseGet(List::of); + return waConfigValues; } @Override public void setValues(final List values) { - this.waConfigValues = POJOHelper.serialize(values); + waConfigValues = values; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAccessPolicy.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAccessPolicy.java index f54d47b65a0..7e39b971842 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAccessPolicy.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAccessPolicy.java @@ -18,10 +18,10 @@ */ package org.apache.syncope.core.persistence.neo4j.entity.policy; -import java.util.Optional; import org.apache.syncope.common.lib.policy.AccessPolicyConf; import org.apache.syncope.core.persistence.api.entity.policy.AccessPolicy; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.apache.syncope.core.persistence.neo4j.converters.AccessPolicyConfConverter; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; @Node(Neo4jAccessPolicy.NODE) @@ -31,15 +31,16 @@ public class Neo4jAccessPolicy extends Neo4jPolicy implements AccessPolicy { public static final String NODE = "AccessPolicy"; - private String jsonConf; + @ConvertWith(converter = AccessPolicyConfConverter.class) + private AccessPolicyConf jsonConf; @Override public AccessPolicyConf getConf() { - return Optional.ofNullable(jsonConf).map(c -> POJOHelper.deserialize(c, AccessPolicyConf.class)).orElse(null); + return jsonConf; } @Override public void setConf(final AccessPolicyConf conf) { - jsonConf = Optional.ofNullable(conf).map(POJOHelper::serialize).orElse(null); + jsonConf = conf; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAttrReleasePolicy.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAttrReleasePolicy.java index f44580f83a4..c1ad9d9aa7f 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAttrReleasePolicy.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAttrReleasePolicy.java @@ -21,7 +21,8 @@ import java.util.Optional; import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf; import org.apache.syncope.core.persistence.api.entity.policy.AttrReleasePolicy; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.apache.syncope.core.persistence.neo4j.converters.AttrReleasePolicyConfConverter; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; @Node(Neo4jAttrReleasePolicy.NODE) @@ -35,7 +36,8 @@ public class Neo4jAttrReleasePolicy extends Neo4jPolicy implements AttrReleasePo private Boolean status; - private String jsonConf; + @ConvertWith(converter = AttrReleasePolicyConfConverter.class) + private AttrReleasePolicyConf jsonConf; @Override public int getOrder() { @@ -59,12 +61,11 @@ public void setStatus(final Boolean status) { @Override public AttrReleasePolicyConf getConf() { - return Optional.ofNullable(jsonConf). - map(c -> POJOHelper.deserialize(c, AttrReleasePolicyConf.class)).orElse(null); + return jsonConf; } @Override public void setConf(final AttrReleasePolicyConf conf) { - jsonConf = Optional.ofNullable(conf).map(POJOHelper::serialize).orElse(null); + jsonConf = conf; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAuthPolicy.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAuthPolicy.java index 7256a9d95ee..889f8d56f51 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAuthPolicy.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jAuthPolicy.java @@ -18,10 +18,10 @@ */ package org.apache.syncope.core.persistence.neo4j.entity.policy; -import java.util.Optional; import org.apache.syncope.common.lib.policy.AuthPolicyConf; import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.apache.syncope.core.persistence.neo4j.converters.AuthPolicyConfConverter; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; @Node(Neo4jAuthPolicy.NODE) @@ -31,17 +31,16 @@ public class Neo4jAuthPolicy extends Neo4jPolicy implements AuthPolicy { public static final String NODE = "AuthPolicy"; - private String jsonConf; + @ConvertWith(converter = AuthPolicyConfConverter.class) + private AuthPolicyConf jsonConf; @Override public AuthPolicyConf getConf() { - return jsonConf == null - ? null - : POJOHelper.deserialize(jsonConf, AuthPolicyConf.class); + return jsonConf; } @Override public void setConf(final AuthPolicyConf conf) { - jsonConf = Optional.ofNullable(conf).map(POJOHelper::serialize).orElse(null); + jsonConf = conf; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jTicketExpirationPolicy.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jTicketExpirationPolicy.java index a06df9cf0d1..da4ad2387b7 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jTicketExpirationPolicy.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/policy/Neo4jTicketExpirationPolicy.java @@ -18,10 +18,10 @@ */ package org.apache.syncope.core.persistence.neo4j.entity.policy; -import java.util.Optional; import org.apache.syncope.common.lib.policy.TicketExpirationPolicyConf; import org.apache.syncope.core.persistence.api.entity.policy.TicketExpirationPolicy; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.apache.syncope.core.persistence.neo4j.converters.TicketExpirationPolicyConfConverter; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; @Node(Neo4jTicketExpirationPolicy.NODE) @@ -31,17 +31,16 @@ public class Neo4jTicketExpirationPolicy extends Neo4jPolicy implements TicketEx public static final String NODE = "TicketExpirationPolicy"; - private String jsonConf; + @ConvertWith(converter = TicketExpirationPolicyConfConverter.class) + private TicketExpirationPolicyConf jsonConf; @Override public TicketExpirationPolicyConf getConf() { - return Optional.ofNullable(jsonConf). - map(c -> POJOHelper.deserialize(c, TicketExpirationPolicyConf.class)). - orElse(null); + return jsonConf; } @Override public void setConf(final TicketExpirationPolicyConf conf) { - jsonConf = Optional.ofNullable(conf).map(POJOHelper::serialize).orElse(null); + jsonConf = conf; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jFormPropertyDef.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jFormPropertyDef.java index 2082dfc665c..85a2494b1ad 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jFormPropertyDef.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jFormPropertyDef.java @@ -28,13 +28,12 @@ import org.apache.syncope.core.persistence.api.entity.task.FormPropertyDef; import org.apache.syncope.core.persistence.api.entity.task.MacroTask; import org.apache.syncope.core.persistence.common.validation.FormPropertyDefCheck; +import org.apache.syncope.core.persistence.neo4j.converters.Locale2StringMapConverter; +import org.apache.syncope.core.persistence.neo4j.converters.String2StringMapConverter; import org.apache.syncope.core.persistence.neo4j.entity.AbstractGeneratedKeyNode; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; import org.springframework.data.neo4j.core.schema.Relationship; -import tools.jackson.core.type.TypeReference; @Node(Neo4jFormPropertyDef.NODE) @FormPropertyDefCheck @@ -44,14 +43,6 @@ public class Neo4jFormPropertyDef extends AbstractGeneratedKeyNode implements Fo public static final String NODE = "FormPropertyDef"; - protected static final TypeReference> ENUMVALUES_TYPEREF = - new TypeReference>() { - }; - - protected static final TypeReference> LABEL_TYPEREF = - new TypeReference>() { - }; - @NotNull @Relationship(type = Neo4jMacroTask.MACRO_TASK_FORM_PROPERTY_DEF_REL, direction = Relationship.Direction.OUTGOING, cascadeUpdates = false) @@ -60,10 +51,8 @@ public class Neo4jFormPropertyDef extends AbstractGeneratedKeyNode implements Fo @NotNull private String name; - private String labels; - - @Transient - private Map labelMap = new HashMap<>(); + @ConvertWith(converter = Locale2StringMapConverter.class) + private Map labels = new HashMap<>(); @NotNull private FormPropertyType type; @@ -81,7 +70,8 @@ public class Neo4jFormPropertyDef extends AbstractGeneratedKeyNode implements Fo private String datePattern; - private String enumValues; + @ConvertWith(converter = String2StringMapConverter.class) + private Map enumValues = new HashMap<>(); @NotNull private Boolean dropdownSingleSelection = Boolean.TRUE; @@ -114,12 +104,12 @@ public void setName(final String name) { @Override public Optional getLabel(final Locale locale) { - return Optional.ofNullable(labelMap.get(locale)); + return Optional.ofNullable(labels.get(locale)); } @Override public Map getLabels() { - return labelMap; + return labels; } @Override @@ -184,13 +174,12 @@ public void setDatePattern(final String datePattern) { @Override public Map getEnumValues() { - return Optional.ofNullable(enumValues).map(v -> POJOHelper.deserialize(v, ENUMVALUES_TYPEREF)). - orElseGet(Map::of); + return enumValues; } @Override public void setEnumValues(final Map enumValues) { - this.enumValues = Optional.ofNullable(enumValues).map(POJOHelper::serialize).orElse(null); + this.enumValues = enumValues; } @Override @@ -222,26 +211,4 @@ public String getMimeType() { public void setMimeType(final String mimeType) { this.mimeType = mimeType; } - - protected void json2map(final boolean clearFirst) { - if (clearFirst) { - getLabels().clear(); - } - if (labels != null) { - getLabels().putAll(POJOHelper.deserialize(labels, LABEL_TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2map(false); - } - - public void postSave() { - json2map(true); - } - - public void map2json() { - labels = POJOHelper.serialize(getLabels()); - } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jLiveSyncTask.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jLiveSyncTask.java index ede651fea69..097ce4f2860 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jLiveSyncTask.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jLiveSyncTask.java @@ -74,7 +74,7 @@ public class Neo4jLiveSyncTask extends Neo4jInboundTask implements private List templates = new ArrayList<>(); @Relationship(type = LIVE_SYNC_TASK_EXEC_REL, direction = Relationship.Direction.INCOMING) - private List executions = new ArrayList<>(); + private List liveSyncTaskExecs = new ArrayList<>(); @Override public int getDelaySecondsAcrossInvocations() { @@ -130,7 +130,7 @@ public List getTemplates() { @Override protected boolean doAdd(final TaskExec exec) { - return executions.add((Neo4jLiveSyncTaskExec) exec); + return liveSyncTaskExecs.add((Neo4jLiveSyncTaskExec) exec); } @Override @@ -140,7 +140,7 @@ protected Class> executionClass() { @Override protected List> executions() { - return executions; + return liveSyncTaskExecs; } @PostLoad diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jMacroTask.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jMacroTask.java index ecd4799dad9..7c1174705d1 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jMacroTask.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jMacroTask.java @@ -86,7 +86,7 @@ public class Neo4jMacroTask extends Neo4jSchedTask implements MacroTask { private Neo4jImplementation macroActions; @Relationship(type = MACRO_TASK_EXEC_REL, direction = Relationship.Direction.INCOMING) - private List executions = new ArrayList<>(); + private List macroTaskExecs = new ArrayList<>(); @Override public Realm getRealm() { @@ -121,7 +121,7 @@ public void setSaveExecs(final boolean saveExecs) { @Override protected boolean doAdd(final TaskExec exec) { - return executions.add((Neo4jMacroTaskExec) exec); + return macroTaskExecs.add((Neo4jMacroTaskExec) exec); } @Override @@ -131,7 +131,7 @@ protected Class> executionClass() { @Override protected List> executions() { - return executions; + return macroTaskExecs; } @Override diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jNotificationTask.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jNotificationTask.java index aff757c7834..61be5369ad6 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jNotificationTask.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jNotificationTask.java @@ -28,13 +28,11 @@ import org.apache.syncope.core.persistence.api.entity.Notification; import org.apache.syncope.core.persistence.api.entity.task.NotificationTask; import org.apache.syncope.core.persistence.api.entity.task.TaskExec; +import org.apache.syncope.core.persistence.neo4j.converters.StringSetConverter; import org.apache.syncope.core.persistence.neo4j.entity.Neo4jNotification; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; import org.springframework.data.neo4j.core.schema.Relationship; -import tools.jackson.core.type.TypeReference; @Node(Neo4jNotificationTask.NODE) public class Neo4jNotificationTask extends AbstractTask implements NotificationTask { @@ -45,9 +43,6 @@ public class Neo4jNotificationTask extends AbstractTask implem public static final String NOTIFICATION_TASK_EXEC_REL = "NOTIFICATION_TASK_EXEC"; - protected static final TypeReference> TYPEREF = new TypeReference>() { - }; - @NotNull @Relationship(direction = Relationship.Direction.OUTGOING, cascadeUpdates = false) private Neo4jNotification notification; @@ -56,13 +51,11 @@ public class Neo4jNotificationTask extends AbstractTask implem private String entityKey; - private String recipients; - - @Transient - private Set recipientsSet = new HashSet<>(); + @ConvertWith(converter = StringSetConverter.class) + private Set recipients = new HashSet<>(); @Relationship(type = NOTIFICATION_TASK_EXEC_REL, direction = Relationship.Direction.INCOMING) - private List executions = new ArrayList<>(); + private List notificationTaskExecs = new ArrayList<>(); @NotNull private String sender; @@ -115,7 +108,7 @@ public void setEntityKey(final String entityKey) { @Override public Set getRecipients() { - return recipientsSet; + return recipients; } @Override @@ -180,7 +173,7 @@ public void setTraceLevel(final TraceLevel traceLevel) { @Override protected boolean doAdd(final TaskExec exec) { - return executions.add((Neo4jNotificationTaskExec) exec); + return notificationTaskExecs.add((Neo4jNotificationTaskExec) exec); } @Override @@ -190,28 +183,6 @@ protected Class> executionClass() { @Override protected List> executions() { - return executions; - } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getRecipients().clear(); - } - if (recipients != null) { - getRecipients().addAll(POJOHelper.deserialize(recipients, TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2list(false); - } - - public void postSave() { - json2list(true); - } - - public void list2json() { - recipients = POJOHelper.serialize(getRecipients()); + return notificationTaskExecs; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPropagationTask.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPropagationTask.java index 134dc1cb616..870773a1bae 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPropagationTask.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPropagationTask.java @@ -83,7 +83,7 @@ public class Neo4jPropagationTask extends AbstractTask implemen private Neo4jExternalResource resource; @Relationship(type = PROPAGATION_TASK_EXEC_REL, direction = Relationship.Direction.INCOMING) - private List executions = new ArrayList<>(); + private List propagationTaskExecs = new ArrayList<>(); @Override public String getConnObjectKey() { @@ -188,7 +188,7 @@ public void setResource(final ExternalResource resource) { @Override protected boolean doAdd(final TaskExec exec) { - return executions.add((Neo4jPropagationTaskExec) exec); + return propagationTaskExecs.add((Neo4jPropagationTaskExec) exec); } @Override @@ -198,6 +198,6 @@ protected Class> executionClass() { @Override protected List> executions() { - return executions; + return propagationTaskExecs; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPullTask.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPullTask.java index 4cf1b17b718..7f716bba619 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPullTask.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPullTask.java @@ -73,7 +73,7 @@ public class Neo4jPullTask extends Neo4jInboundTask implements PullTas private List templates = new ArrayList<>(); @Relationship(type = PULL_TASK_EXEC_REL, direction = Relationship.Direction.INCOMING) - private List executions = new ArrayList<>(); + private List pullTaskExecs = new ArrayList<>(); @Override public PullMode getPullMode() { @@ -129,7 +129,7 @@ public List getTemplates() { @Override protected boolean doAdd(final TaskExec exec) { - return executions.add((Neo4jPullTaskExec) exec); + return pullTaskExecs.add((Neo4jPullTaskExec) exec); } @Override @@ -139,7 +139,7 @@ protected Class> executionClass() { @Override protected List> executions() { - return executions; + return pullTaskExecs; } @PostLoad diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPushTask.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPushTask.java index b789cae765a..0122d239597 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPushTask.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPushTask.java @@ -32,16 +32,15 @@ import org.apache.syncope.core.persistence.api.entity.task.PushTask; import org.apache.syncope.core.persistence.api.entity.task.SchedTask; import org.apache.syncope.core.persistence.api.entity.task.TaskExec; +import org.apache.syncope.core.persistence.neo4j.converters.String2StringMapConverter; import org.apache.syncope.core.persistence.neo4j.entity.Neo4jImplementation; import org.apache.syncope.core.persistence.neo4j.entity.Neo4jImplementationRelationship; import org.apache.syncope.core.persistence.neo4j.entity.Neo4jRealm; import org.apache.syncope.core.persistence.neo4j.entity.SortedSetList; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; import org.springframework.data.annotation.Transient; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; import org.springframework.data.neo4j.core.schema.Relationship; -import tools.jackson.core.type.TypeReference; @Node(Neo4jPushTask.NODE) public class Neo4jPushTask extends Neo4jProvisioningTask implements PushTask { @@ -54,18 +53,12 @@ public class Neo4jPushTask extends Neo4jProvisioningTask implements Pu public static final String PUSH_TASK_EXEC_REL = "PUSH_TASK_EXEC"; - protected static final TypeReference> FILTER_TYPEREF = - new TypeReference>() { - }; - @NotNull @Relationship(direction = Relationship.Direction.OUTGOING, cascadeUpdates = false) private Neo4jRealm sourceRealm; - private String filters; - - @Transient - private Map filterMap = new HashMap<>(); + @ConvertWith(converter = String2StringMapConverter.class) + private Map filters = new HashMap<>(); @Relationship(type = PUSH_TASK_PUSH_ACTIONS_REL, direction = Relationship.Direction.OUTGOING, cascadeUpdates = false) @@ -76,7 +69,7 @@ public class Neo4jPushTask extends Neo4jProvisioningTask implements Pu actions, Neo4jImplementationRelationship.builder()); @Relationship(type = PUSH_TASK_EXEC_REL, direction = Relationship.Direction.INCOMING) - private List executions = new ArrayList<>(); + private List pushTaskExecs = new ArrayList<>(); @Override public Neo4jRealm getSourceRealm() { @@ -103,17 +96,17 @@ public List getActions() { @Override public Optional getFilter(final String anyType) { - return Optional.ofNullable(filterMap.get(anyType)); + return Optional.ofNullable(filters.get(anyType)); } @Override public Map getFilters() { - return filterMap; + return filters; } @Override protected boolean doAdd(final TaskExec exec) { - return executions.add((Neo4jPushTaskExec) exec); + return pushTaskExecs.add((Neo4jPushTaskExec) exec); } @Override @@ -123,29 +116,6 @@ protected Class> executionClass() { @Override protected List> executions() { - return executions; - } - - protected void json2map(final boolean clearFirst) { - if (clearFirst) { - getFilters().clear(); - } - if (filters != null) { - getFilters().putAll(POJOHelper.deserialize(filters, FILTER_TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - sortedActions = new SortedSetList<>(actions, Neo4jImplementationRelationship.builder()); - json2map(false); - } - - public void postSave() { - json2map(true); - } - - public void map2json() { - filters = POJOHelper.serialize(getFilters()); + return pushTaskExecs; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jSchedTask.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jSchedTask.java index 87bd2e9ced9..2b0366965d0 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jSchedTask.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jSchedTask.java @@ -58,7 +58,7 @@ public class Neo4jSchedTask extends AbstractTask implements SchedTask private Boolean active = true; @Relationship(type = SCHED_TASK_EXEC_REL, direction = Relationship.Direction.INCOMING) - private List executions = new ArrayList<>(); + private List schedTaskExecs = new ArrayList<>(); @Override public Implementation getJobDelegate() { @@ -114,7 +114,7 @@ public void setActive(final boolean active) { @Override protected boolean doAdd(final TaskExec exec) { - return executions.add((Neo4jSchedTaskExec) exec); + return schedTaskExecs.add((Neo4jSchedTaskExec) exec); } @Override @@ -124,6 +124,6 @@ protected Class> executionClass() { @Override protected List> executions() { - return executions; + return schedTaskExecs; } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/user/Neo4jUser.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/user/Neo4jUser.java index 9a57ed0b908..e8a006974b9 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/user/Neo4jUser.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/user/Neo4jUser.java @@ -46,6 +46,7 @@ import org.apache.syncope.core.persistence.api.entity.user.URelationship; import org.apache.syncope.core.persistence.api.entity.user.User; import org.apache.syncope.core.persistence.common.validation.AttributableCheck; +import org.apache.syncope.core.persistence.neo4j.converters.StringListConverter; import org.apache.syncope.core.persistence.neo4j.entity.AbstractGroupableRelatable; import org.apache.syncope.core.persistence.neo4j.entity.AbstractRelationship; import org.apache.syncope.core.persistence.neo4j.entity.Neo4jAnyTypeClass; @@ -54,10 +55,10 @@ import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; import org.apache.syncope.core.spring.security.AuthContextUtils; import org.apache.syncope.core.spring.security.SecureRandomUtils; +import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.CompositeProperty; import org.springframework.data.neo4j.core.schema.Node; import org.springframework.data.neo4j.core.schema.Relationship; -import tools.jackson.core.type.TypeReference; @Node(Neo4jUser.NODE) @AttributableCheck @@ -79,9 +80,6 @@ public class Neo4jUser public static final String USER_SECURITYQUESTION_REL = "USER_SECURITY_QUESTION"; - protected static final TypeReference> TYPEREF = new TypeReference>() { - }; - protected String password; @CompositeProperty(converterRef = "plainAttrsConverter") @@ -93,7 +91,8 @@ public class Neo4jUser protected CipherAlgorithm cipherAlgorithm; - protected String passwordHistory; + @ConvertWith(converter = StringListConverter.class) + protected List passwordHistory = new ArrayList<>(); /** * Subsequent failed logins. @@ -282,22 +281,18 @@ public boolean hasTokenExpired() { @Override public void addToPasswordHistory(final String password) { - List ph = getPasswordHistory(); - ph.add(password); - passwordHistory = POJOHelper.serialize(ph); + passwordHistory.add(password); } @Override public void removeOldestEntriesFromPasswordHistory(final int n) { - List ph = getPasswordHistory(); - passwordHistory = POJOHelper.serialize(ph.subList(Math.min(n, ph.size()), ph.size())); + passwordHistory = new ArrayList<>( + passwordHistory.subList(Math.min(n, passwordHistory.size()), passwordHistory.size())); } @Override public List getPasswordHistory() { - return passwordHistory == null - ? new ArrayList<>(0) - : POJOHelper.deserialize(passwordHistory, TYPEREF); + return passwordHistory; } @Override diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityProperties.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityProperties.java index f444717a3e8..2470d840517 100644 --- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityProperties.java +++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityProperties.java @@ -174,8 +174,6 @@ public void setUseLenientSaltSizeCheck(final boolean useLenientSaltSizeCheck) { private final ThrottleProperties authenticationThrottle = new ThrottleProperties(); - private boolean passwordResetHideDetails = true; - private final ThrottleProperties passwordResetThrottle = new ThrottleProperties(); private final AuthenticationErrorProperties authenticationError = new AuthenticationErrorProperties(); @@ -274,14 +272,6 @@ public SecurityProperties.ThrottleProperties getAuthenticationThrottle() { return authenticationThrottle; } - public boolean isPasswordResetHideDetails() { - return passwordResetHideDetails; - } - - public void setPasswordResetHideDetails(final boolean passwordResetHideDetails) { - this.passwordResetHideDetails = passwordResetHideDetails; - } - public ThrottleProperties getPasswordResetThrottle() { return passwordResetThrottle; } diff --git a/core/starter/src/main/resources/core.properties b/core/starter/src/main/resources/core.properties index a55ea47adcd..16210f3ba48 100644 --- a/core/starter/src/main/resources/core.properties +++ b/core/starter/src/main/resources/core.properties @@ -107,8 +107,6 @@ security.authenticationThrottle.maxAttempts=5 security.authenticationThrottle.windowSeconds=60 security.authenticationThrottle.lockSeconds=60 -security.passwordResetHideDetails=true - security.passwordResetThrottle.enabled=true security.passwordResetThrottle.maxAttempts=5 security.passwordResetThrottle.windowSeconds=300 diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml index 011b9dc2207..807c2438da6 100644 --- a/fit/core-reference/pom.xml +++ b/fit/core-reference/pom.xml @@ -1115,12 +1115,6 @@ under the License. syncope-core-persistence-neo4j ${project.version} - - - org.springframework.data - spring-data-commons - 4.0.5 - From cc7fd629f0121e7469873fe9168aa4493f809424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francesco=20Chicchiricc=C3=B2?= Date: Tue, 23 Jun 2026 16:12:17 +0200 Subject: [PATCH 2/3] TMP adding Neo4jMappingContext waiting for https://github.com/spring-projects/spring-data-neo4j/issues/3109 --- core/persistence-neo4j/pom.xml | 4 + .../core/mapping/Neo4jMappingContext.java | 713 ++++++++++++++++++ 2 files changed, 717 insertions(+) create mode 100644 core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/core/mapping/Neo4jMappingContext.java diff --git a/core/persistence-neo4j/pom.xml b/core/persistence-neo4j/pom.xml index 9860f16f7f3..fc1c4776c7e 100644 --- a/core/persistence-neo4j/pom.xml +++ b/core/persistence-neo4j/pom.xml @@ -101,6 +101,10 @@ under the License. org.apache.maven.plugins maven-checkstyle-plugin + + + **/Neo4jMappingContext** + diff --git a/core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/core/mapping/Neo4jMappingContext.java b/core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/core/mapping/Neo4jMappingContext.java new file mode 100644 index 00000000000..3997bb8fcde --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/core/mapping/Neo4jMappingContext.java @@ -0,0 +1,713 @@ +/* + * Copyright 2011-present the original author or authors. + * + * 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 + * + * https://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.springframework.data.neo4j.core.mapping; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; +import org.neo4j.cypherdsl.core.Statement; +import org.neo4j.driver.types.TypeSystem; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.core.GenericTypeResolver; +import org.springframework.core.KotlinDetector; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.data.core.TypeInformation; +import org.springframework.data.mapping.MappingException; +import org.springframework.data.mapping.PersistentEntity; +import org.springframework.data.mapping.callback.EntityCallbacks; +import org.springframework.data.mapping.context.AbstractMappingContext; +import org.springframework.data.mapping.model.EntityInstantiator; +import org.springframework.data.mapping.model.EntityInstantiators; +import org.springframework.data.mapping.model.Property; +import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.neo4j.core.convert.ConvertWith; +import org.springframework.data.neo4j.core.convert.Neo4jConversionService; +import org.springframework.data.neo4j.core.convert.Neo4jConversions; +import org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverter; +import org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverterFactory; +import org.springframework.data.neo4j.core.mapping.callback.EventSupport; +import org.springframework.data.neo4j.core.schema.IdGenerator; +import org.springframework.data.neo4j.core.schema.Node; +import org.springframework.data.neo4j.core.schema.PostLoad; +import org.springframework.data.util.Lazy; +import org.springframework.util.ReflectionUtils; + +/** + * An implementation of both a {@link Schema} as well as a Neo4j version of Spring Data's + * {@link org.springframework.data.mapping.context.MappingContext}. It is recommended to + * provide the initial set of classes through {@link #setInitialEntitySet(Set)}. + * + * @author Michael J. Simons + * @author Gerrit Meier + * @since 6.0 + */ +@API(status = API.Status.STABLE, since = "6.0") +public final class Neo4jMappingContext extends AbstractMappingContext, Neo4jPersistentProperty> + implements Schema { + + /** + * The shared entity instantiators of this context. Those should not be recreated for + * each entity or even not for each query, as otherwise the cache of Spring's + * org.springframework.data.convert.ClassGeneratingEntityInstantiator won't apply + */ + private static final EntityInstantiators INSTANTIATORS = new EntityInstantiators(); + + private static final Set> VOID_TYPES = new HashSet<>(Arrays.asList(Void.class, void.class)); + + /** + * A map of fallback id generators, that have not been added to the application + * context. + */ + private final Map>, IdGenerator> idGenerators = new ConcurrentHashMap<>(); + + private final Map, Neo4jPersistentPropertyConverterFactory> converterFactories = new ConcurrentHashMap<>(); + + /** + * The {@link NodeDescriptionStore} is basically a {@link Map} and it is used to break + * the dependency cycle between this class and the + * {@link DefaultNeo4jEntityConverter}. + */ + private final NodeDescriptionStore nodeDescriptionStore = new NodeDescriptionStore(); + + private final TypeSystem typeSystem; + + private final Neo4jConversionService conversionService; + + private final Map, Set> postLoadMethods = new ConcurrentHashMap<>(); + + private final Lazy propertyCharacteristicsProvider; + + private EventSupport eventSupport; + + @Nullable + private AutowireCapableBeanFactory beanFactory; + + private boolean strict = false; + + public Neo4jMappingContext() { + + this(new Builder()); + } + + public Neo4jMappingContext(Neo4jConversions neo4jConversions) { + + this(new Builder(neo4jConversions, null, null)); + } + + private Neo4jMappingContext(Builder builder) { + + this.conversionService = new DefaultNeo4jConversionService(builder.neo4jConversions); + this.typeSystem = (builder.typeSystem != null) ? builder.typeSystem : TypeSystem.getDefault(); + this.eventSupport = EventSupport.useExistingCallbacks(this, EntityCallbacks.create()); + + super.setSimpleTypeHolder(builder.neo4jConversions.getSimpleTypeHolder()); + + PersistentPropertyCharacteristicsProvider characteristicsProvider = builder.persistentPropertyCharacteristicsProvider; + this.propertyCharacteristicsProvider = Lazy + .of(() -> (characteristicsProvider != null || this.beanFactory == null) ? characteristicsProvider + : this.beanFactory.getBeanProvider(PersistentPropertyCharacteristicsProvider.class).getIfUnique()); + } + + public static Builder builder() { + return new Builder(); + } + + private static boolean isValidParentNode(Class parentClass) { + if (parentClass == null || parentClass.equals(Object.class)) { + return false; + } + + // Either a concrete class explicitly annotated as Node or an abstract class + return Modifier.isAbstract(parentClass.getModifiers()) || parentClass.isAnnotationPresent(Node.class); + } + + private static boolean isValidEntityInterface(Class typeInterface) { + return typeInterface.isAnnotationPresent(Node.class); + } + + private static Set computePostLoadMethods(Neo4jPersistentEntity entity) { + + Set postLoadMethods = new LinkedHashSet<>(); + ReflectionUtils.MethodFilter isValidPostLoad = method -> { + int modifiers = method.getModifiers(); + return !Modifier.isStatic(modifiers) && method.getParameterCount() == 0 + && VOID_TYPES.contains(method.getReturnType()) + && AnnotationUtils.findAnnotation(method, PostLoad.class) != null; + }; + Class underlyingClass = entity.getUnderlyingClass(); + ReflectionUtils.doWithMethods(underlyingClass, method -> postLoadMethods.add(new MethodHolder(method, null)), + isValidPostLoad); + if (KotlinDetector.isKotlinType(underlyingClass)) { + ReflectionUtils.doWithFields(underlyingClass, field -> { + ReflectionUtils.doWithMethods(field.getType(), + method -> postLoadMethods.add(new MethodHolder(method, field)), isValidPostLoad); + }, field -> field.isSynthetic() && field.getName().startsWith("$$delegate_")); + } + + return Collections.unmodifiableSet(postLoadMethods); + } + + /** + * We need to set the context to non-strict in case we must dynamically add parent + * classes. As there is no way to access the original value without reflection, we + * track its change. + * @param strict the new value for the strict setting + */ + @Override + public void setStrict(boolean strict) { + super.setStrict(strict); + this.strict = strict; + } + + @Override + public Neo4jEntityConverter getEntityConverter() { + return new DefaultNeo4jEntityConverter(INSTANTIATORS, this.nodeDescriptionStore, this.conversionService, + this.eventSupport, this.typeSystem); + } + + public Neo4jConversionService getConversionService() { + return this.conversionService; + } + + public EntityInstantiator getInstantiatorFor(PersistentEntity entity) { + return INSTANTIATORS.getInstantiatorFor(entity); + } + + public boolean hasCustomWriteTarget(Class targetType) { + return this.conversionService.hasCustomWriteTarget(targetType); + } + + @Override + protected Neo4jPersistentEntity createPersistentEntity(TypeInformation typeInformation) { + + final DefaultNeo4jPersistentEntity newEntity = new DefaultNeo4jPersistentEntity<>(typeInformation); + String primaryLabel = newEntity.getPrimaryLabel(); + + // We don't store interface in the index. + // This is required for a pretty standard scenario: Having the interface spotting + // the standard name of a domain + // as the class name, and different implementations (for example even in different + // stores) having a store dedicated + // annotation repeating the interface name + if (!newEntity.describesInterface()) { + if (this.nodeDescriptionStore.containsKey(primaryLabel)) { + + Neo4jPersistentEntity existingEntity = (Neo4jPersistentEntity) this.nodeDescriptionStore + .get(primaryLabel); + if (existingEntity != null && !existingEntity.getTypeInformation() + .getRawTypeInformation() + .equals(typeInformation.getRawTypeInformation())) { + String message = String.format(Locale.ENGLISH, + "The schema already contains a node description under the primary label %s", primaryLabel); + throw new MappingException(message); + } + } + + if (this.nodeDescriptionStore.containsValue(newEntity)) { + Optional label = this.nodeDescriptionStore.entrySet() + .stream() + .filter(e -> e.getValue().equals(newEntity)) + .map(Map.Entry::getKey) + .findFirst(); + + String message = String.format(Locale.ENGLISH, + "The schema already contains description %s under the primary label %s", newEntity, + label.orElse("n/a")); + throw new MappingException(message); + } + + NodeDescription existingDescription = this.getNodeDescription(newEntity.getUnderlyingClass()); + if (existingDescription != null) { + + if (!existingDescription.getPrimaryLabel().equals(newEntity.getPrimaryLabel())) { + String message = String.format(Locale.ENGLISH, + "The schema already contains description with the underlying class %s under the primary label %s", + newEntity.getUnderlyingClass().getName(), existingDescription.getPrimaryLabel()); + throw new MappingException(message); + } + } + + this.nodeDescriptionStore.put(primaryLabel, newEntity); + } + + // determine super class to create the node hierarchy + Class type = typeInformation.getType(); + Class superclass = type.getSuperclass(); + + if (isValidParentNode(superclass)) { + synchronized (this) { + super.setStrict(false); + Neo4jPersistentEntity parentNodeDescription = getPersistentEntity(superclass); + if (parentNodeDescription != null) { + parentNodeDescription.addChildNodeDescription(newEntity); + newEntity.setParentNodeDescription(parentNodeDescription); + } + this.setStrict(this.strict); + } + } + + for (Class typeInterface : type.getInterfaces()) { + if (isValidEntityInterface(typeInterface)) { + super.setStrict(false); + Neo4jPersistentEntity parentNodeDescription = getPersistentEntity(typeInterface); + if (parentNodeDescription != null) { + parentNodeDescription.addChildNodeDescription(newEntity); + } + this.setStrict(this.strict); + } + } + + return newEntity; + } + + @Override + protected Neo4jPersistentProperty createPersistentProperty(Property property, Neo4jPersistentEntity owner, + SimpleTypeHolder simpleTypeHolder) { + + PersistentPropertyCharacteristics optionalCharacteristics = this.propertyCharacteristicsProvider.getOptional() + .flatMap(provider -> Optional.ofNullable(provider.apply(property, owner))) + .orElse(null); + + return new DefaultNeo4jPersistentProperty(property, owner, this, simpleTypeHolder, optionalCharacteristics); + } + + @Override + @Nullable public NodeDescription getNodeDescription(String primaryLabel) { + return this.nodeDescriptionStore.get(primaryLabel); + } + + @Override + @Nullable public NodeDescription getNodeDescription(Class underlyingClass) { + return doGetPersistentEntity(underlyingClass); + } + + @Override + @Nullable public Neo4jPersistentEntity getPersistentEntity(TypeInformation typeInformation) { + + Neo4jPersistentEntity existingDescription = this.doGetPersistentEntity(typeInformation); + if (existingDescription != null) { + return existingDescription; + } + return super.getPersistentEntity(typeInformation); + } + + @Override + public Optional> addPersistentEntity(TypeInformation typeInformation) { + + NodeDescription existingDescription = this.doGetPersistentEntity(typeInformation); + if (existingDescription != null) { + return Optional.of((Neo4jPersistentEntity) existingDescription); + } + return super.addPersistentEntity(typeInformation); + } + + @Nullable private Neo4jPersistentEntity doGetPersistentEntity(TypeInformation typeInformation) { + return doGetPersistentEntity(typeInformation.getRawTypeInformation().getType()); + } + + /** + * This checks whether a type is an interface and if so, tries to figure whether a + * persistent entity exists matching the name that can be derived from the interface. + * If the interface is assignable by the class by behind the retrieved entity, that + * entity will be used. Otherwise we will look for an entity matching the interface + * type itself. + * @param underlyingClass the underlying class + * @return an optional persistent entity + */ + @Nullable private Neo4jPersistentEntity doGetPersistentEntity(Class underlyingClass) { + + if (underlyingClass.isInterface()) { + String primaryLabel = DefaultNeo4jPersistentEntity.computePrimaryLabel(underlyingClass); + Neo4jPersistentEntity nodeDescription = (Neo4jPersistentEntity) getNodeDescription(primaryLabel); + if (nodeDescription != null && underlyingClass.isAssignableFrom(nodeDescription.getUnderlyingClass())) { + return nodeDescription; + } + } + + return (Neo4jPersistentEntity) this.nodeDescriptionStore.getNodeDescription(underlyingClass); + } + + private T createBeanOrInstantiate(Class t) { + T idGenerator; + if (this.beanFactory == null) { + idGenerator = BeanUtils.instantiateClass(t); + } + else { + idGenerator = this.beanFactory.getBeanProvider(t).getIfUnique(() -> { + // The beanFactory can't actually be reassigned, so doing a whole double + // lock check is a bit overkill + @SuppressWarnings("NullAway") + var result = this.beanFactory.createBean(t); + return result; + }); + } + return idGenerator; + } + + @Override + public > T getOrCreateIdGeneratorOfType(Class idGeneratorType) { + + return idGeneratorType.cast(this.idGenerators.computeIfAbsent(idGeneratorType, this::createBeanOrInstantiate)); + } + + @Override + @SuppressWarnings("unchecked") + public > Optional getIdGenerator(String reference) { + + if (this.beanFactory == null) { + return Optional.empty(); + } + try { + return Optional.of((T) this.beanFactory.getBean(reference)); + } + catch (NoSuchBeanDefinitionException ex) { + return Optional.empty(); + } + } + + @Nullable Constructor findConstructor(Class clazz, Class... parameterTypes) { + try { + return ReflectionUtils.accessibleConstructor(clazz, parameterTypes); + } + catch (NoSuchMethodException ex) { + return null; + } + } + + private T getOrCreateConverterFactoryOfType( + Class converterFactoryType) { + + return converterFactoryType.cast(this.converterFactories.computeIfAbsent(converterFactoryType, t -> { + Constructor optionalConstructor; + optionalConstructor = findConstructor(t, BeanFactory.class, Neo4jConversionService.class); + if (optionalConstructor != null) { + return t + .cast(BeanUtils.instantiateClass(optionalConstructor, this.beanFactory, this.conversionService)); + } + + optionalConstructor = findConstructor(t, Neo4jConversionService.class, BeanFactory.class); + if (optionalConstructor != null) { + return t + .cast(BeanUtils.instantiateClass(optionalConstructor, this.beanFactory, this.conversionService)); + } + + optionalConstructor = findConstructor(t, BeanFactory.class); + if (optionalConstructor != null) { + return t.cast(BeanUtils.instantiateClass(optionalConstructor, this.beanFactory)); + } + + optionalConstructor = findConstructor(t, Neo4jConversionService.class); + if (optionalConstructor != null) { + return t.cast(BeanUtils.instantiateClass(optionalConstructor, this.conversionService)); + } + return BeanUtils.instantiateClass(t); + })); + } + + @SuppressWarnings("rawtypes") + @Nullable Neo4jPersistentPropertyConverter getOptionalCustomConversionsFor(Neo4jPersistentProperty persistentProperty) { + + // Is the annotation present at all? + if (!persistentProperty.isAnnotationPresent(ConvertWith.class)) { + return null; + } + + ConvertWith convertWith = persistentProperty.getRequiredAnnotation(ConvertWith.class); + Neo4jPersistentPropertyConverterFactory persistentPropertyConverterFactory = this + .getOrCreateConverterFactoryOfType(convertWith.converterFactory()); + Neo4jPersistentPropertyConverter customConverter = persistentPropertyConverterFactory + .getPropertyConverterFor(persistentProperty); + + boolean forCollection = false; + if (persistentProperty.isCollectionLike()) { + Class converterClass; + Method getClassOfDelegate = ReflectionUtils.findMethod(customConverter.getClass(), "getClassOfDelegate"); + if (getClassOfDelegate != null) { + ReflectionUtils.makeAccessible(getClassOfDelegate); + converterClass = (Class) ReflectionUtils.invokeMethod(getClassOfDelegate, customConverter); + } + else { + converterClass = customConverter.getClass(); + } + Map typeVariableMap = (converterClass != null) + ? GenericTypeResolver.getTypeVariableMap(converterClass) : Map.of(); + forCollection = typeVariableMap.values() + .stream() + .anyMatch(propertyType -> propertyType instanceof ParameterizedType + && persistentProperty.getType().equals(((ParameterizedType) propertyType).getRawType())); + } + + return new NullSafeNeo4jPersistentPropertyConverter<>(customConverter, persistentProperty.isComposite(), + forCollection); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + super.setApplicationContext(applicationContext); + + this.beanFactory = applicationContext.getAutowireCapableBeanFactory(); + this.eventSupport = EventSupport.discoverCallbacks(this, this.beanFactory); + } + + public CreateRelationshipStatementHolder createStatementForImperativeSimpleRelationshipBatch( + Neo4jPersistentEntity neo4jPersistentEntity, RelationshipDescription relationshipDescription, + List plainRelationshipRows, boolean canUseElementId) { + + return createStatementForSingleRelationship(neo4jPersistentEntity, + (DefaultRelationshipDescription) relationshipDescription, plainRelationshipRows, canUseElementId); + } + + public CreateRelationshipStatementHolder createStatementForImperativeRelationshipsWithPropertiesBatch(boolean isNew, + Neo4jPersistentEntity neo4jPersistentEntity, RelationshipDescription relationshipDescription, + Object relatedValues, List> relationshipPropertiesRows, boolean canUseElementId) { + + List relationshipPropertyValues = ((Collection) relatedValues) + .stream() + .map(MappingSupport.RelationshipPropertiesWithEntityHolder.class::cast) + .collect(Collectors.toList()); + + return createStatementForRelationshipWithPropertiesBatch(isNew, neo4jPersistentEntity, relationshipDescription, + relationshipPropertyValues, relationshipPropertiesRows, canUseElementId); + } + + public CreateRelationshipStatementHolder createStatementForSingleRelationship( + Neo4jPersistentEntity neo4jPersistentEntity, RelationshipDescription relationshipContext, + Object relatedValue, boolean isNewRelationship, boolean canUseElementId) { + + if (relationshipContext.hasRelationshipProperties()) { + MappingSupport.RelationshipPropertiesWithEntityHolder relatedValueEntityHolder = (MappingSupport.RelationshipPropertiesWithEntityHolder) ( + // either this is a scalar entity holder value + // or a dynamic relationship with + // either a list of entity holders + // or a scalar value + (relatedValue instanceof MappingSupport.RelationshipPropertiesWithEntityHolder) ? relatedValue + : (((Map.Entry) relatedValue).getValue() instanceof List) + ? ((List) ((Map.Entry) relatedValue).getValue()).get(0) + : ((Map.Entry) relatedValue).getValue()); + + String dynamicRelationshipType = null; + if (relationshipContext.isDynamic()) { + Neo4jPersistentProperty inverse = ((DefaultRelationshipDescription) relationshipContext).getInverse(); + TypeInformation keyType = inverse.getTypeInformation().getRequiredComponentType(); + Object key = ((Map.Entry) relatedValue).getKey(); + dynamicRelationshipType = this.conversionService + .writeValue(key, keyType, inverse.getOptionalConverter()) + .asString(); + } + return createStatementForRelationshipWithProperties(neo4jPersistentEntity, relationshipContext, + dynamicRelationshipType, relatedValueEntityHolder, isNewRelationship, canUseElementId); + } + else { + return createStatementForSingleRelationship(neo4jPersistentEntity, + (DefaultRelationshipDescription) relationshipContext, relatedValue, canUseElementId); + } + } + + private CreateRelationshipStatementHolder createStatementForRelationshipWithProperties( + Neo4jPersistentEntity neo4jPersistentEntity, RelationshipDescription relationshipDescription, + @Nullable String dynamicRelationshipType, + MappingSupport.RelationshipPropertiesWithEntityHolder relatedValue, boolean isNewRelationship, + boolean canUseElementId) { + + Statement relationshipCreationQuery = CypherGenerator.INSTANCE.prepareSaveOfRelationshipWithProperties( + neo4jPersistentEntity, relationshipDescription, isNewRelationship, dynamicRelationshipType, + canUseElementId, false); + + Map propMap = new HashMap<>(); + // write relationship properties + getEntityConverter().write(relatedValue.getRelationshipProperties(), propMap); + + return new CreateRelationshipStatementHolder(relationshipCreationQuery, propMap); + } + + private CreateRelationshipStatementHolder createStatementForRelationshipWithPropertiesBatch(boolean isNew, + Neo4jPersistentEntity neo4jPersistentEntity, RelationshipDescription relationshipDescription, + List relatedValues, + List> relationshipPropertiesRows, boolean canUseElementId) { + + Statement relationshipCreationQuery = CypherGenerator.INSTANCE.prepareUpdateOfRelationshipsWithProperties( + neo4jPersistentEntity, relationshipDescription, isNew, canUseElementId); + List relationshipRows = new ArrayList<>(); + Map relationshipPropertiesEntries = new HashMap<>(); + if (isNew) { + for (int i = 0; i < relatedValues.size(); i++) { + MappingSupport.RelationshipPropertiesWithEntityHolder relatedValue = relatedValues.get(i); + // write relationship properties + Map propMap = relationshipPropertiesRows.get(i); + getEntityConverter().write(relatedValue.getRelationshipProperties(), propMap); + relationshipRows.add(propMap); + } + } + relationshipPropertiesEntries.put(Constants.NAME_OF_RELATIONSHIP_LIST_PARAM, relationshipRows); + return new CreateRelationshipStatementHolder(relationshipCreationQuery, relationshipPropertiesEntries); + } + + private CreateRelationshipStatementHolder createStatementForSingleRelationship( + Neo4jPersistentEntity neo4jPersistentEntity, DefaultRelationshipDescription relationshipDescription, + Object relatedValue, boolean canUseElementId) { + + String relationshipType; + if (!relationshipDescription.isDynamic()) { + relationshipType = null; + } + else { + Neo4jPersistentProperty inverse = relationshipDescription.getInverse(); + TypeInformation keyType = inverse.getTypeInformation().getRequiredComponentType(); + Object key = ((Map.Entry) relatedValue).getKey(); + relationshipType = this.conversionService.writeValue(key, keyType, inverse.getOptionalConverter()) + .asString(); + } + + Statement relationshipCreationQuery = CypherGenerator.INSTANCE.prepareSaveOfRelationships(neo4jPersistentEntity, + relationshipDescription, relationshipType, canUseElementId); + return new CreateRelationshipStatementHolder(relationshipCreationQuery, Map.of()); + } + + /** + * Executes all post load methods of the given instance. + * @param entity the entity definition + * @param instance the instance whose post load methods should be executed + * @param type of the entity + * @return the instance + */ + public T invokePostLoad(Neo4jPersistentEntity entity, T instance) { + + getPostLoadMethods(entity).forEach(methodHolder -> methodHolder.invoke(instance)); + return instance; + } + + Set getPostLoadMethods(Neo4jPersistentEntity entity) { + return this.postLoadMethods.computeIfAbsent(entity, Neo4jMappingContext::computePostLoadMethods); + } + + /** + * A builder for creating custom instances of a {@link Neo4jMappingContext}. + * + * @since 6.3.7 + */ + public static final class Builder { + + private Neo4jConversions neo4jConversions; + + private TypeSystem typeSystem; + + @Nullable + private PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider; + + private Builder() { + this(new Neo4jConversions(), null, null); + } + + private Builder(Neo4jConversions neo4jConversions, @Nullable TypeSystem typeSystem, + @Nullable PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider) { + this.neo4jConversions = neo4jConversions; + this.typeSystem = Objects.requireNonNullElseGet(typeSystem, TypeSystem::getDefault); + this.persistentPropertyCharacteristicsProvider = persistentPropertyCharacteristicsProvider; + } + + @SuppressWarnings("HiddenField") + public Builder withNeo4jConversions(Neo4jConversions neo4jConversions) { + this.neo4jConversions = neo4jConversions; + return this; + } + + @SuppressWarnings("HiddenField") + public Builder withPersistentPropertyCharacteristicsProvider( + PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider) { + this.persistentPropertyCharacteristicsProvider = persistentPropertyCharacteristicsProvider; + return this; + } + + @SuppressWarnings("HiddenField") + public Builder withTypeSystem(TypeSystem typeSystem) { + this.typeSystem = Objects.requireNonNullElseGet(typeSystem, TypeSystem::getDefault); + return this; + } + + public Neo4jMappingContext build() { + return new Neo4jMappingContext(this); + } + + } + + static class MethodHolder { + + private final Method method; + + @Nullable + private final Field delegate; + + MethodHolder(Method method, @Nullable Field delegate) { + this.method = method; + this.delegate = delegate; + } + + static Object getInstanceOrDelegate(Object instance, @Nullable Field delegateHolder) { + if (delegateHolder == null) { + return instance; + } + else { + try { + delegateHolder.setAccessible(true); + return delegateHolder.get(instance); + } + catch (IllegalAccessException ex) { + throw new RuntimeException(ex); + } + } + } + + String getName() { + return this.method.getName(); + } + + void invoke(Object instance) { + + this.method.setAccessible(true); + ReflectionUtils.invokeMethod(this.method, getInstanceOrDelegate(instance, this.delegate)); + } + + } + +} From f39f005fb26965c44079d0f971b175709b36ac7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francesco=20Chicchiricc=C3=B2?= Date: Tue, 25 Aug 2026 12:34:18 +0200 Subject: [PATCH 3/3] Fixes --- .../persistence/jpa/inner/ResourceTest.java | 15 +- core/persistence-neo4j/pom.xml | 4 - .../neo4j/entity/Neo4jExternalResource.java | 6 + .../entity/anyobject/Neo4jAMembership.java | 2 +- .../neo4j/entity/task/Neo4jPushTask.java | 6 + .../core/mapping/Neo4jMappingContext.java | 713 ------------------ .../persistence/neo4j/inner/ResourceTest.java | 15 +- .../java/DefaultAuditManager.java | 2 +- .../LDAPMembershipPropagationActions.java | 3 +- .../syncope/fit/core/DebeziumITCase.java | 18 +- .../fit/core/PropagationTaskITCase.java | 42 +- .../syncope/fit/core/PullTaskITCase.java | 3 +- pom.xml | 2 +- 13 files changed, 51 insertions(+), 780 deletions(-) delete mode 100644 core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/core/mapping/Neo4jMappingContext.java diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java index 948fd6b9114..61b2f4738ba 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java @@ -66,7 +66,7 @@ public void findById() { assertEquals("net.tirasa.connid.bundles.soap.WebServiceConnector", connector.getConnectorName()); assertEquals("net.tirasa.connid.bundles.soap", connector.getBundleName()); - Mapping mapping = resource.getProvisionByAnyType(AnyTypeKind.USER.name()).get().getMapping(); + Mapping mapping = resource.getProvisionByAnyType(AnyTypeKind.USER.name()).orElseThrow().getMapping(); assertFalse(mapping.getItems().isEmpty()); assertTrue(mapping.getItems().stream(). @@ -80,6 +80,12 @@ public void findById() { } } + @Test + public void propagationActions() { + ExternalResource resource = resourceDAO.findById("resource-ldap").orElseThrow(); + assertEquals(2, resource.getPropagationActions().size()); + } + @Test public void findWithOrgUnit() { ExternalResource resource = resourceDAO.findById("resource-ldap-orgunit").orElseThrow(); @@ -110,8 +116,8 @@ public void findAll() { @Test public void getConnObjectKey() { ExternalResource resource = resourceDAO.findById("ws-target-resource-2").orElseThrow(); - assertEquals("fullname", resource.getProvisionByAnyType(AnyTypeKind.USER.name()).get(). - getMapping().getConnObjectKeyItem().get().getIntAttrName()); + assertEquals("fullname", resource.getProvisionByAnyType(AnyTypeKind.USER.name()).orElseThrow(). + getMapping().getConnObjectKeyItem().orElseThrow().getIntAttrName()); } @Test @@ -277,7 +283,8 @@ public void saveWithGroupMappingType() { entityManager.flush(); assertNotNull(actual); - assertEquals(3, actual.getProvisionByAnyType(AnyTypeKind.USER.name()).get().getMapping().getItems().size()); + assertEquals(3, actual.getProvisionByAnyType(AnyTypeKind.USER.name()).orElseThrow().getMapping().getItems(). + size()); } @Test diff --git a/core/persistence-neo4j/pom.xml b/core/persistence-neo4j/pom.xml index fc1c4776c7e..9860f16f7f3 100644 --- a/core/persistence-neo4j/pom.xml +++ b/core/persistence-neo4j/pom.xml @@ -101,10 +101,6 @@ under the License. org.apache.maven.plugins maven-checkstyle-plugin - - - **/Neo4jMappingContext** - diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jExternalResource.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jExternalResource.java index 8b76ca05408..52998f8cbf3 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jExternalResource.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jExternalResource.java @@ -55,6 +55,7 @@ import org.springframework.data.annotation.Transient; import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; +import org.springframework.data.neo4j.core.schema.PostLoad; import org.springframework.data.neo4j.core.schema.Relationship; @Node(Neo4jExternalResource.NODE) @@ -353,4 +354,9 @@ public boolean add(final Implementation propagationAction) { public List getPropagationActions() { return sortedPropagationActions; } + + @PostLoad + public void postLoad() { + sortedPropagationActions = new SortedSetList<>(propagationActions, Neo4jImplementationRelationship.builder()); + } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/anyobject/Neo4jAMembership.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/anyobject/Neo4jAMembership.java index a660340b6e3..f3f9bdec091 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/anyobject/Neo4jAMembership.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/anyobject/Neo4jAMembership.java @@ -95,6 +95,6 @@ protected Map plainAttrs() { @PostLoad public void postLoad() { - this.aMembershipType = new AMembershipType(leftEnd.getType()); + aMembershipType = new AMembershipType(leftEnd.getType()); } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPushTask.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPushTask.java index 0122d239597..63472a5a4d8 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPushTask.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jPushTask.java @@ -40,6 +40,7 @@ import org.springframework.data.annotation.Transient; import org.springframework.data.neo4j.core.convert.ConvertWith; import org.springframework.data.neo4j.core.schema.Node; +import org.springframework.data.neo4j.core.schema.PostLoad; import org.springframework.data.neo4j.core.schema.Relationship; @Node(Neo4jPushTask.NODE) @@ -118,4 +119,9 @@ protected Class> executionClass() { protected List> executions() { return pushTaskExecs; } + + @PostLoad + public void postLoad() { + sortedActions = new SortedSetList<>(actions, Neo4jImplementationRelationship.builder()); + } } diff --git a/core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/core/mapping/Neo4jMappingContext.java b/core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/core/mapping/Neo4jMappingContext.java deleted file mode 100644 index 3997bb8fcde..00000000000 --- a/core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/core/mapping/Neo4jMappingContext.java +++ /dev/null @@ -1,713 +0,0 @@ -/* - * Copyright 2011-present the original author or authors. - * - * 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 - * - * https://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.springframework.data.neo4j.core.mapping; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -import org.apiguardian.api.API; -import org.jspecify.annotations.Nullable; -import org.neo4j.cypherdsl.core.Statement; -import org.neo4j.driver.types.TypeSystem; - -import org.springframework.beans.BeanUtils; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.core.GenericTypeResolver; -import org.springframework.core.KotlinDetector; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.data.core.TypeInformation; -import org.springframework.data.mapping.MappingException; -import org.springframework.data.mapping.PersistentEntity; -import org.springframework.data.mapping.callback.EntityCallbacks; -import org.springframework.data.mapping.context.AbstractMappingContext; -import org.springframework.data.mapping.model.EntityInstantiator; -import org.springframework.data.mapping.model.EntityInstantiators; -import org.springframework.data.mapping.model.Property; -import org.springframework.data.mapping.model.SimpleTypeHolder; -import org.springframework.data.neo4j.core.convert.ConvertWith; -import org.springframework.data.neo4j.core.convert.Neo4jConversionService; -import org.springframework.data.neo4j.core.convert.Neo4jConversions; -import org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverter; -import org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverterFactory; -import org.springframework.data.neo4j.core.mapping.callback.EventSupport; -import org.springframework.data.neo4j.core.schema.IdGenerator; -import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; -import org.springframework.data.util.Lazy; -import org.springframework.util.ReflectionUtils; - -/** - * An implementation of both a {@link Schema} as well as a Neo4j version of Spring Data's - * {@link org.springframework.data.mapping.context.MappingContext}. It is recommended to - * provide the initial set of classes through {@link #setInitialEntitySet(Set)}. - * - * @author Michael J. Simons - * @author Gerrit Meier - * @since 6.0 - */ -@API(status = API.Status.STABLE, since = "6.0") -public final class Neo4jMappingContext extends AbstractMappingContext, Neo4jPersistentProperty> - implements Schema { - - /** - * The shared entity instantiators of this context. Those should not be recreated for - * each entity or even not for each query, as otherwise the cache of Spring's - * org.springframework.data.convert.ClassGeneratingEntityInstantiator won't apply - */ - private static final EntityInstantiators INSTANTIATORS = new EntityInstantiators(); - - private static final Set> VOID_TYPES = new HashSet<>(Arrays.asList(Void.class, void.class)); - - /** - * A map of fallback id generators, that have not been added to the application - * context. - */ - private final Map>, IdGenerator> idGenerators = new ConcurrentHashMap<>(); - - private final Map, Neo4jPersistentPropertyConverterFactory> converterFactories = new ConcurrentHashMap<>(); - - /** - * The {@link NodeDescriptionStore} is basically a {@link Map} and it is used to break - * the dependency cycle between this class and the - * {@link DefaultNeo4jEntityConverter}. - */ - private final NodeDescriptionStore nodeDescriptionStore = new NodeDescriptionStore(); - - private final TypeSystem typeSystem; - - private final Neo4jConversionService conversionService; - - private final Map, Set> postLoadMethods = new ConcurrentHashMap<>(); - - private final Lazy propertyCharacteristicsProvider; - - private EventSupport eventSupport; - - @Nullable - private AutowireCapableBeanFactory beanFactory; - - private boolean strict = false; - - public Neo4jMappingContext() { - - this(new Builder()); - } - - public Neo4jMappingContext(Neo4jConversions neo4jConversions) { - - this(new Builder(neo4jConversions, null, null)); - } - - private Neo4jMappingContext(Builder builder) { - - this.conversionService = new DefaultNeo4jConversionService(builder.neo4jConversions); - this.typeSystem = (builder.typeSystem != null) ? builder.typeSystem : TypeSystem.getDefault(); - this.eventSupport = EventSupport.useExistingCallbacks(this, EntityCallbacks.create()); - - super.setSimpleTypeHolder(builder.neo4jConversions.getSimpleTypeHolder()); - - PersistentPropertyCharacteristicsProvider characteristicsProvider = builder.persistentPropertyCharacteristicsProvider; - this.propertyCharacteristicsProvider = Lazy - .of(() -> (characteristicsProvider != null || this.beanFactory == null) ? characteristicsProvider - : this.beanFactory.getBeanProvider(PersistentPropertyCharacteristicsProvider.class).getIfUnique()); - } - - public static Builder builder() { - return new Builder(); - } - - private static boolean isValidParentNode(Class parentClass) { - if (parentClass == null || parentClass.equals(Object.class)) { - return false; - } - - // Either a concrete class explicitly annotated as Node or an abstract class - return Modifier.isAbstract(parentClass.getModifiers()) || parentClass.isAnnotationPresent(Node.class); - } - - private static boolean isValidEntityInterface(Class typeInterface) { - return typeInterface.isAnnotationPresent(Node.class); - } - - private static Set computePostLoadMethods(Neo4jPersistentEntity entity) { - - Set postLoadMethods = new LinkedHashSet<>(); - ReflectionUtils.MethodFilter isValidPostLoad = method -> { - int modifiers = method.getModifiers(); - return !Modifier.isStatic(modifiers) && method.getParameterCount() == 0 - && VOID_TYPES.contains(method.getReturnType()) - && AnnotationUtils.findAnnotation(method, PostLoad.class) != null; - }; - Class underlyingClass = entity.getUnderlyingClass(); - ReflectionUtils.doWithMethods(underlyingClass, method -> postLoadMethods.add(new MethodHolder(method, null)), - isValidPostLoad); - if (KotlinDetector.isKotlinType(underlyingClass)) { - ReflectionUtils.doWithFields(underlyingClass, field -> { - ReflectionUtils.doWithMethods(field.getType(), - method -> postLoadMethods.add(new MethodHolder(method, field)), isValidPostLoad); - }, field -> field.isSynthetic() && field.getName().startsWith("$$delegate_")); - } - - return Collections.unmodifiableSet(postLoadMethods); - } - - /** - * We need to set the context to non-strict in case we must dynamically add parent - * classes. As there is no way to access the original value without reflection, we - * track its change. - * @param strict the new value for the strict setting - */ - @Override - public void setStrict(boolean strict) { - super.setStrict(strict); - this.strict = strict; - } - - @Override - public Neo4jEntityConverter getEntityConverter() { - return new DefaultNeo4jEntityConverter(INSTANTIATORS, this.nodeDescriptionStore, this.conversionService, - this.eventSupport, this.typeSystem); - } - - public Neo4jConversionService getConversionService() { - return this.conversionService; - } - - public EntityInstantiator getInstantiatorFor(PersistentEntity entity) { - return INSTANTIATORS.getInstantiatorFor(entity); - } - - public boolean hasCustomWriteTarget(Class targetType) { - return this.conversionService.hasCustomWriteTarget(targetType); - } - - @Override - protected Neo4jPersistentEntity createPersistentEntity(TypeInformation typeInformation) { - - final DefaultNeo4jPersistentEntity newEntity = new DefaultNeo4jPersistentEntity<>(typeInformation); - String primaryLabel = newEntity.getPrimaryLabel(); - - // We don't store interface in the index. - // This is required for a pretty standard scenario: Having the interface spotting - // the standard name of a domain - // as the class name, and different implementations (for example even in different - // stores) having a store dedicated - // annotation repeating the interface name - if (!newEntity.describesInterface()) { - if (this.nodeDescriptionStore.containsKey(primaryLabel)) { - - Neo4jPersistentEntity existingEntity = (Neo4jPersistentEntity) this.nodeDescriptionStore - .get(primaryLabel); - if (existingEntity != null && !existingEntity.getTypeInformation() - .getRawTypeInformation() - .equals(typeInformation.getRawTypeInformation())) { - String message = String.format(Locale.ENGLISH, - "The schema already contains a node description under the primary label %s", primaryLabel); - throw new MappingException(message); - } - } - - if (this.nodeDescriptionStore.containsValue(newEntity)) { - Optional label = this.nodeDescriptionStore.entrySet() - .stream() - .filter(e -> e.getValue().equals(newEntity)) - .map(Map.Entry::getKey) - .findFirst(); - - String message = String.format(Locale.ENGLISH, - "The schema already contains description %s under the primary label %s", newEntity, - label.orElse("n/a")); - throw new MappingException(message); - } - - NodeDescription existingDescription = this.getNodeDescription(newEntity.getUnderlyingClass()); - if (existingDescription != null) { - - if (!existingDescription.getPrimaryLabel().equals(newEntity.getPrimaryLabel())) { - String message = String.format(Locale.ENGLISH, - "The schema already contains description with the underlying class %s under the primary label %s", - newEntity.getUnderlyingClass().getName(), existingDescription.getPrimaryLabel()); - throw new MappingException(message); - } - } - - this.nodeDescriptionStore.put(primaryLabel, newEntity); - } - - // determine super class to create the node hierarchy - Class type = typeInformation.getType(); - Class superclass = type.getSuperclass(); - - if (isValidParentNode(superclass)) { - synchronized (this) { - super.setStrict(false); - Neo4jPersistentEntity parentNodeDescription = getPersistentEntity(superclass); - if (parentNodeDescription != null) { - parentNodeDescription.addChildNodeDescription(newEntity); - newEntity.setParentNodeDescription(parentNodeDescription); - } - this.setStrict(this.strict); - } - } - - for (Class typeInterface : type.getInterfaces()) { - if (isValidEntityInterface(typeInterface)) { - super.setStrict(false); - Neo4jPersistentEntity parentNodeDescription = getPersistentEntity(typeInterface); - if (parentNodeDescription != null) { - parentNodeDescription.addChildNodeDescription(newEntity); - } - this.setStrict(this.strict); - } - } - - return newEntity; - } - - @Override - protected Neo4jPersistentProperty createPersistentProperty(Property property, Neo4jPersistentEntity owner, - SimpleTypeHolder simpleTypeHolder) { - - PersistentPropertyCharacteristics optionalCharacteristics = this.propertyCharacteristicsProvider.getOptional() - .flatMap(provider -> Optional.ofNullable(provider.apply(property, owner))) - .orElse(null); - - return new DefaultNeo4jPersistentProperty(property, owner, this, simpleTypeHolder, optionalCharacteristics); - } - - @Override - @Nullable public NodeDescription getNodeDescription(String primaryLabel) { - return this.nodeDescriptionStore.get(primaryLabel); - } - - @Override - @Nullable public NodeDescription getNodeDescription(Class underlyingClass) { - return doGetPersistentEntity(underlyingClass); - } - - @Override - @Nullable public Neo4jPersistentEntity getPersistentEntity(TypeInformation typeInformation) { - - Neo4jPersistentEntity existingDescription = this.doGetPersistentEntity(typeInformation); - if (existingDescription != null) { - return existingDescription; - } - return super.getPersistentEntity(typeInformation); - } - - @Override - public Optional> addPersistentEntity(TypeInformation typeInformation) { - - NodeDescription existingDescription = this.doGetPersistentEntity(typeInformation); - if (existingDescription != null) { - return Optional.of((Neo4jPersistentEntity) existingDescription); - } - return super.addPersistentEntity(typeInformation); - } - - @Nullable private Neo4jPersistentEntity doGetPersistentEntity(TypeInformation typeInformation) { - return doGetPersistentEntity(typeInformation.getRawTypeInformation().getType()); - } - - /** - * This checks whether a type is an interface and if so, tries to figure whether a - * persistent entity exists matching the name that can be derived from the interface. - * If the interface is assignable by the class by behind the retrieved entity, that - * entity will be used. Otherwise we will look for an entity matching the interface - * type itself. - * @param underlyingClass the underlying class - * @return an optional persistent entity - */ - @Nullable private Neo4jPersistentEntity doGetPersistentEntity(Class underlyingClass) { - - if (underlyingClass.isInterface()) { - String primaryLabel = DefaultNeo4jPersistentEntity.computePrimaryLabel(underlyingClass); - Neo4jPersistentEntity nodeDescription = (Neo4jPersistentEntity) getNodeDescription(primaryLabel); - if (nodeDescription != null && underlyingClass.isAssignableFrom(nodeDescription.getUnderlyingClass())) { - return nodeDescription; - } - } - - return (Neo4jPersistentEntity) this.nodeDescriptionStore.getNodeDescription(underlyingClass); - } - - private T createBeanOrInstantiate(Class t) { - T idGenerator; - if (this.beanFactory == null) { - idGenerator = BeanUtils.instantiateClass(t); - } - else { - idGenerator = this.beanFactory.getBeanProvider(t).getIfUnique(() -> { - // The beanFactory can't actually be reassigned, so doing a whole double - // lock check is a bit overkill - @SuppressWarnings("NullAway") - var result = this.beanFactory.createBean(t); - return result; - }); - } - return idGenerator; - } - - @Override - public > T getOrCreateIdGeneratorOfType(Class idGeneratorType) { - - return idGeneratorType.cast(this.idGenerators.computeIfAbsent(idGeneratorType, this::createBeanOrInstantiate)); - } - - @Override - @SuppressWarnings("unchecked") - public > Optional getIdGenerator(String reference) { - - if (this.beanFactory == null) { - return Optional.empty(); - } - try { - return Optional.of((T) this.beanFactory.getBean(reference)); - } - catch (NoSuchBeanDefinitionException ex) { - return Optional.empty(); - } - } - - @Nullable Constructor findConstructor(Class clazz, Class... parameterTypes) { - try { - return ReflectionUtils.accessibleConstructor(clazz, parameterTypes); - } - catch (NoSuchMethodException ex) { - return null; - } - } - - private T getOrCreateConverterFactoryOfType( - Class converterFactoryType) { - - return converterFactoryType.cast(this.converterFactories.computeIfAbsent(converterFactoryType, t -> { - Constructor optionalConstructor; - optionalConstructor = findConstructor(t, BeanFactory.class, Neo4jConversionService.class); - if (optionalConstructor != null) { - return t - .cast(BeanUtils.instantiateClass(optionalConstructor, this.beanFactory, this.conversionService)); - } - - optionalConstructor = findConstructor(t, Neo4jConversionService.class, BeanFactory.class); - if (optionalConstructor != null) { - return t - .cast(BeanUtils.instantiateClass(optionalConstructor, this.beanFactory, this.conversionService)); - } - - optionalConstructor = findConstructor(t, BeanFactory.class); - if (optionalConstructor != null) { - return t.cast(BeanUtils.instantiateClass(optionalConstructor, this.beanFactory)); - } - - optionalConstructor = findConstructor(t, Neo4jConversionService.class); - if (optionalConstructor != null) { - return t.cast(BeanUtils.instantiateClass(optionalConstructor, this.conversionService)); - } - return BeanUtils.instantiateClass(t); - })); - } - - @SuppressWarnings("rawtypes") - @Nullable Neo4jPersistentPropertyConverter getOptionalCustomConversionsFor(Neo4jPersistentProperty persistentProperty) { - - // Is the annotation present at all? - if (!persistentProperty.isAnnotationPresent(ConvertWith.class)) { - return null; - } - - ConvertWith convertWith = persistentProperty.getRequiredAnnotation(ConvertWith.class); - Neo4jPersistentPropertyConverterFactory persistentPropertyConverterFactory = this - .getOrCreateConverterFactoryOfType(convertWith.converterFactory()); - Neo4jPersistentPropertyConverter customConverter = persistentPropertyConverterFactory - .getPropertyConverterFor(persistentProperty); - - boolean forCollection = false; - if (persistentProperty.isCollectionLike()) { - Class converterClass; - Method getClassOfDelegate = ReflectionUtils.findMethod(customConverter.getClass(), "getClassOfDelegate"); - if (getClassOfDelegate != null) { - ReflectionUtils.makeAccessible(getClassOfDelegate); - converterClass = (Class) ReflectionUtils.invokeMethod(getClassOfDelegate, customConverter); - } - else { - converterClass = customConverter.getClass(); - } - Map typeVariableMap = (converterClass != null) - ? GenericTypeResolver.getTypeVariableMap(converterClass) : Map.of(); - forCollection = typeVariableMap.values() - .stream() - .anyMatch(propertyType -> propertyType instanceof ParameterizedType - && persistentProperty.getType().equals(((ParameterizedType) propertyType).getRawType())); - } - - return new NullSafeNeo4jPersistentPropertyConverter<>(customConverter, persistentProperty.isComposite(), - forCollection); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - super.setApplicationContext(applicationContext); - - this.beanFactory = applicationContext.getAutowireCapableBeanFactory(); - this.eventSupport = EventSupport.discoverCallbacks(this, this.beanFactory); - } - - public CreateRelationshipStatementHolder createStatementForImperativeSimpleRelationshipBatch( - Neo4jPersistentEntity neo4jPersistentEntity, RelationshipDescription relationshipDescription, - List plainRelationshipRows, boolean canUseElementId) { - - return createStatementForSingleRelationship(neo4jPersistentEntity, - (DefaultRelationshipDescription) relationshipDescription, plainRelationshipRows, canUseElementId); - } - - public CreateRelationshipStatementHolder createStatementForImperativeRelationshipsWithPropertiesBatch(boolean isNew, - Neo4jPersistentEntity neo4jPersistentEntity, RelationshipDescription relationshipDescription, - Object relatedValues, List> relationshipPropertiesRows, boolean canUseElementId) { - - List relationshipPropertyValues = ((Collection) relatedValues) - .stream() - .map(MappingSupport.RelationshipPropertiesWithEntityHolder.class::cast) - .collect(Collectors.toList()); - - return createStatementForRelationshipWithPropertiesBatch(isNew, neo4jPersistentEntity, relationshipDescription, - relationshipPropertyValues, relationshipPropertiesRows, canUseElementId); - } - - public CreateRelationshipStatementHolder createStatementForSingleRelationship( - Neo4jPersistentEntity neo4jPersistentEntity, RelationshipDescription relationshipContext, - Object relatedValue, boolean isNewRelationship, boolean canUseElementId) { - - if (relationshipContext.hasRelationshipProperties()) { - MappingSupport.RelationshipPropertiesWithEntityHolder relatedValueEntityHolder = (MappingSupport.RelationshipPropertiesWithEntityHolder) ( - // either this is a scalar entity holder value - // or a dynamic relationship with - // either a list of entity holders - // or a scalar value - (relatedValue instanceof MappingSupport.RelationshipPropertiesWithEntityHolder) ? relatedValue - : (((Map.Entry) relatedValue).getValue() instanceof List) - ? ((List) ((Map.Entry) relatedValue).getValue()).get(0) - : ((Map.Entry) relatedValue).getValue()); - - String dynamicRelationshipType = null; - if (relationshipContext.isDynamic()) { - Neo4jPersistentProperty inverse = ((DefaultRelationshipDescription) relationshipContext).getInverse(); - TypeInformation keyType = inverse.getTypeInformation().getRequiredComponentType(); - Object key = ((Map.Entry) relatedValue).getKey(); - dynamicRelationshipType = this.conversionService - .writeValue(key, keyType, inverse.getOptionalConverter()) - .asString(); - } - return createStatementForRelationshipWithProperties(neo4jPersistentEntity, relationshipContext, - dynamicRelationshipType, relatedValueEntityHolder, isNewRelationship, canUseElementId); - } - else { - return createStatementForSingleRelationship(neo4jPersistentEntity, - (DefaultRelationshipDescription) relationshipContext, relatedValue, canUseElementId); - } - } - - private CreateRelationshipStatementHolder createStatementForRelationshipWithProperties( - Neo4jPersistentEntity neo4jPersistentEntity, RelationshipDescription relationshipDescription, - @Nullable String dynamicRelationshipType, - MappingSupport.RelationshipPropertiesWithEntityHolder relatedValue, boolean isNewRelationship, - boolean canUseElementId) { - - Statement relationshipCreationQuery = CypherGenerator.INSTANCE.prepareSaveOfRelationshipWithProperties( - neo4jPersistentEntity, relationshipDescription, isNewRelationship, dynamicRelationshipType, - canUseElementId, false); - - Map propMap = new HashMap<>(); - // write relationship properties - getEntityConverter().write(relatedValue.getRelationshipProperties(), propMap); - - return new CreateRelationshipStatementHolder(relationshipCreationQuery, propMap); - } - - private CreateRelationshipStatementHolder createStatementForRelationshipWithPropertiesBatch(boolean isNew, - Neo4jPersistentEntity neo4jPersistentEntity, RelationshipDescription relationshipDescription, - List relatedValues, - List> relationshipPropertiesRows, boolean canUseElementId) { - - Statement relationshipCreationQuery = CypherGenerator.INSTANCE.prepareUpdateOfRelationshipsWithProperties( - neo4jPersistentEntity, relationshipDescription, isNew, canUseElementId); - List relationshipRows = new ArrayList<>(); - Map relationshipPropertiesEntries = new HashMap<>(); - if (isNew) { - for (int i = 0; i < relatedValues.size(); i++) { - MappingSupport.RelationshipPropertiesWithEntityHolder relatedValue = relatedValues.get(i); - // write relationship properties - Map propMap = relationshipPropertiesRows.get(i); - getEntityConverter().write(relatedValue.getRelationshipProperties(), propMap); - relationshipRows.add(propMap); - } - } - relationshipPropertiesEntries.put(Constants.NAME_OF_RELATIONSHIP_LIST_PARAM, relationshipRows); - return new CreateRelationshipStatementHolder(relationshipCreationQuery, relationshipPropertiesEntries); - } - - private CreateRelationshipStatementHolder createStatementForSingleRelationship( - Neo4jPersistentEntity neo4jPersistentEntity, DefaultRelationshipDescription relationshipDescription, - Object relatedValue, boolean canUseElementId) { - - String relationshipType; - if (!relationshipDescription.isDynamic()) { - relationshipType = null; - } - else { - Neo4jPersistentProperty inverse = relationshipDescription.getInverse(); - TypeInformation keyType = inverse.getTypeInformation().getRequiredComponentType(); - Object key = ((Map.Entry) relatedValue).getKey(); - relationshipType = this.conversionService.writeValue(key, keyType, inverse.getOptionalConverter()) - .asString(); - } - - Statement relationshipCreationQuery = CypherGenerator.INSTANCE.prepareSaveOfRelationships(neo4jPersistentEntity, - relationshipDescription, relationshipType, canUseElementId); - return new CreateRelationshipStatementHolder(relationshipCreationQuery, Map.of()); - } - - /** - * Executes all post load methods of the given instance. - * @param entity the entity definition - * @param instance the instance whose post load methods should be executed - * @param type of the entity - * @return the instance - */ - public T invokePostLoad(Neo4jPersistentEntity entity, T instance) { - - getPostLoadMethods(entity).forEach(methodHolder -> methodHolder.invoke(instance)); - return instance; - } - - Set getPostLoadMethods(Neo4jPersistentEntity entity) { - return this.postLoadMethods.computeIfAbsent(entity, Neo4jMappingContext::computePostLoadMethods); - } - - /** - * A builder for creating custom instances of a {@link Neo4jMappingContext}. - * - * @since 6.3.7 - */ - public static final class Builder { - - private Neo4jConversions neo4jConversions; - - private TypeSystem typeSystem; - - @Nullable - private PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider; - - private Builder() { - this(new Neo4jConversions(), null, null); - } - - private Builder(Neo4jConversions neo4jConversions, @Nullable TypeSystem typeSystem, - @Nullable PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider) { - this.neo4jConversions = neo4jConversions; - this.typeSystem = Objects.requireNonNullElseGet(typeSystem, TypeSystem::getDefault); - this.persistentPropertyCharacteristicsProvider = persistentPropertyCharacteristicsProvider; - } - - @SuppressWarnings("HiddenField") - public Builder withNeo4jConversions(Neo4jConversions neo4jConversions) { - this.neo4jConversions = neo4jConversions; - return this; - } - - @SuppressWarnings("HiddenField") - public Builder withPersistentPropertyCharacteristicsProvider( - PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider) { - this.persistentPropertyCharacteristicsProvider = persistentPropertyCharacteristicsProvider; - return this; - } - - @SuppressWarnings("HiddenField") - public Builder withTypeSystem(TypeSystem typeSystem) { - this.typeSystem = Objects.requireNonNullElseGet(typeSystem, TypeSystem::getDefault); - return this; - } - - public Neo4jMappingContext build() { - return new Neo4jMappingContext(this); - } - - } - - static class MethodHolder { - - private final Method method; - - @Nullable - private final Field delegate; - - MethodHolder(Method method, @Nullable Field delegate) { - this.method = method; - this.delegate = delegate; - } - - static Object getInstanceOrDelegate(Object instance, @Nullable Field delegateHolder) { - if (delegateHolder == null) { - return instance; - } - else { - try { - delegateHolder.setAccessible(true); - return delegateHolder.get(instance); - } - catch (IllegalAccessException ex) { - throw new RuntimeException(ex); - } - } - } - - String getName() { - return this.method.getName(); - } - - void invoke(Object instance) { - - this.method.setAccessible(true); - ReflectionUtils.invokeMethod(this.method, getInstanceOrDelegate(instance, this.delegate)); - } - - } - -} diff --git a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/ResourceTest.java b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/ResourceTest.java index 754ac0a3cd5..c503a795a2d 100644 --- a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/ResourceTest.java +++ b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/ResourceTest.java @@ -66,7 +66,7 @@ public void findById() { assertEquals("net.tirasa.connid.bundles.soap.WebServiceConnector", connector.getConnectorName()); assertEquals("net.tirasa.connid.bundles.soap", connector.getBundleName()); - Mapping mapping = resource.getProvisionByAnyType(AnyTypeKind.USER.name()).get().getMapping(); + Mapping mapping = resource.getProvisionByAnyType(AnyTypeKind.USER.name()).orElseThrow().getMapping(); assertFalse(mapping.getItems().isEmpty()); assertTrue(mapping.getItems().stream(). @@ -80,6 +80,12 @@ public void findById() { } } + @Test + public void propagationActions() { + ExternalResource resource = resourceDAO.findById("resource-ldap").orElseThrow(); + assertEquals(2, resource.getPropagationActions().size()); + } + @Test public void findWithOrgUnit() { ExternalResource resource = resourceDAO.findById("resource-ldap-orgunit").orElseThrow(); @@ -110,8 +116,8 @@ public void findAll() { @Test public void getConnObjectKey() { ExternalResource resource = resourceDAO.findById("ws-target-resource-2").orElseThrow(); - assertEquals("fullname", resource.getProvisionByAnyType(AnyTypeKind.USER.name()).get(). - getMapping().getConnObjectKeyItem().get().getIntAttrName()); + assertEquals("fullname", resource.getProvisionByAnyType(AnyTypeKind.USER.name()).orElseThrow(). + getMapping().getConnObjectKeyItem().orElseThrow().getIntAttrName()); } @Test @@ -275,7 +281,8 @@ public void saveWithGroupMappingType() { ExternalResource actual = resourceDAO.save(resource); assertNotNull(actual); - assertEquals(3, actual.getProvisionByAnyType(AnyTypeKind.USER.name()).get().getMapping().getItems().size()); + assertEquals(3, actual.getProvisionByAnyType(AnyTypeKind.USER.name()).orElseThrow().getMapping().getItems(). + size()); } @Test diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java index 89f2cd57d84..f08e06a1c0a 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java @@ -115,7 +115,7 @@ protected static Object maskSensitive(final Object object) { case ConnInstanceTO connInstanceTO -> { ConnInstanceTO clone = SerializationUtils.clone(connInstanceTO); - maskSensitive(connInstanceTO.getConf()); + maskSensitive(clone.getConf()); yield clone; } diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java index 48f2456c841..943da2cc581 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java @@ -134,8 +134,7 @@ public void before(final PropagationTaskInfo taskInfo) { map(groupDAO::findById).flatMap(Optional::stream). filter(group -> group.getResources().contains(taskInfo.getResource())). forEach(group -> { - String groupConnObjectLink = evaluateGroupConnObjectLink( - mapping.getConnObjectLink(), group); + String groupConnObjectLink = evaluateGroupConnObjectLink(mapping.getConnObjectLink(), group); LOG.debug("ConnObjectLink for {} is '{}'", group, groupConnObjectLink); if (StringUtils.isNotBlank(groupConnObjectLink)) { diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DebeziumITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DebeziumITCase.java index d61efc39284..0eb5a2039ee 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DebeziumITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DebeziumITCase.java @@ -98,16 +98,14 @@ public static void debeziumSetup() { ConnInstanceTO connector = SerializationUtils.clone( CONNECTOR_SERVICE.read("01938bdf-7ac6-7149-a103-3ec9e74cc824", null)); - connector.getConf().stream().filter(p -> "bootstrapServers".equals(p.getSchema().getName())).findFirst(). - ifPresent(p -> { - p.getValues().clear(); - p.getValues().add(System.getProperty("KAFKA_BOOTSTRAP_SERVERS")); - }); - connector.getConf().stream().filter(p -> "accountTopic".equals(p.getSchema().getName())).findFirst(). - ifPresent(p -> { - p.getValues().clear(); - p.getValues().add("dbserver1.inventory.customers"); - }); + connector.getConf("bootstrapServers").ifPresent(p -> { + p.getValues().clear(); + p.getValues().add(System.getProperty("KAFKA_BOOTSTRAP_SERVERS")); + }); + connector.getConf("accountTopic").ifPresent(p -> { + p.getValues().clear(); + p.getValues().add("dbserver1.inventory.customers"); + }); connector.getConf().removeIf(p -> "groupTopic".equals(p.getSchema().getName())); CONNECTOR_SERVICE.update(connector); diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java index 65386f704b6..2fa0a14b869 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java @@ -78,7 +78,6 @@ import org.apache.syncope.common.lib.to.TaskTO; import org.apache.syncope.common.lib.to.UserTO; import org.apache.syncope.common.lib.types.AnyTypeKind; -import org.apache.syncope.common.lib.types.AttrSchemaType; import org.apache.syncope.common.lib.types.ExecStatus; import org.apache.syncope.common.lib.types.IdRepoImplementationType; import org.apache.syncope.common.lib.types.ImplementationEngine; @@ -741,40 +740,11 @@ public void issueSYNCOPE1430() throws ParseException { } @Test - public void issueSYNCOPE1473() throws ParseException { - // create a new group schema - PlainSchemaTO schemaTO = new PlainSchemaTO(); - schemaTO.setKey("ldapGroups" + getUUIDString()); - schemaTO.setType(AttrSchemaType.String); - schemaTO.setMultivalue(true); - schemaTO.setReadonly(true); - schemaTO.setAnyTypeClass("minimal user"); - - schemaTO = createSchema(SchemaType.PLAIN, schemaTO); - assertNotNull(schemaTO); - + public void issueSYNCOPE1473() { ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP); UserTO userTO = null; try { - // 1. clone the LDAP resource and add some sensible mappings - Provision provisionGroup = - SerializationUtils.clone(ldap.getProvision(AnyTypeKind.GROUP.name()).orElse(null)); - assertNotNull(provisionGroup); - - Provision provisionUser = - SerializationUtils.clone(ldap.getProvision(AnyTypeKind.USER.name()).orElse(null)); - assertNotNull(provisionUser); - provisionUser.getMapping().getItems().removeIf(item -> "mail".equals(item.getExtAttrName())); - - Item ldapGroups = new Item(); - ldapGroups.setPurpose(MappingPurpose.PROPAGATION); - ldapGroups.setIntAttrName(schemaTO.getKey()); - ldapGroups.setExtAttrName("ldapGroups"); - provisionUser.getMapping().add(ldapGroups); - - ldap.getProvisions().clear(); - ldap.getProvisions().add(provisionUser); - ldap.getProvisions().add(provisionGroup); + // 1. clone the LDAP resource ldap.setKey(RESOURCE_NAME_LDAP + "1473" + getUUIDString()); RESOURCE_SERVICE.create(ldap); @@ -818,8 +788,7 @@ public void issueSYNCOPE1473() throws ParseException { UserUR userUR = new UserUR(); userUR.setKey(userTO.getKey()); - userUR.getMemberships().add( - new MembershipUR.Builder(newGroupTO.getKey()).operation(PatchOperation.ADD_REPLACE).build()); + userUR.getMemberships().add(new MembershipUR.Builder(newGroupTO.getKey()).build()); USER_SERVICE.update(userUR); ConnObject connObject = @@ -830,10 +799,7 @@ public void issueSYNCOPE1473() throws ParseException { } finally { try { RESOURCE_SERVICE.delete(ldap.getKey()); - if (userTO != null) { - USER_SERVICE.delete(userTO.getKey()); - } - SCHEMA_SERVICE.delete(SchemaType.PLAIN, schemaTO.getKey()); + Optional.ofNullable(userTO).map(UserTO::getKey).ifPresent(USER_SERVICE::delete); } catch (Exception ignore) { // ignore } diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java index 3e3ca46122b..ae62a23f223 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java @@ -702,8 +702,7 @@ public void syncTokenWithErrors() { resForTest.setKey("syncTokenWithErrors"); resForTest.setConnector(null); ConnInstanceTO connForTest = SerializationUtils.clone(origConnector); - connForTest.getConf().stream().filter(p -> "password".equals(p.getSchema().getName())).findFirst(). - ifPresent(p -> p.getValues().add(DB_PASSWORD)); + connForTest.getConf("password").ifPresent(p -> p.getValues().add(DB_PASSWORD)); connForTest.setKey(null); connForTest.setDisplayName("For syncTokenWithErrors"); diff --git a/pom.xml b/pom.xml index 867fe5791f2..9063ef30f0a 100644 --- a/pom.xml +++ b/pom.xml @@ -528,7 +528,7 @@ under the License. 11.0.25 40.0.1.Final - 7.2026.7 + 7.2026.8 4.1.14 18-alpine