001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.layout.impl;
018:
019: import java.util.List;
020: import java.util.ArrayList;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.apache.jetspeed.components.portletregistry.PortletRegistry;
025: import org.apache.jetspeed.layout.PortletPlacementException;
026: import org.apache.jetspeed.om.page.Fragment;
027: import org.apache.jetspeed.om.page.Page;
028:
029: /**
030: * NestedFragmentContext
031: *
032: * This object captures the nested position of a fragment
033: * within a page. Given a target fragment and a page,
034: * the target fragment col/row within its parent is
035: * recorded, followed by the target fragment's parent
036: * col/row within its parent, etc.
037: *
038: * The purpose of this object is to support the
039: * create-new-page-on-edit feature. For example, when
040: * a fragment is moved, causing the creation of a new
041: * page, the information captured by this object
042: * allows the copy of the fragment in the new page to
043: * be located.
044: *
045: * @author <a>Steve Milek</a>
046: * @author <a href="mailto:smilek@apache.org">Steve Milek</a>
047: * @version $Id: $
048: */
049: public class NestedFragmentContext {
050: protected static final Log log = LogFactory
051: .getLog(NestedFragmentContext.class);
052: protected static final String eol = System
053: .getProperty("line.separator");
054:
055: private Fragment targetFragment;
056: private Fragment rootFragment;
057: private Page page;
058: private List fragmentLevels;
059:
060: public NestedFragmentContext(Fragment targetFragment, Page page,
061: PortletRegistry registry) throws PortletPlacementException {
062: this .targetFragment = targetFragment;
063: this .page = page;
064: this .rootFragment = page.getRootFragment();
065: init(registry);
066: }
067:
068: protected void init(PortletRegistry registry)
069: throws PortletPlacementException {
070: List nestedFragmentLevels = new ArrayList();
071: Fragment nextTarget = targetFragment;
072: Fragment nextParent = null;
073: do {
074: nextParent = NestedFragmentContext.getParentFragmentById(
075: nextTarget.getId(), rootFragment);
076: if (nextParent != null) {
077: NestedFragmentLevel level = new NestedFragmentLevel(
078: nextTarget, nextParent, registry);
079: nestedFragmentLevels.add(level);
080:
081: nextTarget = nextParent;
082: } else {
083: if (!nextTarget.getId().equals(rootFragment.getId())) {
084: throw new PortletPlacementException(
085: "Cannot determine complete nested structure for fragment "
086: + targetFragment.getId());
087: }
088: nextTarget = null;
089: }
090: } while (nextTarget != null);
091: this .fragmentLevels = nestedFragmentLevels;
092: }
093:
094: public Fragment getFragmentOnNewPage(Page newPage,
095: PortletRegistry registry) throws PortletPlacementException {
096: Fragment newPageRootFragment = newPage.getRootFragment();
097:
098: int depth = fragmentLevels.size();
099:
100: Fragment nextFragment = newPageRootFragment;
101: for (int i = depth - 1; i >= 0; i--) {
102: NestedFragmentLevel level = (NestedFragmentLevel) fragmentLevels
103: .get(i);
104: PortletPlacementContextImpl placement = new PortletPlacementContextImpl(
105: newPage, registry, nextFragment);
106: try {
107: nextFragment = placement
108: .getFragmentAtOldCoordinate(new CoordinateImpl(
109: level.getChildCol(), level
110: .getChildRow()));
111:
112: } catch (PortletPlacementException ppex) {
113: log.error(
114: "getFragmentOnNewPage failure to locate fragment on new page (index="
115: + i
116: + ") :"
117: + eol
118: + this .toString()
119: + (placement != null ? (eol + placement
120: .dumpFragments(null)) : "")
121: + eol, ppex);
122: throw ppex;
123: } catch (RuntimeException ex) {
124: log.error(
125: "getFragmentOnNewPage failure to locate fragment on new page (index="
126: + i
127: + ") :"
128: + eol
129: + this .toString()
130: + (placement != null ? (eol + placement
131: .dumpFragments(null)) : "")
132: + eol, ex);
133: throw ex;
134: }
135: if (nextFragment == null) {
136: throw new PortletPlacementException(
137: "Cannot locate copy of fragment "
138: + targetFragment.getId()
139: + " in the new page structure :"
140: + eol
141: + this .toString()
142: + (placement != null ? (eol + placement
143: .dumpFragments(null)) : ""));
144: }
145: }
146: return nextFragment;
147: }
148:
149: public String toString() {
150: StringBuffer out = new StringBuffer();
151: int depth = fragmentLevels.size();
152: int ldepth = 0;
153: for (int i = depth - 1; i >= 0; i--) {
154: NestedFragmentLevel level = (NestedFragmentLevel) fragmentLevels
155: .get(i);
156: if (ldepth > 0) {
157: out.append(eol);
158: for (int j = 0; j < ldepth; j++)
159: out.append(" ");
160: }
161: ldepth++;
162: out.append(level.toString());
163: }
164: return out.toString();
165: }
166:
167: class NestedFragmentLevel {
168: private int childRow;
169: private int childCol;
170: private Fragment child;
171: private Fragment parent;
172:
173: NestedFragmentLevel(Fragment child, Fragment parent,
174: PortletRegistry registry)
175: throws PortletPlacementException {
176: this .child = child;
177: this .parent = parent;
178: PortletPlacementContextImpl placement = new PortletPlacementContextImpl(
179: page, registry, parent);
180: this .childRow = placement.getFragmentRow(child);
181: this .childCol = placement.getFragmentCol(child);
182: }
183:
184: protected int getChildRow() {
185: return this .childRow;
186: }
187:
188: protected int getChildCol() {
189: return this .childCol;
190: }
191:
192: protected Fragment getChild() {
193: return this .child;
194: }
195:
196: protected Fragment getParent() {
197: return this .parent;
198: }
199:
200: public String toString() {
201: return child.getType() + " col=" + childCol + " row="
202: + childRow + " id=" + child.getId() + " parent-id="
203: + parent.getId();
204: }
205: }
206:
207: public static Fragment getParentFragmentById(String id,
208: Fragment parent) {
209: // find fragment by id, tracking fragment parent
210: if (id == null) {
211: return null;
212: }
213:
214: Fragment matchedParent = null;
215: if (parent != null) {
216: // process the children
217: List children = parent.getFragments();
218: for (int i = 0, cSize = children.size(); i < cSize; i++) {
219: Fragment childFrag = (Fragment) children.get(i);
220: if (childFrag != null) {
221: if (id.equals(childFrag.getId())) {
222: matchedParent = parent;
223: break;
224: } else {
225: matchedParent = NestedFragmentContext
226: .getParentFragmentById(id, childFrag);
227: if (matchedParent != null) {
228: break;
229: }
230: }
231: }
232: }
233: }
234: return matchedParent;
235: }
236: }
|