/** * Copyright 2012 Universitat Pompeu Fabra. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * */ package org.onexus.collection.api.utils; import org.onexus.collection.api.Collection; import org.onexus.collection.api.Field; import org.onexus.collection.api.Link; import org.onexus.resource.api.ORI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public final class LinkUtils { private final static String FIELDS_SEPARATOR = "=="; private LinkUtils() { } public static List<FieldLink> getLinkFields(ORI parentURI, Collection a, Collection b) { return getLinkFields(parentURI, a, b, Collections.EMPTY_LIST); } public static List<FieldLink> getLinkFields(ORI parentURI, Collection a, Collection b, List<ORI> fixedCollections) { List<FieldLink> fieldLinks = new ArrayList<FieldLink>(); List<Link> linksA = a.getLinks(); List<Link> linksB = b.getLinks(); if (linksA == null) { linksA = Collections.EMPTY_LIST; } if (linksB == null) { linksB = Collections.EMPTY_LIST; } // Case 1: A has a direct link to B Map<String, FieldLink> fieldToLink = new HashMap<String, FieldLink>(); for (Link link : linksA) { ORI linkCollection = link.getCollection().toAbsolute(a.getORI()); if (linkCollection.equals(b.getORI())) { for (String field : link.getFields()) { String fromField = getFromFieldName(field); String toField = getToFieldName(field); fieldToLink.put(fromField, new FieldLink(a.getORI(), fromField, b.getORI(), toField)); } } else { if (fixedCollections.contains(linkCollection)) { for (String field : link.getFields()) { String fromField = getFromFieldName(field); String toField = getToFieldName(field); fieldToLink.put(fromField, new FieldLink(a.getORI(), fromField, linkCollection, toField)); } } } } // Case 1b: B has a direct link to A for (Link link : linksB) { if (link.getCollection().toAbsolute(b.getORI()).equals(a.getORI())) { for (String field : link.getFields()) { String fromField = getFromFieldName(field); String toField = getToFieldName(field); fieldToLink.put(toField, new FieldLink(b.getORI(), fromField, a.getORI(), toField)); } } } // Check that all A primary keys are linked if (!fieldToLink.isEmpty() && areAllPrimaryKeyLinked(a.getFields(), fieldToLink)) { fieldLinks.addAll(fieldToLink.values()); return fieldLinks; } // Case 2: All the primary fields of A has a link to collections linked // by B int totalPrimaryKeyFields = 0; List<FieldLink> primaryKeyLinks = new ArrayList<FieldLink>(); for (Field field : a.getFields()) { if (field.isPrimaryKey() != null && field.isPrimaryKey()) { totalPrimaryKeyFields++; // The links that link to this field List<Link> keyLinks = new ArrayList<Link>(); for (Link link : linksA) { for (String fieldName : link.getFields()) { String fromField = getFromFieldName(fieldName); if (fromField.equals(field.getId())) { keyLinks.add(link); } } } // Look if there is any match with B links for (Link linkB : linksB) { for (Link linkA : keyLinks) { ORI linkBCollection = linkB.getCollection().toAbsolute(parentURI); ORI linkACollection = linkA.getCollection().toAbsolute(parentURI); if (linkBCollection.equals(linkACollection)) { // Try to match the field links for (String fieldLinkA : linkA.getFields()) { String toFieldA = getToFieldName(fieldLinkA); for (String fieldLinkB : linkB.getFields()) { String toFieldB = getToFieldName(fieldLinkB); if (toFieldA.equals(toFieldB)) { String fromFieldA = getFromFieldName(fieldLinkA); String fromFieldB = getFromFieldName(fieldLinkB); primaryKeyLinks.add(new FieldLink( a.getORI(), fromFieldA, b .getORI(), fromFieldB)); } } } } } } } } if (totalPrimaryKeyFields == primaryKeyLinks.size()) { fieldLinks.addAll(primaryKeyLinks); } return fieldLinks; } private static boolean areAllPrimaryKeyLinked(List<Field> fields, Map<String, FieldLink> fieldToLink) { boolean allKeyLinked = false; if (fields != null) { for (Field field : fields) { if (field.isPrimaryKey() != null && field.isPrimaryKey()) { allKeyLinked = true; if (!fieldToLink.containsKey(field.getId())) { allKeyLinked = false; break; } } } } return allKeyLinked; } public static String getToFieldName(String fieldLink) { String values[] = fieldLink.split(FIELDS_SEPARATOR); return values.length == 2 ? values[1].trim() : values[0].trim(); } public static String getFromFieldName(String fieldLink) { String values[] = fieldLink.split(FIELDS_SEPARATOR); return values[0].trim(); } }