001 /*
002 * JBoss, Home of Professional Open Source.
003 * Copyright 2008, Red Hat Middleware LLC, and individual contributors
004 * as indicated by the @author tags. See the copyright.txt file in the
005 * distribution for a full listing of individual contributors.
006 *
007 * This is free software; you can redistribute it and/or modify it
008 * under the terms of the GNU Lesser General Public License as
009 * published by the Free Software Foundation; either version 2.1 of
010 * the License, or (at your option) any later version.
011 *
012 * This software is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this software; if not, write to the Free
019 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021 */
022 package org.jboss.dna.connector.federation.merge.strategy;
023
024 import java.util.Iterator;
025 import java.util.List;
026 import java.util.Map;
027 import java.util.UUID;
028 import net.jcip.annotations.ThreadSafe;
029 import org.jboss.dna.connector.federation.contribution.Contribution;
030 import org.jboss.dna.connector.federation.merge.FederatedNode;
031 import org.jboss.dna.connector.federation.merge.MergePlan;
032 import org.jboss.dna.graph.DnaLexicon;
033 import org.jboss.dna.graph.ExecutionContext;
034 import org.jboss.dna.graph.properties.Name;
035 import org.jboss.dna.graph.properties.Property;
036 import org.jboss.dna.graph.properties.UuidFactory;
037 import org.jboss.dna.graph.properties.ValueFormatException;
038 import org.jboss.dna.graph.properties.Path.Segment;
039
040 /**
041 * A merge strategy that is optimized for merging when there is a single contribution.
042 *
043 * @author Randall Hauch
044 */
045 @ThreadSafe
046 public class OneContributionMergeStrategy implements MergeStrategy {
047
048 public static final boolean DEFAULT_REUSE_UUID_FROM_CONTRIBUTION = true;
049
050 private boolean useUuidFromContribution = DEFAULT_REUSE_UUID_FROM_CONTRIBUTION;
051
052 /**
053 * @return reuseUuidFromContribution
054 */
055 public boolean isContributionUuidUsedForFederatedNode() {
056 return useUuidFromContribution;
057 }
058
059 /**
060 * @param useUuidFromContribution Sets useUuidFromContribution to the specified value.
061 */
062 public void setContributionUuidUsedForFederatedNode( boolean useUuidFromContribution ) {
063 this.useUuidFromContribution = useUuidFromContribution;
064 }
065
066 /**
067 * {@inheritDoc}
068 * <p>
069 * This method only uses the one and only one non-null {@link Contribution} in the <code>contributions</code>.
070 * </p>
071 *
072 * @see org.jboss.dna.connector.federation.merge.strategy.MergeStrategy#merge(org.jboss.dna.connector.federation.merge.FederatedNode,
073 * java.util.List, org.jboss.dna.graph.ExecutionContext)
074 */
075 public void merge( FederatedNode federatedNode,
076 List<Contribution> contributions,
077 ExecutionContext context ) {
078 assert federatedNode != null;
079 assert context != null;
080 assert contributions != null;
081 assert contributions.size() > 0;
082 Contribution contribution = contributions.get(0);
083 assert contribution != null;
084 final boolean findUuid = isContributionUuidUsedForFederatedNode();
085 // Copy the children ...
086 List<Segment> children = federatedNode.getChildren();
087 children.clear();
088 Iterator<Segment> childIterator = contribution.getChildren();
089 while (childIterator.hasNext()) {
090 Segment child = childIterator.next();
091 children.add(child);
092 }
093 // Copy the properties ...
094 Map<Name, Property> properties = federatedNode.getPropertiesByName();
095 properties.clear();
096 UUID uuid = null;
097 UuidFactory uuidFactory = null;
098 Iterator<Property> propertyIterator = contribution.getProperties();
099 while (propertyIterator.hasNext()) {
100 Property property = propertyIterator.next();
101 if (findUuid && uuid == null && property.getName().getLocalName().equals("uuid")) {
102 if (property.isSingle()) {
103 if (uuidFactory == null) uuidFactory = context.getValueFactories().getUuidFactory();
104 try {
105 uuid = uuidFactory.create(property.getValues().next());
106 } catch (ValueFormatException e) {
107 // Ignore conversion exceptions
108 }
109 }
110 } else {
111 properties.put(property.getName(), property);
112 }
113 }
114 // If we found a single "uuid" property whose value is a valid UUID ..
115 if (uuid != null) {
116 // then set the UUID on the federated node ...
117 federatedNode.setUuid(uuid);
118 }
119 // Set the UUID as a property ...
120 Property uuidProperty = context.getPropertyFactory().create(DnaLexicon.UUID, federatedNode.getUuid());
121 properties.put(uuidProperty.getName(), uuidProperty);
122
123 // Assign the merge plan ...
124 MergePlan mergePlan = MergePlan.create(contributions);
125 federatedNode.setMergePlan(mergePlan);
126 }
127
128 }