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 */ 017package org.apache.wicket; 018 019import java.util.Locale; 020 021import org.apache.wicket.util.string.Strings; 022 023/** 024 * An implementation of IMarkupIdGenerator that uses the Session to generate 025 * sequence numbers for the component markup ids. 026 * As a prefix for the generated markup id in development mode it uses the component id 027 * and in production mode the string <em>id</em>. 028 */ 029public class DefaultMarkupIdGenerator implements IMarkupIdGenerator 030{ 031 @Override 032 public String generateMarkupId(Component component, boolean createIfDoesNotExist) 033 { 034 Object storedMarkupId = component.getMarkupIdImpl(); 035 if (storedMarkupId instanceof String) 036 { 037 return (String)storedMarkupId; 038 } 039 040 if (storedMarkupId == null && createIfDoesNotExist == false) 041 { 042 return null; 043 } 044 045 Session session = component.getSession(); 046 int generatedMarkupId = storedMarkupId instanceof Integer ? (Integer)storedMarkupId 047 : session.nextSequenceValue(); 048 049 if (generatedMarkupId == 0xAD) 050 { 051 // WICKET-4559 skip suffix 'ad' because some ad-blocking solutions may hide the component 052 generatedMarkupId = session.nextSequenceValue(); 053 } 054 055 if (storedMarkupId == null) 056 { 057 component.setMarkupIdImpl(generatedMarkupId); 058 } 059 060 String markupIdPrefix = "id"; 061 if (component.getApplication().usesDevelopmentConfig()) 062 { 063 // in non-deployment mode we make the markup id include component id 064 // so it is easier to debug 065 markupIdPrefix = component.getId(); 066 } 067 068 String markupIdPostfix = Integer.toHexString(generatedMarkupId).toLowerCase(Locale.ROOT); 069 070 String markupId = markupIdPrefix + markupIdPostfix; 071 072 // make sure id is compliant with w3c requirements (starts with a letter) 073 char c = markupId.charAt(0); 074 if (!Character.isLetter(c)) 075 { 076 markupId = "id" + markupId; 077 } 078 079 // escape some noncompliant characters 080 markupId = Strings.replaceAll(markupId, "_", "__").toString(); 081 markupId = markupId.replace('.', '_'); 082 markupId = markupId.replace('-', '_'); 083 markupId = markupId.replace(' ', '_'); 084 085 return markupId; 086 } 087}