001 /* 002 * JBoss DNA (http://www.jboss.org/dna) 003 * See the COPYRIGHT.txt file distributed with this work for information 004 * regarding copyright ownership. Some portions may be licensed 005 * to Red Hat, Inc. under one or more contributor license agreements. 006 * See the AUTHORS.txt file in the distribution for a full listing of 007 * individual contributors. 008 * 009 * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA 010 * is licensed to you under the terms of the GNU Lesser General Public License as 011 * published by the Free Software Foundation; either version 2.1 of 012 * the License, or (at your option) any later version. 013 * 014 * JBoss DNA is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 017 * Lesser General Public License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this software; if not, write to the Free 021 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 022 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 023 */ 024 package org.jboss.dna.graph.request; 025 026 import java.util.Collections; 027 import java.util.Map; 028 import org.jboss.dna.common.util.CheckArg; 029 import org.jboss.dna.graph.GraphI18n; 030 import org.jboss.dna.graph.Location; 031 import org.jboss.dna.graph.property.Name; 032 import org.jboss.dna.graph.property.Path; 033 import org.jboss.dna.graph.property.Property; 034 035 /** 036 * Instruction to update the properties on the node at the specified location. 037 * <p> 038 * This request is capable of specifying that certain properties are to have new values and that other properties are to be 039 * removed. The request has a single map of properties keyed by their name. If a property is to be set with new values, the map 040 * will contain an entry with the property keyed by its name. However, if a property is to be removed, the entry will contain the 041 * property name for the key but will have a null entry value. 042 * </p> 043 * <p> 044 * The use of the map also ensures that a single property appears only once in the request (it either has new values or it is to 045 * be removed). 046 * </p> 047 * <p> 048 * Note that the number of values in a property (e.g., {@link Property#size()}, {@link Property#isEmpty()}, 049 * {@link Property#isSingle()}, and {@link Property#isMultiple()}) has no influence on whether the property should be removed. It 050 * is possible for a property to have no values. 051 * </p> 052 * 053 * @author Randall Hauch 054 */ 055 public class UpdatePropertiesRequest extends Request implements ChangeRequest { 056 057 private static final long serialVersionUID = 1L; 058 059 private final Location on; 060 private final String workspaceName; 061 private final Map<Name, Property> properties; 062 private Location actualLocation; 063 064 /** 065 * Create a request to update the properties on the node at the supplied location. 066 * 067 * @param on the location of the node to be read 068 * @param workspaceName the name of the workspace containing the node 069 * @param properties the map of properties (keyed by their name), which is reused without copying 070 * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to update 071 */ 072 public UpdatePropertiesRequest( Location on, 073 String workspaceName, 074 Map<Name, Property> properties ) { 075 CheckArg.isNotNull(on, "on"); 076 CheckArg.isNotEmpty(properties, "properties"); 077 CheckArg.isNotNull(workspaceName, "workspaceName"); 078 this.workspaceName = workspaceName; 079 this.on = on; 080 this.properties = Collections.unmodifiableMap(properties); 081 } 082 083 /** 084 * {@inheritDoc} 085 * 086 * @see org.jboss.dna.graph.request.Request#isReadOnly() 087 */ 088 @Override 089 public boolean isReadOnly() { 090 return false; 091 } 092 093 /** 094 * Get the location defining the node that is to be updated. 095 * 096 * @return the location of the node; never null 097 */ 098 public Location on() { 099 return on; 100 } 101 102 /** 103 * Get the name of the workspace in which the node exists. 104 * 105 * @return the name of the workspace; never null 106 */ 107 public String inWorkspace() { 108 return workspaceName; 109 } 110 111 /** 112 * Get the map of properties for the node, keyed by property name. Any property to be removed will have a map entry with a 113 * null value. 114 * 115 * @return the properties being updated; never null and never empty 116 */ 117 public Map<Name, Property> properties() { 118 return properties; 119 } 120 121 /** 122 * Sets the actual and complete location of the node being updated. This method must be called when processing the request, 123 * and the actual location must have a {@link Location#getPath() path}. 124 * 125 * @param actual the actual location of the node being updated, or null if the {@link #on() current location} should be used 126 * @throws IllegalArgumentException if the actual location does represent the {@link Location#isSame(Location) same location} 127 * as the {@link #on() current location}, or if the actual location does not have a path. 128 */ 129 public void setActualLocationOfNode( Location actual ) { 130 if (!on.isSame(actual)) { // not same if actual is null 131 throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, on)); 132 } 133 assert actual != null; 134 if (!actual.hasPath()) { 135 throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual)); 136 } 137 this.actualLocation = actual; 138 } 139 140 /** 141 * Get the actual location of the node that was updated. 142 * 143 * @return the actual location, or null if the actual location was not set 144 */ 145 public Location getActualLocationOfNode() { 146 return actualLocation; 147 } 148 149 /** 150 * {@inheritDoc} 151 * 152 * @see org.jboss.dna.graph.request.ChangeRequest#changes(java.lang.String, org.jboss.dna.graph.property.Path) 153 */ 154 public boolean changes( String workspace, 155 Path path ) { 156 return this.workspaceName.equals(workspace) && on.hasPath() && on.getPath().isAtOrBelow(path); 157 } 158 159 /** 160 * {@inheritDoc} 161 * 162 * @see java.lang.Object#equals(java.lang.Object) 163 */ 164 @Override 165 public boolean equals( Object obj ) { 166 if (obj == this) return true; 167 if (this.getClass().isInstance(obj)) { 168 UpdatePropertiesRequest that = (UpdatePropertiesRequest)obj; 169 if (!this.on().equals(that.on())) return false; 170 if (!this.properties().equals(that.properties())) return false; 171 if (!this.inWorkspace().equals(that.inWorkspace())) return false; 172 return true; 173 } 174 return false; 175 } 176 177 /** 178 * {@inheritDoc} 179 * 180 * @see org.jboss.dna.graph.request.ChangeRequest#changedLocation() 181 */ 182 public Location changedLocation() { 183 return on; 184 } 185 186 /** 187 * {@inheritDoc} 188 * 189 * @see java.lang.Object#toString() 190 */ 191 @Override 192 public String toString() { 193 return "update properties on " + on() + " in the \"" + workspaceName + "\" workspace to " + properties(); 194 } 195 196 }