1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.layout.impl;
18
19 import java.util.List;
20 import java.util.ArrayList;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.jetspeed.components.portletregistry.PortletRegistry;
25 import org.apache.jetspeed.layout.PortletPlacementException;
26 import org.apache.jetspeed.om.page.Fragment;
27 import org.apache.jetspeed.om.page.Page;
28 /***
29 * NestedFragmentContext
30 *
31 * This object captures the nested position of a fragment
32 * within a page. Given a target fragment and a page,
33 * the target fragment col/row within its parent is
34 * recorded, followed by the target fragment's parent
35 * col/row within its parent, etc.
36 *
37 * The purpose of this object is to support the
38 * create-new-page-on-edit feature. For example, when
39 * a fragment is moved, causing the creation of a new
40 * page, the information captured by this object
41 * allows the copy of the fragment in the new page to
42 * be located.
43 *
44 * @author <a>Steve Milek</a>
45 * @author <a href="mailto:smilek@apache.org">Steve Milek</a>
46 * @version $Id: $
47 */
48 public class NestedFragmentContext
49 {
50 protected static final Log log = LogFactory.getLog( NestedFragmentContext.class );
51 protected static final String eol = System.getProperty( "line.separator" );
52
53 private Fragment targetFragment;
54 private Fragment rootFragment;
55 private Page page;
56 private List fragmentLevels;
57
58 public NestedFragmentContext( Fragment targetFragment, Page page, PortletRegistry registry )
59 throws PortletPlacementException
60 {
61 this.targetFragment = targetFragment;
62 this.page = page;
63 this.rootFragment = page.getRootFragment();
64 init( registry );
65 }
66
67 protected void init( PortletRegistry registry )
68 throws PortletPlacementException
69 {
70 List nestedFragmentLevels = new ArrayList();
71 Fragment nextTarget = targetFragment;
72 Fragment nextParent = null;
73 do
74 {
75 nextParent = NestedFragmentContext.getParentFragmentById( nextTarget.getId(), rootFragment );
76 if ( nextParent != null )
77 {
78 NestedFragmentLevel level = new NestedFragmentLevel( nextTarget, nextParent, registry );
79 nestedFragmentLevels.add( level );
80
81 nextTarget = nextParent;
82 }
83 else
84 {
85 if ( ! nextTarget.getId().equals( rootFragment.getId() ) )
86 {
87 throw new PortletPlacementException( "Cannot determine complete nested structure for fragment " + targetFragment.getId() );
88 }
89 nextTarget = null;
90 }
91 }
92 while ( nextTarget != null );
93 this.fragmentLevels = nestedFragmentLevels;
94 }
95
96 public Fragment getFragmentOnNewPage( Page newPage, PortletRegistry registry )
97 throws PortletPlacementException
98 {
99 Fragment newPageRootFragment = newPage.getRootFragment();
100
101 int depth = fragmentLevels.size();
102
103 Fragment nextFragment = newPageRootFragment;
104 for ( int i = depth -1; i >= 0 ; i-- )
105 {
106 NestedFragmentLevel level = (NestedFragmentLevel)fragmentLevels.get(i);
107 PortletPlacementContextImpl placement = new PortletPlacementContextImpl( newPage, registry, nextFragment );
108 try
109 {
110 nextFragment = placement.getFragmentAtOldCoordinate( new CoordinateImpl( level.getChildCol(), level.getChildRow() ) );
111
112 }
113 catch ( PortletPlacementException ppex )
114 {
115 log.error( "getFragmentOnNewPage failure to locate fragment on new page (index=" + i + ") :" + eol + this.toString() + ( placement != null ? ( eol + placement.dumpFragments(null) ) : "" ) + eol, ppex );
116 throw ppex;
117 }
118 catch ( RuntimeException ex )
119 {
120 log.error( "getFragmentOnNewPage failure to locate fragment on new page (index=" + i + ") :" + eol + this.toString() + ( placement != null ? ( eol + placement.dumpFragments(null) ) : "" ) + eol, ex );
121 throw ex;
122 }
123 if ( nextFragment == null )
124 {
125 throw new PortletPlacementException( "Cannot locate copy of fragment " + targetFragment.getId() + " in the new page structure :" + eol + this.toString() + ( placement != null ? ( eol + placement.dumpFragments(null) ) : "" ));
126 }
127 }
128 return nextFragment;
129 }
130
131 public String toString()
132 {
133 StringBuffer out = new StringBuffer();
134 int depth = fragmentLevels.size();
135 int ldepth = 0;
136 for ( int i = depth -1; i >= 0 ; i-- )
137 {
138 NestedFragmentLevel level = (NestedFragmentLevel)fragmentLevels.get(i);
139 if ( ldepth > 0 )
140 {
141 out.append( eol );
142 for ( int j = 0 ; j < ldepth ; j++ )
143 out.append( " " );
144 }
145 ldepth++;
146 out.append( level.toString() );
147 }
148 return out.toString();
149 }
150
151 class NestedFragmentLevel
152 {
153 private int childRow;
154 private int childCol;
155 private Fragment child;
156 private Fragment parent;
157
158 NestedFragmentLevel( Fragment child, Fragment parent, PortletRegistry registry )
159 throws PortletPlacementException
160 {
161 this.child = child;
162 this.parent = parent;
163 PortletPlacementContextImpl placement = new PortletPlacementContextImpl( page, registry, parent );
164 this.childRow = placement.getFragmentRow( child );
165 this.childCol = placement.getFragmentCol( child );
166 }
167
168 protected int getChildRow()
169 {
170 return this.childRow;
171 }
172 protected int getChildCol()
173 {
174 return this.childCol;
175 }
176 protected Fragment getChild()
177 {
178 return this.child;
179 }
180 protected Fragment getParent()
181 {
182 return this.parent;
183 }
184 public String toString()
185 {
186 return child.getType() + " col=" + childCol + " row=" + childRow + " id=" + child.getId() + " parent-id=" + parent.getId() ;
187 }
188 }
189
190 public static Fragment getParentFragmentById( String id, Fragment parent )
191 {
192
193 if ( id == null )
194 {
195 return null;
196 }
197
198 Fragment matchedParent = null;
199 if( parent != null )
200 {
201
202 List children = parent.getFragments();
203 for( int i = 0, cSize = children.size() ; i < cSize ; i++)
204 {
205 Fragment childFrag = (Fragment)children.get( i );
206 if ( childFrag != null )
207 {
208 if ( id.equals( childFrag.getId() ) )
209 {
210 matchedParent = parent;
211 break;
212 }
213 else
214 {
215 matchedParent = NestedFragmentContext.getParentFragmentById( id, childFrag );
216 if ( matchedParent != null )
217 {
218 break;
219 }
220 }
221 }
222 }
223 }
224 return matchedParent;
225 }
226 }