| /******************************************************************************* |
| * Copyright (c) 2003, 2004 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.j2ee.internal.java.codegen; |
| |
| |
| |
| import org.eclipse.jdt.core.IMember; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.jdom.IDOMField; |
| import org.eclipse.jdt.core.jdom.IDOMMember; |
| import org.eclipse.jdt.core.jdom.IDOMMethod; |
| import org.eclipse.jdt.core.jdom.IDOMType; |
| |
| /** |
| * This merge strategy abstract base class implements some of the {@link IJavaMergeStrategy}api and |
| * provides infrastructure for subclass concrete implementations. |
| * |
| * @see IJavaMergeStrategy |
| */ |
| public abstract class JavaMergeStrategy implements IJavaMergeStrategy { |
| private boolean fDefaultPreserveNonCollisionOldMembers = false; |
| private boolean fDefaultIncrementalPreserveCollision = false; |
| protected static final String DEFAULT_GENERATED_MEMBER_FLAG = "@generated";//$NON-NLS-1$ |
| protected static final String DEFAULT_USER_CODE_BEGIN = "// user code begin";//$NON-NLS-1$ |
| protected static final String DEFAULT_USER_CODE_BEGIN_TEMPLATE = DEFAULT_USER_CODE_BEGIN + " {%0}";//$NON-NLS-1$ |
| protected static final String DEFAULT_USER_CODE_END = "// user code end";//$NON-NLS-1$ |
| |
| /** |
| * JavaMergeStrategy default constructor. |
| */ |
| public JavaMergeStrategy() { |
| super(); |
| } |
| |
| /** |
| * The default default field merglet is {@link JavaFieldMerglet}. |
| * |
| * @see IJavaMergeStrategy |
| */ |
| public IJavaMerglet createDefaultFieldMerglet() { |
| return new JavaFieldMerglet(this); |
| } |
| |
| /** |
| * The default default method merglet is {@link JavaMethodMerglet}. |
| * |
| * @see IJavaMergeStrategy |
| */ |
| public IJavaMerglet createDefaultMethodMerglet() { |
| return new JavaMethodMerglet(this); |
| } |
| |
| /** |
| * The default default type merglet is {@link JavaTypeMerglet}. |
| * |
| * @see IJavaMergeStrategy |
| */ |
| public IJavaMerglet createDefaultTypeMerglet() { |
| return new JavaTypeMerglet(this); |
| } |
| |
| /** |
| * Creates the merge results object from the history object. Subclasses would want to override |
| * if they have a specialization of MergeResults and/or the history descriptor. |
| */ |
| protected MergeResults createInitialMergeResults(JavaMemberHistoryDescriptor histDesc) { |
| MergeResults mr = new MergeResults(); |
| mr.setDeleteOnly(histDesc.isDeleteOnly()); |
| mr.setOldMember(histDesc.getOldMember()); |
| mr.setCollisionMember(histDesc.getCollisionMember()); |
| return mr; |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public String getGeneratedMemberTag() { |
| return DEFAULT_GENERATED_MEMBER_FLAG; |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public String getUserCodeBegin() { |
| return DEFAULT_USER_CODE_BEGIN; |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public String getUserCodeBeginTemplate() { |
| return DEFAULT_USER_CODE_BEGIN_TEMPLATE; |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public String getUserCodeEnd() { |
| return DEFAULT_USER_CODE_END; |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public boolean isDefaultIncrementalPreserveCollision() { |
| return fDefaultIncrementalPreserveCollision; |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public boolean isDefaultPreserveNonCollisionOldMembers() { |
| return fDefaultPreserveNonCollisionOldMembers; |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public MergeResults merge(JavaMemberHistoryDescriptor histDesc, IDOMField newField) throws MergeException { |
| return merge(histDesc, newField, createDefaultFieldMerglet()); |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public MergeResults merge(JavaMemberHistoryDescriptor histDesc, IDOMMember newMember, IJavaMerglet merglet) throws MergeException { |
| // Set up our results and get the old member for tests. |
| MergeResults mr = createInitialMergeResults(histDesc); |
| |
| // If this is delete only, we only need to check the old member. |
| if (mr.isDeleteOnly()) |
| mergeForDeleteOnly(mr, merglet); |
| else |
| mergeForGenerate(mr, newMember, merglet); |
| |
| return mr; |
| } |
| |
| /** |
| * @see IJavaMergeStrategy The default strategy only generates the type if it does not exist or |
| * the old member was marked generated. It doesn't generate if the old and new are exactly |
| * the same either. |
| */ |
| public MergeResults merge(JavaMemberHistoryDescriptor histDesc, IDOMType newType) throws MergeException { |
| return merge(histDesc, newType, createDefaultTypeMerglet()); |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public MergeResults merge(JavaMethodHistoryDescriptor histDesc, IDOMMethod newMethod) throws MergeException { |
| return merge(histDesc, newMethod, createDefaultMethodMerglet()); |
| } |
| |
| /** |
| * {@link JavaMergeStrategy#merge(JavaMemberHistoryDescriptor, IDOMMember, IJavaMerglet)}uses |
| * this method for merging if the member history descriptor (see |
| * {@link JavaMemberHistoryDescriptor}) indicated that the only action expected is a delete of |
| * the old member. |
| * <p> |
| * This method uses {@link IJavaMerglet#validateForDeleteOnly(MergeResults)}to decide of the |
| * delete only generation is allowed. If the delete is disallowed, |
| * {@link MergeResults#isGenerate()}is set to false. |
| * |
| * @exception org.eclipse.jst.j2ee.internal.internal.internal.java.codegen.MergeException |
| */ |
| protected void mergeForDeleteOnly(MergeResults mr, IJavaMerglet merglet) throws MergeException { |
| if (mr.getOldMember() != null) { |
| mr.setGenerate(merglet.validateForDeleteOnly(mr)); |
| } else { |
| // No need to delete a member that is not there. |
| mr.setGenerate(false); |
| } |
| } |
| |
| /** |
| * {@link JavaMergeStrategy#merge(JavaMemberHistoryDescriptor, IDOMMember, IJavaMerglet)}uses |
| * this method for merging if the member history descriptor (see |
| * {@link JavaMemberHistoryDescriptor}) did <b>not </b> indicate that the only action expected |
| * is a delete of the old member. |
| * <p> |
| * Checks that we need to generate and that we can generate. Also sets up for needed deletions. |
| * Uses {@link IJavaMerglet#validateCollision(MergeResults)}, |
| * {@link IJavaMerglet#isPreserveNonCollisionOldMembers()}, |
| * {@link IJavaMerglet#validateForDelete(MergeResults)}, |
| * {@link IJavaMerglet#isIncrementalPreserveCollision()}and |
| * {@link IJavaMerglet#merge(MergeResults, IDOMMember)}. |
| * |
| * @exception org.eclipse.jst.j2ee.internal.internal.internal.java.codegen.MergeException |
| */ |
| protected void mergeForGenerate(MergeResults mr, IDOMMember newMember, IJavaMerglet merglet) throws MergeException { |
| // Check for collisions that cause us not to want to generate the new member. |
| boolean needToGenerate = merglet.validateCollision(mr); |
| |
| // If the old member is not null and is different |
| // than the collision member and the merglet does not |
| // necessarily want to preserve old non collision members, |
| // we need to make sure it is okay to delete it. |
| boolean okayToDeleteOldMember = false; |
| if ((mr.getOldMember() != null) && (mr.getOldMember() != mr.getCollisionMember()) && (!merglet.isPreserveNonCollisionOldMembers())) |
| okayToDeleteOldMember = merglet.validateForDelete(mr); |
| |
| // If we collided above, we do not need to generate. |
| if (needToGenerate) { |
| // At this point we think we are generating a member, however |
| // the merglet could decide the generation is not needed because |
| // the result is the same as the collision member. |
| // Also need to consider incremental collision replacement. |
| if (!isBatchGeneration() && merglet.isIncrementalPreserveCollision() && (mr.getCollisionMember() != null)) |
| needToGenerate = false; |
| else |
| needToGenerate = merglet.merge(mr, newMember); |
| } |
| |
| // If the merglet decided to generate the new member... |
| if (needToGenerate) { |
| // We will generate the new member. If it is not |
| // okay to delete the old member, clear the old |
| // member out because we want to leave it. |
| if (!okayToDeleteOldMember) |
| mr.setOldMember(null); |
| } else { |
| // If there is an old member that is okay to delete, revert to delete only. |
| if (okayToDeleteOldMember) |
| mr.setDeleteOnly(true); |
| else |
| mr.setGenerate(false); |
| } |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public void setDefaultIncrementalPreserveCollision(boolean newDefaultIncrementalPreserveCollision) { |
| fDefaultIncrementalPreserveCollision = newDefaultIncrementalPreserveCollision; |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public void setDefaultPreserveNonCollisionOldMembers(boolean newDefaultPreserveNonCollisionOldMembers) { |
| fDefaultPreserveNonCollisionOldMembers = newDefaultPreserveNonCollisionOldMembers; |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public boolean wasGenerated(String source, int endCheckIndex) { |
| if (source == null) |
| return true; |
| |
| boolean foundGeneratedFlag = false; |
| if (endCheckIndex <= 0) |
| foundGeneratedFlag = (source.indexOf(getGeneratedMemberTag()) >= 0); |
| else |
| foundGeneratedFlag = (source.lastIndexOf(getGeneratedMemberTag(), endCheckIndex) >= 0); |
| return foundGeneratedFlag; |
| } |
| |
| /** |
| * @see IJavaMergeStrategy |
| */ |
| public boolean wasGenerated(IMember member) throws MergeException { |
| if ((member == null) || (!member.exists())) |
| return true; |
| |
| boolean foundGeneratedFlag = false; |
| try { |
| int endCheckIndex = member.getNameRange().getOffset() - member.getSourceRange().getOffset(); |
| foundGeneratedFlag = wasGenerated(member.getSource(), endCheckIndex); |
| } catch (JavaModelException exc) { |
| throw new MergeException(exc); |
| } |
| return foundGeneratedFlag; |
| } |
| } |