001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 */
019package org.apache.causeway.persistence.jdo.integration.metamodel;
020
021import java.text.MessageFormat;
022import java.util.List;
023import java.util.function.Predicate;
024import java.util.stream.Collectors;
025
026import javax.jdo.annotations.PrimaryKey;
027
028import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
029import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
030import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
031import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation;
032import org.apache.causeway.persistence.jdo.provider.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet;
033
034public final class JdoPropertyUtils {
035
036    private JdoPropertyUtils() {
037    }
038
039    /**
040     * Searches for the property annotated with {@link PrimaryKey}.
041     * <p>
042     * Returns the {@link OneToOneAssociation} if there is precisely one; else
043     * <tt>null</tt>.
044     *
045     * @see JdoPrimaryKeyPropertyPredicate
046     */
047    public static OneToOneAssociation getPrimaryKeyPropertyFor(final ObjectSpecification objectSpec) {
048        return getPropertyFor(objectSpec, "@PrimaryKey", new JdoPrimaryKeyPropertyPredicate());
049    }
050
051    public static boolean hasPrimaryKeyProperty(final ObjectSpecification objectSpec) {
052        return getPrimaryKeyPropertyFor(objectSpec) != null;
053    }
054
055    private static OneToOneAssociation getPropertyFor(
056            final ObjectSpecification objSpec,
057            final String annotationName,
058            final Predicate<ObjectAssociation> predicate) {
059
060        if (objSpec == null || !objSpec.containsFacet(JdoPersistenceCapableFacet.class)) {
061            return null;
062        }
063
064
065        final List<ObjectAssociation> propertyList = objSpec
066                .streamAssociations(MixedIn.EXCLUDED)
067                .filter(predicate)
068                .limit(2)
069                .collect(Collectors.toList());
070
071        if (propertyList.size() == 0) {
072            return JdoPropertyUtils.getPropertyFor(objSpec.superclass(), annotationName, predicate);
073        }
074        if (propertyList.size() > 1) {
075            throw new IllegalStateException(MessageFormat.format("Shouldn''t have more than one property annotated with {0} (''{1}'')", annotationName, objSpec.getFullIdentifier()));
076        }
077        return (OneToOneAssociation) propertyList.get(0);
078    }
079
080}