Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 249301 Details for
Bug 432147
[refactoring] Extract Constant displays error message on name of local variable
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Patch 3 with initializer block improvements from review
patch3.patch (text/plain), 20.45 KB, created by
Timo Kinnunen
on 2014-12-09 17:11:10 EST
(
hide
)
Description:
Patch 3 with initializer block improvements from review
Filename:
MIME Type:
Creator:
Timo Kinnunen
Created:
2014-12-09 17:11:10 EST
Size:
20.45 KB
patch
obsolete
>diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/PromoteTempToFieldRefactoring.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/PromoteTempToFieldRefactoring.java >index 774f96e..56687ce 100644 >--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/PromoteTempToFieldRefactoring.java >+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/PromoteTempToFieldRefactoring.java >@@ -2,14 +2,15 @@ > * Copyright (c) 2000, 2014 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: >+ * Timo Kinnunen - Contribution for bug 432147 - [refactoring] Extract Constant displays error message on name of local variable > * IBM Corporation - initial API and implementation > *******************************************************************************/ > package org.eclipse.jdt.internal.corext.refactoring.code; > > import java.util.ArrayList; > import java.util.Arrays; > import java.util.HashMap; >@@ -52,14 +53,15 @@ > import org.eclipse.jdt.core.dom.Expression; > import org.eclipse.jdt.core.dom.FieldDeclaration; > import org.eclipse.jdt.core.dom.IBinding; > import org.eclipse.jdt.core.dom.IExtendedModifier; > import org.eclipse.jdt.core.dom.IMethodBinding; > import org.eclipse.jdt.core.dom.ITypeBinding; > import org.eclipse.jdt.core.dom.IVariableBinding; >+import org.eclipse.jdt.core.dom.Initializer; > import org.eclipse.jdt.core.dom.Javadoc; > import org.eclipse.jdt.core.dom.MethodDeclaration; > import org.eclipse.jdt.core.dom.Modifier; > import org.eclipse.jdt.core.dom.SimpleName; > import org.eclipse.jdt.core.dom.Statement; > import org.eclipse.jdt.core.dom.SwitchStatement; > import org.eclipse.jdt.core.dom.Type; >@@ -122,14 +124,15 @@ > > //------ settings ---------// > private String fFieldName; > private int fVisibility; /*see Modifier*/ > private boolean fDeclareStatic; > private boolean fDeclareFinal; > private int fInitializeIn; /*see INITIALIZE_IN_* constraints */ >+ private boolean fInitializeAsConstantIfPossible= false; > > //------ fields used for computations ---------// > private CompilationUnit fCompilationUnitNode; > private VariableDeclaration fTempDeclarationNode; > //------ analysis ---------// > private boolean fInitializerUsesLocalTypes; > private boolean fTempTypeUsesClassTypeVariables; >@@ -253,37 +256,50 @@ > } > > public boolean canEnableSettingFinal(){ > if (fInitializeIn == INITIALIZE_IN_CONSTRUCTOR) > return canEnableSettingDeclareInConstructors() && ! tempHasAssignmentsOtherThanInitialization(); > else if (fInitializeIn == INITIALIZE_IN_FIELD) > return canEnableSettingDeclareInFieldDeclaration() && ! tempHasAssignmentsOtherThanInitialization(); >- else if (getMethodDeclaration().isConstructor()) >+ else if (isDeclaredInConstructor() || isDeclaredInInitializer()) > return !tempHasAssignmentsOtherThanInitialization(); > else > return false; > } > > private boolean tempHasAssignmentsOtherThanInitialization() { > TempAssignmentFinder assignmentFinder= new TempAssignmentFinder(fTempDeclarationNode); > fCompilationUnitNode.accept(assignmentFinder); > return assignmentFinder.hasAssignments(); > } > > public boolean canEnableSettingDeclareInConstructors(){ > return ! fDeclareStatic && > ! fInitializerUsesLocalTypes && >- ! getMethodDeclaration().isConstructor() && >+ ! isDeclaredInConstructor() && > ! isDeclaredInAnonymousClass() && > ! isTempDeclaredInStaticMethod() && > tempHasInitializer(); > } > >+ private boolean isDeclaredInConstructor() { >+ BodyDeclaration methodDeclaration= getBodyDeclaration(); >+ if(methodDeclaration instanceof MethodDeclaration) { >+ return ((MethodDeclaration) methodDeclaration).isConstructor(); >+ } >+ return false; >+ } >+ >+ private boolean isDeclaredInInitializer() { >+ BodyDeclaration initializerDeclaration= getBodyDeclaration(); >+ return initializerDeclaration instanceof Initializer; >+ } >+ > public boolean canEnableSettingDeclareInMethod(){ >- return ! fDeclareFinal && >+ return (! fDeclareFinal || isDeclaredInInitializer()) && > tempHasInitializer(); > } > private boolean tempHasInitializer() { > return getTempInitializer() != null; > } > > public boolean canEnableSettingDeclareInFieldDeclaration(){ >@@ -291,19 +307,19 @@ > } > > private Expression getTempInitializer() { > return fTempDeclarationNode.getInitializer(); > } > > private boolean isTempDeclaredInStaticMethod() { >- return Modifier.isStatic(getMethodDeclaration().getModifiers()); >+ return Modifier.isStatic(getBodyDeclaration().getModifiers()); > } > >- private MethodDeclaration getMethodDeclaration(){ >- return (MethodDeclaration)ASTNodes.getParent(fTempDeclarationNode, MethodDeclaration.class); >+ private BodyDeclaration getBodyDeclaration(){ >+ return (BodyDeclaration)ASTNodes.getParent(fTempDeclarationNode, BodyDeclaration.class); > } > > private boolean isDeclaredInAnonymousClass() { > return null != ASTNodes.getParent(fTempDeclarationNode, AnonymousClassDeclaration.class); > } > > /* >@@ -318,15 +334,15 @@ > return result; > > initAST(pm); > > if (fTempDeclarationNode == null) > return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.PromoteTempToFieldRefactoring_select_declaration); > >- if (! Checks.isDeclaredIn(fTempDeclarationNode, MethodDeclaration.class)) >+ if (! Checks.isDeclaredIn(fTempDeclarationNode, MethodDeclaration.class) && !Checks.isDeclaredIn(fTempDeclarationNode, Initializer.class) ) > return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.PromoteTempToFieldRefactoring_only_declared_in_methods); > > if (isMethodParameter()) > return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.PromoteTempToFieldRefactoring_method_parameters); > > if (isTempAnExceptionInCatchBlock()) > return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.PromoteTempToFieldRefactoring_exceptions); >@@ -344,22 +360,31 @@ > if (!fSelfInitializing) > initializeDefaults(); > return result; > } > > private void initializeDefaults() { > fVisibility= Modifier.PRIVATE; >- fDeclareStatic= Modifier.isStatic(getMethodDeclaration().getModifiers()); >- fDeclareFinal= false; >- if (canEnableSettingDeclareInMethod()) >- fInitializeIn= INITIALIZE_IN_METHOD; >- else if (canEnableSettingDeclareInFieldDeclaration()) >- fInitializeIn= INITIALIZE_IN_FIELD; >- else if (canEnableSettingDeclareInConstructors()) >- fInitializeIn= INITIALIZE_IN_CONSTRUCTOR; >+ fDeclareStatic= Modifier.isStatic(getBodyDeclaration().getModifiers()); >+ if (fInitializeAsConstantIfPossible) { >+ if(canEnableSettingDeclareInFieldDeclaration()) >+ fInitializeIn= INITIALIZE_IN_FIELD; >+ else if (canEnableSettingDeclareInMethod()) >+ fInitializeIn= INITIALIZE_IN_METHOD; >+ else if (canEnableSettingDeclareInConstructors()) >+ fInitializeIn= INITIALIZE_IN_CONSTRUCTOR; >+ } else { >+ if (canEnableSettingDeclareInMethod()) >+ fInitializeIn= INITIALIZE_IN_METHOD; >+ else if (canEnableSettingDeclareInFieldDeclaration()) >+ fInitializeIn= INITIALIZE_IN_FIELD; >+ else if (canEnableSettingDeclareInConstructors()) >+ fInitializeIn= INITIALIZE_IN_CONSTRUCTOR; >+ } >+ fDeclareFinal= fInitializeAsConstantIfPossible && canEnableSettingFinal(); > } > > public String[] guessFieldNames() { > String rawTempName= StubUtility.getBaseName(fTempDeclarationNode.resolveBinding(), fCu.getJavaProject()); > String[] excludedNames= getNamesOfFieldsInDeclaringType(); > int dim= ASTNodes.getDimensions(fTempDeclarationNode); > return StubUtility.getFieldNameSuggestions(fCu.getJavaProject(), rawTempName, dim, getModifiers(), excludedNames); >@@ -397,15 +422,15 @@ > } > > private void checkTempInitializerForLocalTypeUsage() { > Expression initializer= fTempDeclarationNode.getInitializer(); > if (initializer == null) > return; > >- IMethodBinding declaringMethodBinding= getMethodDeclaration().resolveBinding(); >+ IMethodBinding declaringMethodBinding= getMethodBinding(); > ITypeBinding[] methodTypeParameters= declaringMethodBinding == null ? new ITypeBinding[0] : declaringMethodBinding.getTypeParameters(); > LocalTypeAndVariableUsageAnalyzer localTypeAnalyer= new LocalTypeAndVariableUsageAnalyzer(methodTypeParameters); > initializer.accept(localTypeAnalyer); > fInitializerUsesLocalTypes= ! localTypeAnalyer.getUsageOfEnclosingNodes().isEmpty(); > } > > private RefactoringStatus checkTempTypeForLocalTypeUsage(){ >@@ -413,24 +438,29 @@ > if (vds == null) > return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.PromoteTempToFieldRefactoring_cannot_promote); > Type type= vds.getType(); > ITypeBinding binding= type.resolveBinding(); > if (binding == null) > return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.PromoteTempToFieldRefactoring_cannot_promote); > >- IMethodBinding declaringMethodBinding= getMethodDeclaration().resolveBinding(); >+ IMethodBinding declaringMethodBinding= getMethodBinding(); > ITypeBinding[] methodTypeParameters= declaringMethodBinding == null ? new ITypeBinding[0] : declaringMethodBinding.getTypeParameters(); > LocalTypeAndVariableUsageAnalyzer analyzer= new LocalTypeAndVariableUsageAnalyzer(methodTypeParameters); > type.accept(analyzer); > boolean usesLocalTypes= ! analyzer.getUsageOfEnclosingNodes().isEmpty(); > fTempTypeUsesClassTypeVariables= analyzer.getClassTypeVariablesUsed(); > if (usesLocalTypes) > return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.PromoteTempToFieldRefactoring_uses_type_declared_locally); > return null; > } >+ >+ private IMethodBinding getMethodBinding() { >+ BodyDeclaration methodDeclaration= getBodyDeclaration(); >+ return methodDeclaration != null && methodDeclaration instanceof MethodDeclaration ? ((MethodDeclaration) methodDeclaration).resolveBinding() : null; >+ } > > private VariableDeclarationStatement getTempDeclarationStatement() { > return (VariableDeclarationStatement) ASTNodes.getParent(fTempDeclarationNode, VariableDeclarationStatement.class); > } > > private boolean isTempAnExceptionInCatchBlock() { > return (fTempDeclarationNode.getParent() instanceof CatchClause); >@@ -466,15 +496,15 @@ > pm.done(); > } > } > > private RefactoringStatus checkClashesInConstructors() { > Assert.isTrue(fInitializeIn == INITIALIZE_IN_CONSTRUCTOR); > Assert.isTrue(!isDeclaredInAnonymousClass()); >- final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) getMethodDeclaration().getParent(); >+ final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) getBodyDeclaration().getParent(); > if (declaration instanceof TypeDeclaration) { > MethodDeclaration[] methods= ((TypeDeclaration) declaration).getMethods(); > for (int i= 0; i < methods.length; i++) { > MethodDeclaration method= methods[i]; > if (!method.isConstructor()) > continue; > NameCollector nameCollector= new NameCollector(method) { >@@ -509,15 +539,15 @@ > } > } > } > return null; > } > > private FieldDeclaration[] getFieldDeclarations() { >- List<BodyDeclaration> bodyDeclarations= ASTNodes.getBodyDeclarations(getMethodDeclaration().getParent()); >+ List<BodyDeclaration> bodyDeclarations= ASTNodes.getBodyDeclarations(getBodyDeclaration().getParent()); > List<FieldDeclaration> fields= new ArrayList<FieldDeclaration>(1); > for (Iterator<BodyDeclaration> iter= bodyDeclarations.iterator(); iter.hasNext();) { > Object each= iter.next(); > if (each instanceof FieldDeclaration) > fields.add((FieldDeclaration) each); > } > return fields.toArray(new FieldDeclaration[fields.size()]); >@@ -575,15 +605,15 @@ > rewrite.replace(occurence, newName, null); > } > } > } > > private void addInitializersToConstructors(ASTRewrite rewrite) throws CoreException { > Assert.isTrue(! isDeclaredInAnonymousClass()); >- final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration)getMethodDeclaration().getParent(); >+ final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration)getBodyDeclaration().getParent(); > final MethodDeclaration[] constructors= getAllConstructors(declaration); > if (constructors.length == 0) { > AST ast= rewrite.getAST(); > MethodDeclaration newConstructor= ast.newMethodDeclaration(); > newConstructor.setConstructor(true); > newConstructor.modifiers().addAll(ast.newModifiers(declaration.getModifiers() & ModifierRewrite.VISIBILITY_MODIFIERS)); > newConstructor.setName(ast.newSimpleName(declaration.getName().getIdentifier())); >@@ -817,15 +847,15 @@ > rewrite.remove(fragment, null); > if (fragments.size() == 1) > rewrite.remove(tempDeclarationStatement, null); > } > > private void addFieldDeclaration(ASTRewrite rewrite) { > FieldDeclaration[] fields= getFieldDeclarations(); >- ASTNode parent= getMethodDeclaration().getParent(); >+ ASTNode parent= getBodyDeclaration().getParent(); > ChildListPropertyDescriptor descriptor= ASTNodes.getBodyDeclarationsProperty(parent); > int insertIndex; > if (fields.length == 0) > insertIndex= 0; > else > insertIndex= ASTNodes.getBodyDeclarations(parent).indexOf(fields[fields.length - 1]) + 1; > >@@ -979,8 +1009,12 @@ > return new RefactoringStatus(); > } > > > public void setLinkedProposalModel(LinkedProposalModel model) { > fLinkedProposalModel= model; > } >+ >+ public void setInitializeAsConstantIfPossible(boolean value) { >+ fInitializeAsConstantIfPossible = value; >+ } > } >diff --git a/org.eclipse.jdt.ui/ui refactoring/org/eclipse/jdt/internal/ui/refactoring/refactoringui.properties b/org.eclipse.jdt.ui/ui refactoring/org/eclipse/jdt/internal/ui/refactoring/refactoringui.properties >index 0291a09..9d72a98 100644 >--- a/org.eclipse.jdt.ui/ui refactoring/org/eclipse/jdt/internal/ui/refactoring/refactoringui.properties >+++ b/org.eclipse.jdt.ui/ui refactoring/org/eclipse/jdt/internal/ui/refactoring/refactoringui.properties >@@ -134,15 +134,15 @@ > PullUpInputPage_pull_up1=Pull Up Methods > PullUpInputPage_exception=An unexpected exception occurred. See the error log for more details > > ExtractTempAction_label=Extract &Local Variable... > ExtractTempAction_extract_temp=Extract Local Variable > > ConvertLocalToField_label=Con&vert Local Variable to Field... >-ConvertLocalToField_title=Convert Local Variable to Field >+ConvertLocalToField_title=Convert Local Variable to Field or Constant > > ExtractConstantAction_label=Extr&act Constant... > ExtractSuperTypeAction_label=Ex&tract Superclass... > ExtractConstantAction_extract_constant=Extract Constant > > InlineTempAction_inline_temp=Inline Local Variable > InlineTempAction_label=&Inline Local Variable... >@@ -317,15 +317,15 @@ > MoveInstanceMethodPage_Method_name=New &method name: > MoveInstanceMethodPage_New_receiver=&New target for ''{0}'': > MoveInstanceMethodPage_Receiver=Receiver > MoveInstanceMethodPage_Type=Type > MoveInstanceMethodPage_invalid_target=Target ''{0}'' is used in an assignment. > > PromoteTempInputPage_Field_declaration=Field decla&ration >-PromoteTempInputPage_Current_method=&Current method >+PromoteTempInputPage_Current_method=&Current block > PromoteTempInputPage_constructors=C&lass constructors > PromoteTempInputPage_Field_name=F&ield name: > PromoteTempInputPage_Initialize=Initialize in > PromoteTempInputPage_declare_static=&Declare field as \'static\' > PromoteTempInputPage_declare_final=Decl&are field as \'final\' > > UseSupertypeInputPage_Select_supertype=Select the supertype to use >diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/actions/ExtractConstantAction.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/actions/ExtractConstantAction.java >index ff6a4c8..41fa011 100644 >--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/actions/ExtractConstantAction.java >+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/actions/ExtractConstantAction.java >@@ -2,33 +2,49 @@ > * Copyright (c) 2000, 2011 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: >+ * Timo Kinnunen - Contribution for bug 432147 - [refactoring] Extract Constant displays error message on name of local variable > * IBM Corporation - initial API and implementation > *******************************************************************************/ > package org.eclipse.jdt.ui.actions; > > import org.eclipse.jface.text.ITextSelection; > > import org.eclipse.ui.PlatformUI; > >+import org.eclipse.jdt.core.ICompilationUnit; >+import org.eclipse.jdt.core.JavaModelException; >+import org.eclipse.jdt.core.SourceRange; >+import org.eclipse.jdt.core.dom.ASTNode; >+import org.eclipse.jdt.core.dom.CompilationUnit; >+import org.eclipse.jdt.core.dom.SimpleName; >+import org.eclipse.jdt.core.dom.VariableDeclaration; >+ >+import org.eclipse.jdt.internal.corext.dom.fragments.ASTFragmentFactory; >+import org.eclipse.jdt.internal.corext.dom.fragments.IASTFragment; > import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester; > import org.eclipse.jdt.internal.corext.refactoring.code.ExtractConstantRefactoring; >+import org.eclipse.jdt.internal.corext.refactoring.code.PromoteTempToFieldRefactoring; >+import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; >+import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; > > import org.eclipse.jdt.ui.refactoring.RefactoringSaveHelper; > > import org.eclipse.jdt.internal.ui.IJavaHelpContextIds; >+import org.eclipse.jdt.internal.ui.JavaPlugin; > import org.eclipse.jdt.internal.ui.actions.ActionUtil; > import org.eclipse.jdt.internal.ui.actions.SelectionConverter; > import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; > import org.eclipse.jdt.internal.ui.javaeditor.JavaTextSelection; > import org.eclipse.jdt.internal.ui.refactoring.ExtractConstantWizard; >+import org.eclipse.jdt.internal.ui.refactoring.PromoteTempWizard; > import org.eclipse.jdt.internal.ui.refactoring.RefactoringMessages; > import org.eclipse.jdt.internal.ui.refactoring.actions.RefactoringStarter; > > /** > * Extracts an expression into a constant field and replaces all occurrences of > * the expression with the new constant. > * >@@ -80,11 +96,33 @@ > /* (non-Javadoc) > * Method declared on SelectionDispatchAction > */ > @Override > public void run(ITextSelection selection) { > if (!ActionUtil.isEditable(fEditor)) > return; >- ExtractConstantRefactoring refactoring= new ExtractConstantRefactoring(SelectionConverter.getInputAsCompilationUnit(fEditor), selection.getOffset(), selection.getLength()); >+ ICompilationUnit unit= SelectionConverter.getInputAsCompilationUnit(fEditor); >+ CompilationUnit cuNode= RefactoringASTParser.parseWithASTProvider(unit, true, null); >+ int selectionStart= selection.getOffset(); >+ int selectionLength= selection.getLength(); >+ ExtractConstantRefactoring refactoring= new ExtractConstantRefactoring(cuNode, selectionStart, selectionLength); >+ try { >+ CompilationUnitRewrite cuRewrite= new CompilationUnitRewrite(unit, cuNode); >+ SourceRange range= new SourceRange(selectionStart, selectionLength); >+ IASTFragment ast= ASTFragmentFactory.createFragmentForSourceRange(range, cuRewrite.getRoot(), unit); >+ ASTNode node= ast.getAssociatedNode(); >+ if (node instanceof SimpleName && node.getParent() instanceof VariableDeclaration) { >+ ICompilationUnit cunit= SelectionConverter.getInputAsCompilationUnit(fEditor); >+ PromoteTempToFieldRefactoring refactoring2= new PromoteTempToFieldRefactoring(cunit, selection.getOffset(), selection.getLength()); >+ refactoring2.setDeclareFinal(true); >+ refactoring2.setDeclareStatic(true); >+ refactoring2.setFieldName(refactoring.guessConstantName()); >+ refactoring2.setInitializeAsConstantIfPossible(true); >+ new RefactoringStarter().activate(new PromoteTempWizard(refactoring2), getShell(), RefactoringMessages.ConvertLocalToField_title, RefactoringSaveHelper.SAVE_NOTHING); >+ return; >+ } >+ } catch (JavaModelException e) { >+ JavaPlugin.log(e); >+ } > new RefactoringStarter().activate(new ExtractConstantWizard(refactoring), getShell(), RefactoringMessages.ExtractConstantAction_extract_constant, RefactoringSaveHelper.SAVE_NOTHING); > } > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 432147
:
242929
|
244026
| 249301