View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors.
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   * 
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.graph.connector.federation;
25  
26  import java.util.List;
27  import java.util.Map;
28  import net.jcip.annotations.NotThreadSafe;
29  import org.modeshape.graph.Location;
30  import org.modeshape.graph.property.Name;
31  import org.modeshape.graph.property.Property;
32  
33  /**
34   * Information about a node that has been projected into the repository from a source. Each projected node may be followed by a
35   * {@link #next() next} projected node.
36   */
37  @NotThreadSafe
38  abstract class ProjectedNode {
39      private final Location location;
40      private ProjectedNode next;
41  
42      protected ProjectedNode( Location location ) {
43          this.location = location;
44      }
45  
46      public Location location() {
47          return location;
48      }
49  
50      public int size() {
51          return next != null ? next.size() + 1 : 1;
52      }
53  
54      public int numberOfProxies() {
55          int base = isProxy() ? 1 : 0;
56          return next != null ? next.numberOfProxies() + base : base;
57      }
58  
59      public boolean hasNext() {
60          return next != null;
61      }
62  
63      public ProjectedNode next() {
64          return next;
65      }
66  
67      /*package*/void add( ProjectedNode next ) {
68          if (this.next != null) {
69              this.next.add(next);
70          } else {
71              this.next = next;
72          }
73      }
74  
75      public abstract boolean isPlaceholder();
76  
77      public abstract boolean isProxy();
78  
79      public abstract PlaceholderNode asPlaceholder();
80  
81      public abstract ProxyNode asProxy();
82  }
83  
84  @NotThreadSafe
85  class PlaceholderNode extends ProjectedNode {
86      private final Map<Name, Property> properties;
87      private final List<ProjectedNode> children;
88  
89      protected PlaceholderNode( Location location,
90                                 Map<Name, Property> properties,
91                                 List<ProjectedNode> children ) {
92          super(location);
93          this.properties = properties;
94          this.children = children;
95      }
96  
97      public List<ProjectedNode> children() {
98          return children;
99      }
100 
101     public Map<Name, Property> properties() {
102         return properties;
103     }
104 
105     @Override
106     public boolean isPlaceholder() {
107         return true;
108     }
109 
110     @Override
111     public PlaceholderNode asPlaceholder() {
112         return this;
113     }
114 
115     @Override
116     public boolean isProxy() {
117         return false;
118     }
119 
120     @Override
121     public ProxyNode asProxy() {
122         return null;
123     }
124 
125     @Override
126     public String toString() {
127         return "Placeholder " + location();
128     }
129 }
130 
131 @NotThreadSafe
132 class ProxyNode extends ProjectedNode {
133     private final Projection projection;
134     private final boolean sameLocationAsOriginal;
135     private final Location federatedLocation;
136 
137     protected ProxyNode( Projection projection,
138                          Location locationInSource,
139                          Location locationInFederated ) {
140         super(locationInSource);
141         this.projection = projection;
142         this.federatedLocation = locationInFederated;
143         this.sameLocationAsOriginal = locationInSource.isSame(locationInFederated);
144     }
145 
146     protected ProxyNode( Projection projection,
147                          Location locationInSource,
148                          Location locationInFederated,
149                          boolean isSameLocation ) {
150         super(locationInSource);
151         this.projection = projection;
152         this.federatedLocation = locationInFederated;
153         this.sameLocationAsOriginal = isSameLocation;
154     }
155 
156     public String source() {
157         return projection.getSourceName();
158     }
159 
160     public String workspaceName() {
161         return projection.getWorkspaceName();
162     }
163 
164     /*package*/Projection projection() {
165         return projection;
166     }
167 
168     public Location federatedLocation() {
169         return federatedLocation;
170     }
171 
172     @Override
173     public boolean isPlaceholder() {
174         return false;
175     }
176 
177     @Override
178     public PlaceholderNode asPlaceholder() {
179         return null;
180     }
181 
182     @Override
183     public boolean isProxy() {
184         return true;
185     }
186 
187     @Override
188     public ProxyNode asProxy() {
189         return this;
190     }
191 
192     /**
193      * Determine whether this projected node is a top-level node in the source projected into the federated repository.
194      * 
195      * @return true if the projected node is a top-level node in the source, or false otherwise
196      */
197     public boolean isTopLevelNode() {
198         return federatedLocation != null && federatedLocation.hasPath() && projection.isTopLevelPath(federatedLocation.getPath());
199     }
200 
201     public boolean isSameLocationAsOriginal() {
202         return this.sameLocationAsOriginal;
203     }
204 
205     @Override
206     public String toString() {
207         return "Proxy for " + federatedLocation() + " projected from " + location() + " in workspace \"" + workspaceName()
208                + "\" in \"" + source() + "\"";
209     }
210 }