001/*
002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $
018 */
019
020package org.nuxeo.ecm.directory;
021
022import java.util.List;
023
024import org.nuxeo.common.xmap.annotation.XNode;
025import org.nuxeo.common.xmap.annotation.XObject;
026
027/**
028 * Reference that uses the matching reference of the target directory to actually do the job.
029 *
030 * @author ogrisel
031 */
032@XObject(value = "inverseReference")
033public class InverseReference extends AbstractReference {
034
035    /**
036     * Indicates if the target directory can be updated from the current reference
037     *
038     * @since 5.7
039     */
040    protected boolean readOnly = false;
041
042    @XNode("@dualReferenceField")
043    protected String dualReferenceName;
044
045    protected Reference dualReference;
046
047    @XNode("@field")
048    public void setFieldName(String fieldName) {
049        this.fieldName = fieldName;
050    }
051
052    @Override
053    @XNode("@directory")
054    public void setTargetDirectoryName(String targetDirectoryName) {
055        this.targetDirectoryName = targetDirectoryName;
056    }
057
058    @XNode("@readOnly")
059    public void setReadOnly(boolean readOnly) {
060        this.readOnly = readOnly;
061    }
062
063    public boolean isReadOnly() {
064        return readOnly;
065    }
066
067    protected void checkDualReference() throws DirectoryException {
068        if (dualReference == null) {
069            List<Reference> references = getTargetDirectory().getReferences(dualReferenceName);
070            if (references.size() == 0) {
071                dualReference = null;
072            } else if (references.size() == 1) {
073                dualReference = references.get(0);
074            } else {
075                for (Reference ref : references) {
076                    if (ref instanceof InverseReference) {
077                        continue;
078                    } else if (sourceDirectoryName.equals(ref.getTargetDirectory().getName())
079                            && targetDirectoryName.equals(ref.getSourceDirectory().getName())) {
080                        if (dualReference == null) {
081                            dualReference = ref;
082                        } else {
083                            throw new DirectoryException(
084                                    "More than one reference: could not find reference " + dualReferenceName);
085                        }
086                    }
087                }
088            }
089        }
090        if (dualReference == null) {
091            throw new DirectoryException("could not find reference " + dualReferenceName);
092        }
093        if (dualReference instanceof InverseReference) {
094            throw new DirectoryException(String.format("InverseReference %s cannot refer to InverseReference %s",
095                    getFieldName(), dualReferenceName));
096        }
097    }
098
099    public void addLinks(String sourceId, List<String> targetIds) throws DirectoryException {
100        if (readOnly) {
101            return;
102        }
103        checkDualReference();
104        dualReference.addLinks(targetIds, sourceId);
105    }
106
107    public void addLinks(List<String> sourceIds, String targetId) throws DirectoryException {
108        if (readOnly) {
109            return;
110        }
111        checkDualReference();
112        dualReference.addLinks(targetId, sourceIds);
113    }
114
115    public void removeLinksForTarget(String targetId) throws DirectoryException {
116        if (readOnly) {
117            return;
118        }
119        checkDualReference();
120        dualReference.removeLinksForSource(targetId);
121    }
122
123    public void removeLinksForSource(String sourceId) throws DirectoryException {
124        if (readOnly) {
125            return;
126        }
127        checkDualReference();
128        dualReference.removeLinksForTarget(sourceId);
129    }
130
131    public List<String> getSourceIdsForTarget(String targetId) throws DirectoryException {
132        checkDualReference();
133        return dualReference.getTargetIdsForSource(targetId);
134    }
135
136    public List<String> getTargetIdsForSource(String sourceId) throws DirectoryException {
137        checkDualReference();
138        return dualReference.getSourceIdsForTarget(sourceId);
139    }
140
141    public void setTargetIdsForSource(String sourceId, List<String> targetIds) throws DirectoryException {
142        if (readOnly) {
143            return;
144        }
145        checkDualReference();
146        dualReference.setSourceIdsForTarget(sourceId, targetIds);
147    }
148
149    public void setSourceIdsForTarget(String targetId, List<String> sourceIds) throws DirectoryException {
150        if (readOnly) {
151            return;
152        }
153        checkDualReference();
154        dualReference.setTargetIdsForSource(targetId, sourceIds);
155    }
156
157    @Override
158    protected AbstractReference newInstance() {
159        return new InverseReference();
160    }
161
162    public InverseReference clone() {
163        InverseReference clone = (InverseReference) super.clone();
164        clone.dualReferenceName = dualReferenceName;
165        return clone;
166    }
167}